Ассемблер (ASM) для AVR в вопросах и ответах
Re: Ассемблер (ASM) для AVR в вопросах и ответах
спасибо, что помогли
Что хорошо для меня - полезно для всех! 
- Реклама
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Метеор, давайте по простому, без научных терминов и преамбул.
Когда учился в школе, у нас был сильный преподаватель по физике. Даже заядлые рас***дяи знали физику на отлично. Он объяснял всё на простых примерах и на простом языке.
Всё просто.
Организуем массив в ОЗУ из четырёх байтов.
Организуем приём с UART по прерыванию.
Выделим один регистр под счётчик принятых байтов
В прерывании UART запишем принятый байт в ОЗУ и увеличим счётчик на 1 и перейдём к следующей ячейке ОЗУ.
В основной программе, мы застрянем в цикле, пока значение счётчика не станет 4
После этого можно скопировать из ОЗУ любой из 4х байтов (в данном случае второй байт)
и делать с ним всё, что нам потребуется.
Покажу на примере AVR.
Когда учился в школе, у нас был сильный преподаватель по физике. Даже заядлые рас***дяи знали физику на отлично. Он объяснял всё на простых примерах и на простом языке.
Всё просто.
Организуем массив в ОЗУ из четырёх байтов.
Организуем приём с UART по прерыванию.
Выделим один регистр под счётчик принятых байтов
В прерывании UART запишем принятый байт в ОЗУ и увеличим счётчик на 1 и перейдём к следующей ячейке ОЗУ.
В основной программе, мы застрянем в цикле, пока значение счётчика не станет 4
После этого можно скопировать из ОЗУ любой из 4х байтов (в данном случае второй байт)
и делать с ним всё, что нам потребуется.
Покажу на примере AVR.
Код: Выделить всё
.dseg
buffer: .byte 4 ;Выделим 4 байта в ОЗУ (организуем массив)
;----------
.cseg
.org 0x0000
rjmp RESET
................ ; тут векторы прерываний
...................
UART_RECEIVE_COMPLETE: ;Лучше организовать приём по прерыванию.
in R18, SREG ;Спасём SREG
in R16, UDR ;Копируем в R16 принятый байт из регистра UART
cpi r17, 0x00 ;Если это второй и далее байты,
brne RCV ;то сразу пишем его в ОЗУ, а иначе проверим начало пакета
cpi R16, 0xXX ;Признак начала пакета(первый байт пакета)
breq RCV ;Если он верен, то запишем его, иначе выйдем из прерывания, ничего не трогая
out SREG, R18 ; Восстановим SREG
reti ;Выйдем из прерывания
RCV: ;Запись принятого байта в ОЗУ
st Y+, R16 ; Запишем его в ОЗУ с увеличением на 1 значения пары Y
inc R17 ; Увеличим наш счётчик принятых байтов на 1
out SREG, R18 ; Восстановим SREG
reti ;Выйдем из прерывания
;----------
RESET: ;Тут начало программы
.............
.............
.......... ;Настроим всё (порты, стек, UART и т.д.)
ldi YL, Low(buffer) ;Прихватим парой Y наш массивчик в ОЗУ
ldi YH, High(buffer)
ldi R17, 0x00 ; Этот регистр будет у нас в роли счётчика принятых байтов
;----------
LOOP: ; Упрёмся тут в ожидании приёма всех четырёх байтов.
cpi R17, 0x04 ; Всё ли приняли?
brmi LOOP ;Если нет, то снова проверим
ldi R17, 0x00 ; Иначе сбросим "счётчик"
lds R16, buffer+1 ;Загрузим второй байт из ОЗУ в R16
.......... ;И делаем с ним всё, что нам вздумается
.............
.....
I am DX168B and this is my favourite forum on internet!
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
DX168B, в какой-нибудь момент приемник пропустит один байт и во что это выльется не стоит писать....
Я считаю, что нужно организовать пакеты по 4 байта и ввести таймаут между пакетами. (1байт_2байт_3байт_4байт_таймаут_________________). В этом случае, если в пакете пришло не 4 байта и таймаут прошел, пакет считается "битым" и не записывается в ОЗУ. Достигается это запуском (сбросом в "0" запущенного) таймера при каждом приеме байта.
Я считаю, что нужно организовать пакеты по 4 байта и ввести таймаут между пакетами. (1байт_2байт_3байт_4байт_таймаут_________________). В этом случае, если в пакете пришло не 4 байта и таймаут прошел, пакет считается "битым" и не записывается в ОЗУ. Достигается это запуском (сбросом в "0" запущенного) таймера при каждом приеме байта.
Ставим плюсы: )
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Как в Винде? Там есть и таймауты, XON char и XOFF char.
Для того, чтобы не вылилось это во что-то, нужно ограничить размер пакета и не давать переполняться массиву в ОЗУ выше 4х байтов. Просто это я в программе не указал. Можно просто вырубить прерывание UART после приёма всех четырёх байтов, спокойно обработать их, сброситься в ноль и снова ожидать приёма, включив прерывание UART. Если нужна ещё и целостность пакета, то можно и проверку CRC организовать, если конечно она присылается ему.
Я делал простую проверку. Конечно она может допустить тоже ошибки, но вероятности уже меньше.
Складывал все байты пакета и потом делил на их количество. Результатом и получалась примитивная контрольная сумма в виде одного байта. Только надо учесть то, чтобы ведущее устройство производило расчёт этой суммы и прикрепляло результат к пакету. Потом ведомое производит расчёт суммы, за исключением байта принятой суммы с ведущего устройства. результаты сравниваются и уже принимается решение об обработке принятого пакета.
Для того, чтобы не вылилось это во что-то, нужно ограничить размер пакета и не давать переполняться массиву в ОЗУ выше 4х байтов. Просто это я в программе не указал. Можно просто вырубить прерывание UART после приёма всех четырёх байтов, спокойно обработать их, сброситься в ноль и снова ожидать приёма, включив прерывание UART. Если нужна ещё и целостность пакета, то можно и проверку CRC организовать, если конечно она присылается ему.
Я делал простую проверку. Конечно она может допустить тоже ошибки, но вероятности уже меньше.
Складывал все байты пакета и потом делил на их количество. Результатом и получалась примитивная контрольная сумма в виде одного байта. Только надо учесть то, чтобы ведущее устройство производило расчёт этой суммы и прикрепляло результат к пакету. Потом ведомое производит расчёт суммы, за исключением байта принятой суммы с ведущего устройства. результаты сравниваются и уже принимается решение об обработке принятого пакета.
Последний раз редактировалось DX168B Вс янв 16, 2011 19:38:09, всего редактировалось 1 раз.
I am DX168B and this is my favourite forum on internet!
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
как раз в этом случае может произойти ошибка. если один байт не пройдет, то четвертый байт пакета уже будет записан из 1 байта следующего пакета. Все зависит от поставленных задач. Если устройство ответственное, то и защита должна быть соответствующая.DX168B писал(а):Можно просто вырубить прерывание UART после приёма всех четырёх байтов, спокойно обработать их, сброситься в ноль и снова ожидать приёма, включив прерывание UART. Если нужна ещё и целостность пакета, то можно и проверку CRC организовать.
Ставим плюсы: )
- Реклама
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Если последний байт пакета символизирует конец пакета и отличается от первого байта, то можно не заморачиваться с таймером. Достаточно его проверить. Ну а если это не конец пакета, то уже другого выхода нет - только таймаут. 
I am DX168B and this is my favourite forum on internet!
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
смотря какого рода данные передаются
если байты могут принимать любое значение от 0 до 255, то невозможно определить конец пакета по значению последнего байта.
Ставим плюсы: )
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Ну и я про то же.. 
I am DX168B and this is my favourite forum on internet!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Код: Выделить всё
com lbyte ;
inc lbyte
ldi digit1, -3 Кто сможет объяснить что происходит в этих строчках?
И сразу по этим строчкам, что такое дополнительный код ?
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Что тут может быть непонятного ?
В современных процессорах отрицательные числа представляются в виде двоичного дополнения плюс единица. Т.е.
-X = ~X + 1
Поэтому если тебе надо поменять знак числа и у данного процессора нет готовой команды NEG,
то сначала инвертируешь, потом инкрементируешь.
com lbyte
inc lbyte
- это смена знака у lbyte.
Например было 03
Инвертируем и получаем FC
Инкрементируем и получаем FD, а FD = -3
В самом деле FD + 03 = 00, т.е. -3 + 3 = 0
В современных процессорах отрицательные числа представляются в виде двоичного дополнения плюс единица. Т.е.
-X = ~X + 1
Поэтому если тебе надо поменять знак числа и у данного процессора нет готовой команды NEG,
то сначала инвертируешь, потом инкрементируешь.
com lbyte
inc lbyte
- это смена знака у lbyte.
Например было 03
Инвертируем и получаем FC
Инкрементируем и получаем FD, а FD = -3
В самом деле FD + 03 = 00, т.е. -3 + 3 = 0
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Доброго времени суток!
Помогите определить точное время задержки, кварц 12Мгц (0,083мкс), при Тmp1 = 1
Или вообщем мне нужно такую процедуру что-бы при кварце 12Мгц, выполнялось условие 2-3мкс * Tmp1 Кто что предложит?
Помогите определить точное время задержки, кварц 12Мгц (0,083мкс), при Тmp1 = 1
Код: Выделить всё
Delay1:
ldi Tmp2, 3
cycle:
dec Tmp2
brne cycle
dec Tmp1
brne Delay1
retИли вообщем мне нужно такую процедуру что-бы при кварце 12Мгц, выполнялось условие 2-3мкс * Tmp1 Кто что предложит?
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
с учетом вызова подрограммы командой rcall, задержка составляет 1,5мкс = 18 циклов.

