Ассемблер (ASM) для AVR в вопросах и ответах
- AndyWorld
- Прорезались зубы
- Сообщения: 209
- Зарегистрирован: Вт сен 30, 2008 09:23:14
- Откуда: Краснодарский край
Хочу разобраться с этим USART. Мега 16.
Взял книжку и ДШ. Вроде все как надо, и инициализация и прием - передача. Не пойму как правильно постоить алгоритм работы.
При инициализации, я так понял, любой принятый символ бразует прерывание в котором мы его и обрабатываем.
У меня этот ожидаемый символ $31 на что мне в ответ должен выдаться символ $BF. И он выдается !!! Но только один раз. Потом сколько бы я не посылал символ $31 в ответ тишина. Понимаю, что где то, какие то флаги нужно дернуть но не пойму.
Взял книжку и ДШ. Вроде все как надо, и инициализация и прием - передача. Не пойму как правильно постоить алгоритм работы.
При инициализации, я так понял, любой принятый символ бразует прерывание в котором мы его и обрабатываем.
У меня этот ожидаемый символ $31 на что мне в ответ должен выдаться символ $BF. И он выдается !!! Но только один раз. Потом сколько бы я не посылал символ $31 в ответ тишина. Понимаю, что где то, какие то флаги нужно дернуть но не пойму.
- Вложения
-
- usart.txt
- (728 байт) 238 скачиваний
- AndyWorld
- Прорезались зубы
- Сообщения: 209
- Зарегистрирован: Вт сен 30, 2008 09:23:14
- Откуда: Краснодарский край
Вобщем, причесав код с USART выяснилась причина по которой
на полученный символ ответный символ посылался один раз.
Причина в том, что в прерывании видимо нельзя использовать
такой прием:
;cpi temp,$31 ;Сравниваем полученное значение
;breq send_symbol ;если равно то переходим
при исполнении относительного перехода на метку send_symbol
уже не возможно по ret вернуться назад в прерывание.И разрешение
прерывания "прием закончен" не происходило.
USART_RXC: ;Процедура обработки
in temp,UDR ;Помещаем полученный бит в рабочий регистр
cbi UCSRB,RXCIE ;Запрещаем прерывание "прием закончен"
cpi temp,$31 ;Сравниваем полученное значение
breq send_symbol ;если равно то переходим
sbi UCSRB,RXCIE ;разрешаем прерывание "прием закончен"
reti
send_symbol:
ldi temp,$BF
rcall out_com
ret
пришлось добавить еще одну процедуру check_symbol, и тогда все заработало как надо.
USART_RXC: ;Процедура обработки прерывания
in temp,UDR ;Помещаем полученный бит в рабочий регистр
cbi UCSRB,RXCIE ;Запрещаем прерывание "прием закончен"
rcall check_symbol
sbi UCSRB,RXCIE ;разрешаем прерывание "прием закончен"
reti
check_symbol:
cpi temp,$31 ;Сравниваем полученное значение
breq send_symbol ;если равно то переходим
ret
send_symbol:
ldi temp,$BF
rcall out_com
ret
Неужели пара команд cpi и breq - это не есть точка возврата?
И еще. В примерах книги Д.Мортона "Микроконтроллеры AVR Вводный курс"
При объявлении прерываний они просто перечислялись по порядку, а не нужные были просто забиты reti.Вот так:
rjmp Init ;$000
reti ;$001
reti ;$002
reti ;$003
reti ;$004
reti ;$005
rjmp TMR0 ;$006
но это для at90s2313
А в моем случае, для Mega16, каждое прерывание приходится тыкать носом в вектор по ДШ.
.cseg
.org 0
rjmp Init
reti ;rjmp EXT_INT0 ;External interrupt Request 0
reti ;rjmp EXT_INT1 ;External interrupt Request 1
reti ;rjmp TIMER2_COMP ;Timer/Counter2 Compare match
reti ;rjmp TIMER2_OVF ;Timer/Counter2 Overflow
reti ;rjmp TIMER1_CAPT ;Timer/Counter1 Capture Event
reti ;rjmp TIMER1_COMPA ;Timer/Counter1 Compate Match A
reti ;rjmp TIMER1_COMPB ;Timer/Counter1 Compate Match B
reti ;rjmp TIMER1_OVF ;Timer/Counter1 Overflow
reti ;rjmp TIMER0_OVF ;Timer/Counter0 Overflow
reti ;rjmp SPI_CTC ;Serial Tramsfer Comlete
.org 22
rjmp USART_RXC ;USART Rx Complete
если я этого не сделаю, то при возникновении нужного прерывания я никогда в него не попаду.
Ну и не попадал, собственно говоря.
А ведь не должно быть так по идее. Или его книга устарела, или я чего то не понимаю или
это некий прикол от AVRStudio...
на полученный символ ответный символ посылался один раз.
Причина в том, что в прерывании видимо нельзя использовать
такой прием:
;cpi temp,$31 ;Сравниваем полученное значение
;breq send_symbol ;если равно то переходим
при исполнении относительного перехода на метку send_symbol
уже не возможно по ret вернуться назад в прерывание.И разрешение
прерывания "прием закончен" не происходило.
USART_RXC: ;Процедура обработки
in temp,UDR ;Помещаем полученный бит в рабочий регистр
cbi UCSRB,RXCIE ;Запрещаем прерывание "прием закончен"
cpi temp,$31 ;Сравниваем полученное значение
breq send_symbol ;если равно то переходим
sbi UCSRB,RXCIE ;разрешаем прерывание "прием закончен"
reti
send_symbol:
ldi temp,$BF
rcall out_com
ret
пришлось добавить еще одну процедуру check_symbol, и тогда все заработало как надо.
USART_RXC: ;Процедура обработки прерывания
in temp,UDR ;Помещаем полученный бит в рабочий регистр
cbi UCSRB,RXCIE ;Запрещаем прерывание "прием закончен"
rcall check_symbol
sbi UCSRB,RXCIE ;разрешаем прерывание "прием закончен"
reti
check_symbol:
cpi temp,$31 ;Сравниваем полученное значение
breq send_symbol ;если равно то переходим
ret
send_symbol:
ldi temp,$BF
rcall out_com
ret
Неужели пара команд cpi и breq - это не есть точка возврата?
И еще. В примерах книги Д.Мортона "Микроконтроллеры AVR Вводный курс"
При объявлении прерываний они просто перечислялись по порядку, а не нужные были просто забиты reti.Вот так:
rjmp Init ;$000
reti ;$001
reti ;$002
reti ;$003
reti ;$004
reti ;$005
rjmp TMR0 ;$006
но это для at90s2313
А в моем случае, для Mega16, каждое прерывание приходится тыкать носом в вектор по ДШ.
.cseg
.org 0
rjmp Init
reti ;rjmp EXT_INT0 ;External interrupt Request 0
reti ;rjmp EXT_INT1 ;External interrupt Request 1
reti ;rjmp TIMER2_COMP ;Timer/Counter2 Compare match
reti ;rjmp TIMER2_OVF ;Timer/Counter2 Overflow
reti ;rjmp TIMER1_CAPT ;Timer/Counter1 Capture Event
reti ;rjmp TIMER1_COMPA ;Timer/Counter1 Compate Match A
reti ;rjmp TIMER1_COMPB ;Timer/Counter1 Compate Match B
reti ;rjmp TIMER1_OVF ;Timer/Counter1 Overflow
reti ;rjmp TIMER0_OVF ;Timer/Counter0 Overflow
reti ;rjmp SPI_CTC ;Serial Tramsfer Comlete
.org 22
rjmp USART_RXC ;USART Rx Complete
если я этого не сделаю, то при возникновении нужного прерывания я никогда в него не попаду.
Ну и не попадал, собственно говоря.
А ведь не должно быть так по идее. Или его книга устарела, или я чего то не понимаю или
это некий прикол от AVRStudio...
- GP1
- Поставщик валерьянки для Кота
- Сообщения: 2401
- Зарегистрирован: Пт май 23, 2008 19:32:22
- Откуда: Россия, Волгоград
- Контактная информация:
хочу напомнить что вектора у меги16 - 2-х словные и имеют только четные адреса $0002, $0004, $0006 и т.д., просто писать
reti без явного объявления адреса есть полный не-айс.
и на будующее не используй для меги16 и выше в адресах переходов на обработчик команды rjmp - она однословная, что опять без явного задания адреса вектора будет приводить к непредсказуемым результатам.
для правильной работы этого куска код надо перед каждым reti вставить .org $000x, тогда все будет гуд.
а такой выход из п/п есть полный беспредел с точки зрения мк, через некоторое время работы твой SP будет показывать цену на дрова в прошлом году а не вершину стека.
reti без явного объявления адреса есть полный не-айс.
и на будующее не используй для меги16 и выше в адресах переходов на обработчик команды rjmp - она однословная, что опять без явного задания адреса вектора будет приводить к непредсказуемым результатам.
Код: Выделить всё
.cseg
.org 0
rjmp Init
reti ;rjmp EXT_INT0 ;External interrupt Request 0
reti ;rjmp EXT_INT1 ;External interrupt Request 1
reti ;rjmp TIMER2_COMP ;Timer/Counter2 Compare match
reti ;rjmp TIMER2_OVF ;Timer/Counter2 Overflow
reti ;rjmp TIMER1_CAPT ;Timer/Counter1 Capture Event
reti ;rjmp TIMER1_COMPA ;Timer/Counter1 Compate Match A
reti ;rjmp TIMER1_COMPB ;Timer/Counter1 Compate Match B
reti ;rjmp TIMER1_OVF ;Timer/Counter1 Overflow
reti ;rjmp TIMER0_OVF ;Timer/Counter0 Overflow
reti ;rjmp SPI_CTC ;Serial Tramsfer Comlete
.org 22для правильной работы этого куска код надо перед каждым reti вставить .org $000x, тогда все будет гуд.
Код: Выделить всё
USART_RXC: ;Процедура обработки
in temp,UDR ;Помещаем полученный бит в рабочий регистр
cbi UCSRB,RXCIE ;Запрещаем прерывание "прием закончен"
cpi temp,$31 ;Сравниваем полученное значение
breq send_symbol ;если равно то переходим
sbi UCSRB,RXCIE ;разрешаем прерывание "прием закончен"
retiа такой выход из п/п есть полный беспредел с точки зрения мк, через некоторое время работы твой SP будет показывать цену на дрова в прошлом году а не вершину стека.
- Pooher
- Мучитель микросхем
- Сообщения: 491
- Зарегистрирован: Вс янв 07, 2007 01:45:48
- Откуда: Российская Федерация, будь она неладна...
Код: Выделить всё
USART_RXC:
in temp,UDR
cbi UCSRB,RXCIE
cpi temp,$31
breq send_symbol
sbi UCSRB,RXCIE
cbi UCSRA,RXC
reti
send_symbol:
ldi temp,$BF
rcall out_com
retЧто мешало написать так:
Код: Выделить всё
USART_RXC:
in temp,UDR
cbi UCSRB,RXCIE
cpi temp,$31
breq send_symbol
sbi UCSRB,RXCIE
cbi UCSRA,RXC
reti
send_symbol:
ldi temp,$BF
rcall out_com
sbi UCSRB,RXCIE
cbi UCSRA,RXC
retiНаучить нельзя, можно научиться. Пифагор.
Вставь недостающие буквы в слово *у*ня. Если у тебя получилось слово кухня, значит ты интеллигентный человек.
Вставь недостающие буквы в слово *у*ня. Если у тебя получилось слово кухня, значит ты интеллигентный человек.
-
SII
- Вымогатель припоя
- Сообщения: 635
- Зарегистрирован: Пт янв 30, 2009 14:50:35
- Откуда: Солнечногорск
GP1 писал(а):хочу напомнить что вектора у меги16 - 2-х словные и имеют только четные адреса $0002, $0004, $0006 и т.д., просто писать
reti без явного объявления адреса есть полный не-айс.
и на будующее не используй для меги16 и выше в адресах переходов на обработчик команды rjmp - она однословная, что опять без явного задания адреса вектора будет приводить к непредсказуемым результатам.
Чуть дополню. Можно использовать ORG, как Вы указали. Можно писать пару инструкций reti/nop на каждый вектор. Ну а если нужен переход на обработчик, то, конечно, лучше всего написать jmp, а не rjmp/nop или ORG и rjmp.
- AndyWorld
- Прорезались зубы
- Сообщения: 209
- Зарегистрирован: Вт сен 30, 2008 09:23:14
- Откуда: Краснодарский край
Спасибо всем кто ответил! Конечно "хорошая мысля, приходт опосля", это я к тому как нужно грамотно обработать прерывание. На выходных я уже и сам пришел к тому примеру что предложил Pooher.
Про rjmp и rcall мне известно. Это работает пока моя программа не перевалила за 8к. Просто занимаюсь по книгам, а там примеры под Тини, и я чтобы не запутаться пока использую такие переходы.
Про rjmp и rcall мне известно. Это работает пока моя программа не перевалила за 8к. Просто занимаюсь по книгам, а там примеры под Тини, и я чтобы не запутаться пока использую такие переходы.
Помогите разобраться с циклом subi-sbci-brcc
Решил изготовить пульт для фотоаппарата, сделал, прошил работает, но решил, что контроллеры это занятная вещь и ... изучаю ассемблер авр
Извиняюсь за примитивный вопрос, но возникло не понимание как работает данный цикл.
FCLK 1.2MHz, @0 к примеру 500 (us)
ldi tempL,byte1((@0 * FCLK / 20 / 100000 - 5) / 10)
ldi tempH,byte2((@0 * FCLK / 20 / 100000 - 5) / 10)
loop: Delay(16) ;16 (тактах )
subi tempL,1 ;1
sbci tempH,0 ;1
brcc loop ;2(1)
Не понимаю связку команд
subi tempL,1 (из tempL будет вычитаться 1 )
sbci tempH,0 (непонимаю
brcc loop (тут как я понял если tempH = 0, то выйдем из цикла но)
З.Ы. Сильно не пинайте, AVR занимаюсь всего месяц мануалы смотрел но не доходит.
Извиняюсь за примитивный вопрос, но возникло не понимание как работает данный цикл.
FCLK 1.2MHz, @0 к примеру 500 (us)
ldi tempL,byte1((@0 * FCLK / 20 / 100000 - 5) / 10)
ldi tempH,byte2((@0 * FCLK / 20 / 100000 - 5) / 10)
loop: Delay(16) ;16 (тактах )
subi tempL,1 ;1
sbci tempH,0 ;1
brcc loop ;2(1)
Не понимаю связку команд
subi tempL,1 (из tempL будет вычитаться 1 )
sbci tempH,0 (непонимаю
brcc loop (тут как я понял если tempH = 0, то выйдем из цикла но)
З.Ы. Сильно не пинайте, AVR занимаюсь всего месяц мануалы смотрел но не доходит.
Re: Помогите разобраться с циклом subi-sbci-brcc
Denikmar писал(а):Не понимаю связку команд
subi tempL,1 (из tempL будет вычитаться 1 )
sbci tempH,0 (непонимаю
brcc loop (тут как я понял если tempH = 0, то выйдем из цикла но)
З.Ы. Сильно не пинайте, AVR занимаюсь всего месяц мануалы смотрел но не доходит.
Да ничего сложного -
Код: Выделить всё
subi tempL,1 (из tempL будет вычитаться 1 )
sbci tempH,0 (непонимаю 
