Заранее спасибо.
AVR studio в вопросах и ответах
Подскажите, пожалуйста, имеется ли в АВР-студии возможность эмулировать работу МК при заданных осцилограммах напряжений на его входах? То есть я программирую МК так, чтобы он вёл себя определённым образом при подаче на вход определённых сигналов, и хочу это проверить перед прошивкой. Я знаю, что в АВР-студии можно во время дебагинга выставлять мышкой значения логических входов МК. Но, поскольку входные сигналы имеют длину в тысячи тактов МК, проделать такую проверку пологаясь только на брэйкпоинты и мышку не представляется возможным. Кроме того, желательно, чтобы эмулировалась работа переферийных устройств, в частности компаратора (поскольку именно на него будет подаваться аналоговый сигнал). Подскажите, чем можно воспользоваться, если в AVR Studio нет такой возможности.
Заранее спасибо.
Заранее спасибо.
- Реклама
Доброго всем дня! Пишу один простенький код под тиньку13 но он почему то не хочет работать не в протеусе не в железке, симулятор студии работает нормально...
Код следующий:
Понимаю что код ужасный но очень нужна помощь, месяц убил на него а он не работает толком. Ошибки выбиваются при работе с кнопками, а именно при вызове макроса POW_ON.
протеус говорит на это:
железка просто молчит
Заранее благодарен
Код следующий:
Спойлер
Код: Выделить всё
#define F_CPU 128000L
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <avr/sfr_defs.h>
#define AMP bit_is_set(PINB,0)
#define POW bit_is_set(PINB,1)
#define TIMER bit_is_set(PINB,2)
#define TIMERSTOP (POW && TIMER)
#define LED_ON PORTB |= _BV(PB5)
#define LED_OFF PORTB &= ~_BV(PB5)
#define POW_ON PORTB = 0x10
#define POW_OFF PORTB = 0x20
#define AMP_ON PORTB |= _BV(PB3)
#define AMP_OFF PORTB &= ~_BV(PB3)
#define AMP_S(state) if(state){AMP_ON;}else{AMP_OFF;}
volatile unsigned int countdown = 0;
volatile bool isTIMER = false;
volatile bool isAMP = false;
volatile bool isON = false;
void timer_enable(void)
{
TCCR0B |= (1<<CS02) | (1<<CS00); //clock/1024
TCNT0 = 7;//Timer value;
isTIMER = true;
}
void timer_disable(void)
{
TCCR0B |= (0<<CS02) | (0<<CS00); //timer stopped
isTIMER = false;
}
void power_off(void)
{
timer_disable();
isAMP = false;
isON = false;
}
ISR(TIM0_OVF_vect)
{
if(PORTB&0x20)
{
LED_OFF;
}
else
{
LED_ON;
}
countdown -= 2;
if(countdown == 0)
{
power_off();
}
TCNT0 = 7;//Timer value;
}
void config(void)
{
DDRB = 0x38;
PORTB = 0x20;
TIMSK0 = 0x02;
}
int main(void)
{
config();
asm("sei");
while(1)
{
if(TIMERSTOP && isON)
{
_delay_ms(20);
if(TIMERSTOP)
{
timer_disable();
countdown = 0;
}
}
else if(TIMER && isON)
{
_delay_ms(20);
if(TIMER)
{
if(!isTIMER)
{
timer_enable();
}
countdown += 30;
}
}
else if(AMP && isON)
{
_delay_ms(50);
if(AMP)
{
isAMP = !isAMP;
AMP_S(isAMP);
}
}
else if(POW)
{
_delay_ms(20);
if(POW)
{
if(isON)
{
power_off();
}
else
{
isON = true;
POW_ON;
}
}
}
_delay_ms(100);
}
}
протеус говорит на это:
Спойлер
Заранее благодарен
Какая же это работа с кнопками? Такое происходит когда в схеме происходят очень быстрые процессы, тогда модель математически распадается(появляются такие ситуации как деление на ноль, бесконечные величины и т.д.) и невозможно что-либо далее рассчитать. В данном случае, не пытайтесь в симулятор ввести ВСЮ схему - только те части которые необходимо симулировать, остальную часть схемы заменить математическим эквивалентом или просто выбросить.
У вас там наверняка есть и силовые ключи и трансформатор... эти элементы не нужны для отладки программы, именно они и приводят к таким последствиям.
У вас там наверняка есть и силовые ключи и трансформатор... эти элементы не нужны для отладки программы, именно они и приводят к таким последствиям.
Да, вы правы, есть полевики и реле, но почему тогда в железе не работает?
На этот вопрос существует миллион ответов. искать их непродуктивно. Проще ответить на вопрос почему оно ДОЛЖНО работать, обычно на этот вопрос ответов не так уж много. Попробуйте подойти к решению проблемы именно с этой стороны.
- Реклама
В протеусе заработало после упрощения схемы, нашлось пару мелких недочетов, проверю на железе теперь) Спасибо Вам огромное 
Можно, но только лог. "1" и "0".B@R5uk писал(а):Подскажите, пожалуйста, имеется ли в АВР-студии возможность эмулировать работу МК при заданных осцилограммах напряжений на его входах?
Симулятор опшионс — стимули энд логгинг — стимули: подгружаете файл, который будет воздействовать на соотв. порт.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Но бывает полезней к студии подключить протеус в качестве удаленного отладчика(вообще поидее наоборот, это студия подключается к протеусу в качестве удаленного отладчика, но загружает его в своё окно). Правда, протеус тогда может помещаться только в пределах главного окна студии, что не всегда удобно...
Gudd-Head, подскажите, пожалуйста, где можно прочитать про формат файлов *.sti или про то, какой программой их можно создать?
вот здесь можно прочитать: http://www.simple-devices.ru/attachment ... 8-2010.pdfB@R5uk писал(а):где можно прочитать про формат файлов *.sti или про то, какой программой их можно создать?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
ARV, Gudd-Head, спасибо вам преогромнейшее, вы не представляете, как мне помогли. Отладил таки свою подпрограмму приёма сигнала. Оно даже в железе заработало. Замутил тут хитрую систему, позволяющую передавать данные из программы на ноутбуке в микроконтроллер через звуковой выход путём модуляции по типу спектрумовского сохранения на кассету. Если кто в курсе, тот поймёт. Программа -- жесть, жёсткие тайминги, привязка к скорости выполнения каждой комманды МК, длительность каждого цикла и каждого пути по всем ветвлениям процедуры пришлось рассчитать.
Это, вероятно, просто признак неправильного подхода к задаче. "спектрум" будучи более медлительным и тот справлялся замечательно с этой задачей, а у вас пришлось все жестко рассчитывать. Или скорости огромные? да вроде же звуковой тракт...
Я в своё время разбирался с его программой. Там во-первых у процессора набор инструкций более удобный, во-вторых, спектрум работает на частоте 3,5 МГц, а мой МК сейчас от встроенного 1 МГц-вого генератора, в третьих, если мне не изменяет память, то там тоже много рабочих констант, то есть всё жёстко рассчитано.Alexeyslav писал(а):Это, вероятно, просто признак неправильного подхода к задаче. "спектрум" будучи более медлительным и тот справлялся замечательно с этой задачей, а у вас пришлось все жестко рассчитывать. Или скорости огромные? да вроде же звуковой тракт...
Впрочем, вот моя программа, может посоветуете, что можно улучшить (только не советуйте всё переделать через прерывания -- я пока всех тонкостей не знаю):
Спойлер
Код: Выделить всё
.include "tn26def.inc"
cli ; Отмена прерываний
ldi r16, 0x7F ; Порт А -- выход, кроме
out DDRA, r16 ; самого старшего бита
ldi r16, 0x40 ; Порт Б -- вход, кроме
out DDRB, r16 ; бита 6
ldi r16, 1<<ACBG ; Положительный вход комаратора
out ACSR, r16 ; подключить к внутренним 1.18В
ldi r16, 0xDF ; Инициализация
out SP, r16 ; стека
loop: ldi r26, 0x60 ; Инициализация
ldi r27, 0x00 ; указателя X
ld r16, X ; Загрузка прочитанного байта из памяти
bst r16, 7 ; Сохранение старшего бита
andi r16, 0x7F ; Маска выхода
out PORTA, r16 ; Вывод младших 7-и битов в прот А
ser r16 ; Подтяжка неиспользуемых выходов
bld r16, 6 ; Подготовка вывода
out PORTB, r16 ; Вывод старшего 8-го бита
ldi r16, 0x01 ; Количество принимаемых байт
rcall rsvr_begin ; Вызов процедуры приёма данных
rjmp loop ; Рабочий цикл
;==============
; Процедура принятия данных
;==============
.def btcnt = r16
.def lstat = r17
.def temp = r18
.def lpcnt = r19
.def plcnt = r20
.def flcnt = r21
.def rslt = r21
;.equ INPRT = PINB
.equ INPRT = ACSR
; Регистры, используемые на этапе синхронизации:
; - lstat
; - lpcnt
; - plcnt
; - temp
; - flcnt
; Регистры, используемые в процессе считывания:
; - btcnt (передаётся в процедуру из программы)
; - X (R27:R26) (передаётся в процедуру из программы)
; - lstat (инициализируется на этапе синхронизации)
; - lpcnt
; - plcnt
; - temp
; - rslt
; Инициализация
rsvr_begin: ldi flcnt, 0x10 ; Допустимое число ошибок синхронизации
in lstat, INPRT ; Чтение линии
rsvr_afrsh: ldi plcnt, 0x08 ; Минимальное число синхроимпульсов
; Ожидание переключения с таймаутом
ldi lpcnt, 0x28 ; Допустимое время ожидания смены сигнала
rsvr_wait_1: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
brne rsvr_chng_1 ; Если значение изменилось переход к задержке
dec lpcnt ; Уменьшить допустимое время ожидания
brne rsvr_wait_1 ; Если время не вышло, продолжить ожидание
; Обработка таймаута
rsvr_timeout: dec flcnt ; Уменьшить допустимое число ошибок
brne rsvr_afrsh ; Если лимит ошибок не достигнут, продолжить
rjmp rsvr_end ; Иначе, закончить процедуру
; Мёртвое время после переключения
rsvr_chng_1: ldi lpcnt, 0x05 ; Инициализация задержки
rsvr_revsl: com lstat ; Инвертировать запомненное состояние линии
rsvr_dtm_1: dec lpcnt ; Уменьшить время задержки
brne rsvr_dtm_1 ; Повторить, если время не вышло
; Ожидание переключения с таймаутом
ldi lpcnt, 0x25 ; Допустимое время ожидания смены сигнала
rsvr_wait_2: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
brne rsvr_chck_1 ; Если уровень изменился, переход к проверкам
dec lpcnt ; Уменьшить допустимое время ожидания
brne rsvr_wait_2 ; Если время не вышло, продолжить ожидание
rjmp rsvr_timeout ; Иначе, переход к обработке таймаута
; Проверка длительности импульса
rsvr_chck_1: cpi lpcnt, 0x0D ; Сравнить оставшееся время с порогом
brcc rsvr_chck_2 ; Если не синхроимпульс, ко второй проверке
subi plcnt, 0x01 ; Уменьшить необходимое число синхроимпульсов
brcc rsvr_skip_1 ; Если заёма нет, то пропуск
clr plcnt ; отмены вычитания
rsvr_skip_1: ldi lpcnt, 0x03 ; Инициализация задержки
rjmp rsvr_revsl ; Переход к задержке
; Проверка возможности перехода к считыванию
rsvr_chck_2: tst plcnt ; Проверка необходимого числа синхроимпульсов
breq rsvr_rdng ; Если достаточно, то к процедуре считывания
dec flcnt ; Уменьшить допустимое число ошибок
breq rsvr_end ; Если лимит попыток достигнут, закончить
ldi plcnt, 0x08 ; Минимальное число синхроимпульсов
ldi lpcnt, 0x03 ; Инициализация задержки
rjmp rsvr_revsl ; Переход к задержке
; Процедура считывания данных
rsvr_rdng: ldi lpcnt, 0x05 ; Инициализация задержки
com lstat
rsvr_btinit: ldi rslt, 0x80 ; Инициализация принимаемого байта
; Мёртвое время после последней операции
rsvr_dtm_2: dec lpcnt ; Уменьшить время задержки
brne rsvr_dtm_2 ; Повторить, если время не вышло
; Ожидание переключения с таймаутом
ldi lpcnt, 0x0B ; Допустимое время ожидания смены сигнала
rsvr_wait_3: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
brne rsvr_chng_2 ; Если значение изменилось переход к задержке
dec lpcnt ; Уменьшить допустимое время ожидания
brne rsvr_wait_3 ; Если время не вышло, продолжить ожидание
rjmp rsvr_end ; Иначе, закончить процедуру
; Задержка перед считыванием
rsvr_chng_2: ldi lpcnt, 0x11 ; Инициализация задержки перед считыванием
rsvr_dtm_3: dec lpcnt ; Уменьшить время задержки
brne rsvr_dtm_3 ; Повторить, если время не вышло
; Процедура считывания
ldi plcnt, 0x00 ; Инициализация числа чтений нулевго бита
; Счёт по низкому уровню
ldi lpcnt, 0x08 ; Инициализация числа чтений низкого уровня
rsvr_read_1: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
breq rsvr_skip_2 ; Если прочитана единица, то пропустить
inc plcnt ; инремент числа чтений нулевого бита
rsvr_skip_2: dec lpcnt ; Уменьшить необходимое число чтений
brne rsvr_read_1 ; Если чтения не исчерпаны, повторить
; Счёт по высокому уровню
ldi lpcnt, 0x08 ; Инициализация числа чтений высокого уровня
rsvr_read_2: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
brne rsvr_skip_3 ; Если прочитан ноль, то пропустить
inc plcnt ; инремент числа чтений нулевого бита
rsvr_skip_3: dec lpcnt ; Уменьшить необходимое число чтений
brne rsvr_read_2 ; Если чтения не исчерпаны, повторить
; Расшифровка принятого бита в читаемый байт
subi plcnt, 0x08 ; Сравнение числа нулевых чтений с порогом
ror rslt ; Сохранение бита в принимаемый байт
brcs rsvr_save ; Если байт готов, то сохранить его
ldi lpcnt, 0x06 ; Инициализация задержки
rjmp rsvr_dtm_2 ; Переход к задержке
; Сохранение байта
rsvr_save: st x+, rslt ; Запись байта в регистры/память
cpi r26, 0x10 ; Проверка выхода указателя за регистр R15
brne rsvr_skip_4 ; Если выхода нет, то пропустить
ldi r26, 0x60 ; перестановку указателя на память
rsvr_skip_4: cpi r26, 0xD8 ; Проверить наличие свободного места
breq rsvr_end ; Если место закончилось, закончить процедуру
dec btcnt ; Иначе, уменьшить количество читаемых байт
breq rsvr_end ; Если все байты приняты, закончить процедуру
ldi lpcnt, 0x02 ; Иначе, инициализация задержки
rjmp rsvr_dtm_2 ; Переход к задержке
; Конец
rsvr_end: ret
Частота процессора не показатель, на том процессоре который использовался в спектруме одна самая простая команда выполнялась 4 такта, а длинная - 12 тактов и более. Так что ресурс по скорости исполнения инструкций и того ниже.
Привязка к длительности импульса конечно очень проста, но такой способ передачи данных очень чувствителен к помехам, любой лишний импульс и все насмарку т.к. теряется синхронизация.
Проще было бы посмотреть в сторону передачи данных как это делается в UART, только появляется специфика - нестабильная скорость передачи/приема, которую я решил очень просто - передается всего 4 информационных бита в одной посылке, это дает нам нечувствительность к разнице скорости приема/передачи в 10%, перед началом передачи даётся импульс повышенной длительности по которому приемник определяет необходимую скорость передачи, подразумевая что во время передачи всего пакета частота тактирования существенно не изменится(более 10%).
У меня получилось таким способом выиграть еще 16% (+-8% отклонения скорсоти в обе стороны) на нестабильность скорости приема/передачи. У вас может получится и того больше.
Всё это я делал на фиксированной скорости 48Кбод = 4.8Мгц/100 контроллер после получения синхронизирующего импульса и коррекции скорости приема по нему просто считывал состояние порта каждые 100 тактов при помощи таймера - в остальное время контроллер не делал ничего критичного. Единственные узкие места - обеспечить минимальное время между концом первого импульса синхронизации и вычислением скорости приема по результатам измерения длительности импульса и алгоритм ожидания начала следующего импульса синхронизации перед каждой посылкой из 4-х бит, чтобы ликвидировать накапливающуюся ошибку скорости приема.
В данном случае, в случае помех может быть повреждены отдельные биты, но пакеты будут приняты несмотря ни на что. И эта проблема уже решается применением помехоустойчивых кодов на уровне выше. Но судя по тому что у вас сейчас все работает на наличие помех не жалуетесь.
Привязка к длительности импульса конечно очень проста, но такой способ передачи данных очень чувствителен к помехам, любой лишний импульс и все насмарку т.к. теряется синхронизация.
Проще было бы посмотреть в сторону передачи данных как это делается в UART, только появляется специфика - нестабильная скорость передачи/приема, которую я решил очень просто - передается всего 4 информационных бита в одной посылке, это дает нам нечувствительность к разнице скорости приема/передачи в 10%, перед началом передачи даётся импульс повышенной длительности по которому приемник определяет необходимую скорость передачи, подразумевая что во время передачи всего пакета частота тактирования существенно не изменится(более 10%).
У меня получилось таким способом выиграть еще 16% (+-8% отклонения скорсоти в обе стороны) на нестабильность скорости приема/передачи. У вас может получится и того больше.
Всё это я делал на фиксированной скорости 48Кбод = 4.8Мгц/100 контроллер после получения синхронизирующего импульса и коррекции скорости приема по нему просто считывал состояние порта каждые 100 тактов при помощи таймера - в остальное время контроллер не делал ничего критичного. Единственные узкие места - обеспечить минимальное время между концом первого импульса синхронизации и вычислением скорости приема по результатам измерения длительности импульса и алгоритм ожидания начала следующего импульса синхронизации перед каждой посылкой из 4-х бит, чтобы ликвидировать накапливающуюся ошибку скорости приема.
В данном случае, в случае помех может быть повреждены отдельные биты, но пакеты будут приняты несмотря ни на что. И эта проблема уже решается применением помехоустойчивых кодов на уровне выше. Но судя по тому что у вас сейчас все работает на наличие помех не жалуетесь.
3,5 МГц — это частота исполнения команд процессора Z80. А так то частота тактовых импульсов 14 МГц. Да, там есть команды, которые исполняются долго, но даже инкремент, декремент сдвоенного регистра по длительности равен команде NOP. Так что частота, всё-таки показатель.
На счёт стабильности приёма я в своей программе не задумывался вообще. Для меня тут было главное — простота кода и чтобы хоть как-то заработало. (Кстати, полноценные тесты ещё впереди). Тем, не менее, у меня в процессе приёма синхронизация происходит для каждого бита по спаду сигнала от предыдущего бита. В те моменты времени, когда в сигнале передаётся информация, процедура производит 16 чтений порта, результаты усредняются, и в конце подсчитывается итоговый результат. (Код перед вами — легко убедиться самому -- код с метки rsvr_read_1) Так что стабильность, думаю, достигается высокая (необходима ошибка синхронизации на 1/8 рабочего периода, (который равен 250 мкс), либо 50% сигнала в информационной области должно быть испорчено, чтобы результат получился неправильный).
На счёт таймера мысль была, но поскольку это моё первое знакомство с AVR вообще, я пока ещё не в курсе как, да чего. Изучение ещё только предстоит. Возможно, используя прерывания и таймер удастся сделать процедуру приёма сигнала в фоновом режиме, а не загружая весь МК работой. При моёй текущей частоте несущего сигнала, бит передаётся в течении 250 циклов МК, этого времени более чем достаточно для обсчёта. А если подключить кварц на 12 МГц, то расходовать 3000 операций на один бит данных — это уже будет перебор.
Ещё раз код, а то уехал.
На счёт стабильности приёма я в своей программе не задумывался вообще. Для меня тут было главное — простота кода и чтобы хоть как-то заработало. (Кстати, полноценные тесты ещё впереди). Тем, не менее, у меня в процессе приёма синхронизация происходит для каждого бита по спаду сигнала от предыдущего бита. В те моменты времени, когда в сигнале передаётся информация, процедура производит 16 чтений порта, результаты усредняются, и в конце подсчитывается итоговый результат. (Код перед вами — легко убедиться самому -- код с метки rsvr_read_1) Так что стабильность, думаю, достигается высокая (необходима ошибка синхронизации на 1/8 рабочего периода, (который равен 250 мкс), либо 50% сигнала в информационной области должно быть испорчено, чтобы результат получился неправильный).
На счёт таймера мысль была, но поскольку это моё первое знакомство с AVR вообще, я пока ещё не в курсе как, да чего. Изучение ещё только предстоит. Возможно, используя прерывания и таймер удастся сделать процедуру приёма сигнала в фоновом режиме, а не загружая весь МК работой. При моёй текущей частоте несущего сигнала, бит передаётся в течении 250 циклов МК, этого времени более чем достаточно для обсчёта. А если подключить кварц на 12 МГц, то расходовать 3000 операций на один бит данных — это уже будет перебор.
Ещё раз код, а то уехал.
Спойлер
Код: Выделить всё
.include "tn26def.inc"
cli ; Отмена прерываний
ldi r16, 0x7F ; Порт А -- выход, кроме
out DDRA, r16 ; самого старшего бита
ldi r16, 0x40 ; Порт Б -- вход, кроме
out DDRB, r16 ; бита 6
ldi r16, 1<<ACBG ; Положительный вход комаратора
out ACSR, r16 ; подключить к внутренним 1.18В
ldi r16, 0xDF ; Инициализация
out SP, r16 ; стека
loop: ldi r26, 0x60 ; Инициализация
ldi r27, 0x00 ; указателя X
ld r16, X ; Загрузка прочитанного байта из памяти
bst r16, 7 ; Сохранение старшего бита
andi r16, 0x7F ; Маска выхода
out PORTA, r16 ; Вывод младших 7-и битов в прот А
ser r16 ; Подтяжка неиспользуемых выходов
bld r16, 6 ; Подготовка вывода
out PORTB, r16 ; Вывод старшего 8-го бита
ldi r16, 0x01 ; Количество принимаемых байт
rcall rsvr_begin ; Вызов процедуры приёма данных
rjmp loop ; Рабочий цикл
;==============
; Процедура принятия данных
;==============
.def btcnt = r16
.def lstat = r17
.def temp = r18
.def lpcnt = r19
.def plcnt = r20
.def flcnt = r21
.def rslt = r21
;.equ INPRT = PINB
.equ INPRT = ACSR
; Регистры, используемые на этапе синхронизации:
; - lstat
; - lpcnt
; - plcnt
; - temp
; - flcnt
; Регистры, используемые в процессе считывания:
; - btcnt (передаётся в процедуру из программы)
; - X (R27:R26) (передаётся в процедуру из программы)
; - lstat (инициализируется на этапе синхронизации)
; - lpcnt
; - plcnt
; - temp
; - rslt
; Инициализация
rsvr_begin: ldi flcnt, 0x10 ; Допустимое число ошибок синхронизации
in lstat, INPRT ; Чтение линии
rsvr_afrsh: ldi plcnt, 0x08 ; Минимальное число синхроимпульсов
; Ожидание переключения с таймаутом
ldi lpcnt, 0x28 ; Допустимое время ожидания смены сигнала
rsvr_wait_1: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
brne rsvr_chng_1 ; Если значение изменилось переход к задержке
dec lpcnt ; Уменьшить допустимое время ожидания
brne rsvr_wait_1 ; Если время не вышло, продолжить ожидание
; Обработка таймаута
rsvr_timeout: dec flcnt ; Уменьшить допустимое число ошибок
brne rsvr_afrsh ; Если лимит ошибок не достигнут, продолжить
rjmp rsvr_end ; Иначе, закончить процедуру
; Мёртвое время после переключения
rsvr_chng_1: ldi lpcnt, 0x05 ; Инициализация задержки
rsvr_revsl: com lstat ; Инвертировать запомненное состояние линии
rsvr_dtm_1: dec lpcnt ; Уменьшить время задержки
brne rsvr_dtm_1 ; Повторить, если время не вышло
; Ожидание переключения с таймаутом
ldi lpcnt, 0x25 ; Допустимое время ожидания смены сигнала
rsvr_wait_2: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
brne rsvr_chck_1 ; Если уровень изменился, переход к проверкам
dec lpcnt ; Уменьшить допустимое время ожидания
brne rsvr_wait_2 ; Если время не вышло, продолжить ожидание
rjmp rsvr_timeout ; Иначе, переход к обработке таймаута
; Проверка длительности импульса
rsvr_chck_1: cpi lpcnt, 0x0D ; Сравнить оставшееся время с порогом
brcc rsvr_chck_2 ; Если не синхроимпульс, ко второй проверке
subi plcnt, 0x01 ; Уменьшить необходимое число синхроимпульсов
brcc rsvr_skip_1 ; Если заёма нет, то пропуск
clr plcnt ; отмены вычитания
rsvr_skip_1: ldi lpcnt, 0x03 ; Инициализация задержки
rjmp rsvr_revsl ; Переход к задержке
; Проверка возможности перехода к считыванию
rsvr_chck_2: tst plcnt ; Проверка необходимого числа синхроимпульсов
breq rsvr_rdng ; Если достаточно, то к процедуре считывания
dec flcnt ; Уменьшить допустимое число ошибок
breq rsvr_end ; Если лимит попыток достигнут, закончить
ldi plcnt, 0x08 ; Минимальное число синхроимпульсов
ldi lpcnt, 0x03 ; Инициализация задержки
rjmp rsvr_revsl ; Переход к задержке
; Процедура считывания данных
rsvr_rdng: ldi lpcnt, 0x05 ; Инициализация задержки
com lstat
rsvr_btinit: ldi rslt, 0x80 ; Инициализация принимаемого байта
; Мёртвое время после последней операции
rsvr_dtm_2: dec lpcnt ; Уменьшить время задержки
brne rsvr_dtm_2 ; Повторить, если время не вышло
; Ожидание переключения с таймаутом
ldi lpcnt, 0x0B ; Допустимое время ожидания смены сигнала
rsvr_wait_3: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
brne rsvr_chng_2 ; Если значение изменилось переход к задержке
dec lpcnt ; Уменьшить допустимое время ожидания
brne rsvr_wait_3 ; Если время не вышло, продолжить ожидание
rjmp rsvr_end ; Иначе, закончить процедуру
; Задержка перед считыванием
rsvr_chng_2: ldi lpcnt, 0x11 ; Инициализация задержки перед считыванием
rsvr_dtm_3: dec lpcnt ; Уменьшить время задержки
brne rsvr_dtm_3 ; Повторить, если время не вышло
; Процедура считывания
ldi plcnt, 0x00 ; Инициализация числа чтений нулевго бита
; Счёт по низкому уровню
ldi lpcnt, 0x08 ; Инициализация числа чтений низкого уровня
rsvr_read_1: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
breq rsvr_skip_2 ; Если прочитана единица, то пропустить
inc plcnt ; инремент числа чтений нулевого бита
rsvr_skip_2: dec lpcnt ; Уменьшить необходимое число чтений
brne rsvr_read_1 ; Если чтения не исчерпаны, повторить
; Счёт по высокому уровню
ldi lpcnt, 0x08 ; Инициализация числа чтений высокого уровня
rsvr_read_2: in temp, INPRT ; Чтение линии
eor temp, lstat ; Сравнение
andi temp, 1<<ACO ; с запомненным значением
brne rsvr_skip_3 ; Если прочитан ноль, то пропустить
inc plcnt ; инремент числа чтений нулевого бита
rsvr_skip_3: dec lpcnt ; Уменьшить необходимое число чтений
brne rsvr_read_2 ; Если чтения не исчерпаны, повторить
; Расшифровка принятого бита в читаемый байт
subi plcnt, 0x08 ; Сравнение числа нулевых чтений с порогом
ror rslt ; Сохранение бита в принимаемый байт
brcs rsvr_save ; Если байт готов, то сохранить его
ldi lpcnt, 0x06 ; Инициализация задержки
rjmp rsvr_dtm_2 ; Переход к задержке
; Сохранение байта
rsvr_save: st x+, rslt ; Запись байта в регистры/память
cpi r26, 0x10 ; Проверка выхода указателя за регистр R15
brne rsvr_skip_4 ; Если выхода нет, то пропустить
ldi r26, 0x60 ; перестановку указателя на память
rsvr_skip_4: cpi r26, 0xD8 ; Проверить наличие свободного места
breq rsvr_end ; Если место закончилось, закончить процедуру
dec btcnt ; Иначе, уменьшить количество читаемых байт
breq rsvr_end ; Если все байты приняты, закончить процедуру
ldi lpcnt, 0x02 ; Иначе, инициализация задержки
rjmp rsvr_dtm_2 ; Переход к задержке
; Конец
rsvr_end: ret
Последний раз редактировалось B@R5uk Вт июл 15, 2014 15:45:07, всего редактировалось 1 раз.
Что-то вы в оффтоп свалились, товарищи.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Gudd-Head, прошу прощения.
А AVR Studio только к протеусу можно подключить? С Микрокапом она не дружит? А то не охото новую программу осваивать, а моделировать работу МК в виртуальном железе очень хотелось бы.
А AVR Studio только к протеусу можно подключить? С Микрокапом она не дружит? А то не охото новую программу осваивать, а моделировать работу МК в виртуальном железе очень хотелось бы.
Где это вы такой Z80 нашли? В те времена он работал на максимальной частоте 2.5Мгц, потом появились его высокоскоростные аналоги на Z80A 4Мгц, 6Мгц, 8Мгц и даже Z80H на 12Мгц.
14Мгц это вероятно была системная частота которая делилась формируя необходимые частоты в схеме и в том числе нужные для процессора 3.5мгц, потом эти 3.5Мгц тактируют внутренний конвеер в процессоре, и каждая команда выполняется минимум за 4 таких такта, даже NOP.
3000 тактов на бит это не перебор, их можно потратить на помехоустойчивый алгоритм.
14Мгц это вероятно была системная частота которая делилась формируя необходимые частоты в схеме и в том числе нужные для процессора 3.5мгц, потом эти 3.5Мгц тактируют внутренний конвеер в процессоре, и каждая команда выполняется минимум за 4 таких такта, даже NOP.
3000 тактов на бит это не перебор, их можно потратить на помехоустойчивый алгоритм.
Доброго времени суток! Подскажите а как в студии писать в еепром собственные структуры? С байтами то все понятно, а вот по аналогии со структурами не получается работать. Структура имеет следующий вид
Необходимо записать в еепром массив из 10 таких структур. Ткните мордой пожалуйста
Заранее благодарен 
Спойлер
Код: Выделить всё
typedef struct {
unsigned char R;
unsigned char G;
unsigned char B;
} TColor;