- Вложения
-
- test.JPG
- (17.12 КБ) 990 скачиваний
Ставим плюсы: )
-
Nicke
- Первый раз сказал Мяу!
- Сообщения: 27
- Зарегистрирован: Вт фев 09, 2010 19:21:27
- Откуда: Belarus
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Помогите.... Вот проблема на 644 меге.
пишу на АВР студио..
считываю полученные данные с компа
ldi r16,0xff ;r16-ff
;udr - помещаю 0x49
lds r16,udr0
и после этой команды получаю в р16 - 0х00!!!!
Если делаю на меге8 все работает а на 644 при считывании с UDR я получаю 00.
пишу на АВР студио..
считываю полученные данные с компа
ldi r16,0xff ;r16-ff
;udr - помещаю 0x49
lds r16,udr0
и после этой команды получаю в р16 - 0х00!!!!
Если делаю на меге8 все работает а на 644 при считывании с UDR я получаю 00.
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Nicke писал(а):lds r16,udr0
Попробуйте
Код: Выделить всё
in r16,udr0Хотя, вообще не очень понятно что вы делаете и что в итоге хотите получить.
Последний раз редактировалось Gudd-Head Вт янв 25, 2011 14:44:27, всего редактировалось 1 раз.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
- Engineer_Keen
- Друг Кота
- Сообщения: 3871
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Не дотянется... у меги644 адрес UDR0 - 0xC6
Думаю проблема не в этом. Нужен кусок кода по крупнее.
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Командой lds желательно считывать байты из ОЗУ, in - из регистров периферии и SREG, mov - из одного регистра РОН в другой РОН.
Код: Выделить всё
in r16, udr0
lds r16, 0x0060
mov r16, r17
I am DX168B and this is my favourite forum on internet!
- Engineer_Keen
- Друг Кота
- Сообщения: 3871
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Недостаток инструкции IN в том, что она дальше адреса 0x3F не работает
Кстати, посмотрел пример приема байта по UART на мегу644, там стоит IN R16,UDRn. Или я что-то не догоняю, или они примеры тупо из одного документа в другой копируют....
Кстати, посмотрел пример приема байта по UART на мегу644, там стоит IN R16,UDRn. Или я что-то не догоняю, или они примеры тупо из одного документа в другой копируют....
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Да, in/out дальше 3F не работает. Признаюсь, лень было скачивать даташит. Согласен, надо через LDS.
Возможно, студия что-то криво подставляет, и можно поробовать задать адрес напрямую:
Возможно, студия что-то криво подставляет, и можно поробовать задать адрес напрямую:
Код: Выделить всё
LDS r16, $00C6; C6 - адрес UDR0[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
-
Nicke
- Первый раз сказал Мяу!
- Сообщения: 27
- Зарегистрирован: Вт фев 09, 2010 19:21:27
- Откуда: Belarus
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Вообщем вот код.
.include "m644def.inc"
.list
.equ button1=0
.equ button2=1
.def temp=r16
.def countH=r17
.def countL=r18
.def data=r19
.dseg
buf: .byte 1000
.cseg
.org 0
;Инициализация стека
ldi temp, low(RAMEND)
out SPL, temp
ldi temp, high(RAMEND)
out SPH, temp
;Инициализация USART
ldi R16,$00 ;USART.Mode=9600,N,1(16Mhz)
sts UCSR0A,R16
ldi R16,$06
sts UCSR0C,R16
ldi R16,$67
sts UBRR0L,R16
ldi R16,$00
sts UBRR0H,R16
ldi R16,$18
sts UCSR0B,R16
;Отключаем компоратор
ldi temp, 0x80
out ACSR, temp
;Инициализация портов
ldi temp, 0xFF
out DDRB, temp
ldi temp, 0x00
out DDRC, temp ;Порт C на ввод
ldi temp, 0xFF
out PORTC, temp ;Включаем подтягивающие резисторы
;======================;
;Начало работы устройства
;======================;
start:
lds r20,UCSR0A
sbrs r20, RXC0
rjmp start
lds r16, UDR0 ;ЗДЕСЬ В R16 ПОМЕЩАЕТСЯ НУЛИ
out PORTB,r16
lds r20,UCSR0A
sbrs r20, RXC0
rjmp start1
lds r16, UDR0
rjmp (PC-4)
start1:
sts UDR0,r16
lds R16,UCSR0A
sbrs R16,UDRE0
rjmp (PC-3)
rjmp start
Пробывал адрес памяти давать на прямую тоже самое. На другом компе тоже самое, в ПРотеусе тоже не работает. Осталось только застрелиться. Хотя беру мегу8 теже операции блин работает. А lds потому что адрес "c6" а что они в даташите пишут так вообщем описывают принцип действия, хотя скорее всего копируют.
.include "m644def.inc"
.list
.equ button1=0
.equ button2=1
.def temp=r16
.def countH=r17
.def countL=r18
.def data=r19
.dseg
buf: .byte 1000
.cseg
.org 0
;Инициализация стека
ldi temp, low(RAMEND)
out SPL, temp
ldi temp, high(RAMEND)
out SPH, temp
;Инициализация USART
ldi R16,$00 ;USART.Mode=9600,N,1(16Mhz)
sts UCSR0A,R16
ldi R16,$06
sts UCSR0C,R16
ldi R16,$67
sts UBRR0L,R16
ldi R16,$00
sts UBRR0H,R16
ldi R16,$18
sts UCSR0B,R16
;Отключаем компоратор
ldi temp, 0x80
out ACSR, temp
;Инициализация портов
ldi temp, 0xFF
out DDRB, temp
ldi temp, 0x00
out DDRC, temp ;Порт C на ввод
ldi temp, 0xFF
out PORTC, temp ;Включаем подтягивающие резисторы
;======================;
;Начало работы устройства
;======================;
start:
lds r20,UCSR0A
sbrs r20, RXC0
rjmp start
lds r16, UDR0 ;ЗДЕСЬ В R16 ПОМЕЩАЕТСЯ НУЛИ
out PORTB,r16
lds r20,UCSR0A
sbrs r20, RXC0
rjmp start1
lds r16, UDR0
rjmp (PC-4)
start1:
sts UDR0,r16
lds R16,UCSR0A
sbrs R16,UDRE0
rjmp (PC-3)
rjmp start
Пробывал адрес памяти давать на прямую тоже самое. На другом компе тоже самое, в ПРотеусе тоже не работает. Осталось только застрелиться. Хотя беру мегу8 теже операции блин работает. А lds потому что адрес "c6" а что они в даташите пишут так вообщем описывают принцип действия, хотя скорее всего копируют.
- Engineer_Keen
- Друг Кота
- Сообщения: 3871
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Nicke писал(а):в ПРотеусе тоже не работает.
Только что скопировал, скомпилировал, запустил в протеусе.
Результ: байт с USART выводится и PORTB и посылается обратно в USART.
Так ведь и должно быть по задумке?


