Страница 21 из 399
Добавлено: Пн ноя 02, 2009 15:07:02
GP1
непонял смысла задачи...
для чего умножать частоту работы таймера?
можно по конкретней: тактовая мк и что нужно получить на выходе.
пишите в личку, посмотрю.
Добавлено: Пт ноя 06, 2009 09:26:27
AndyWorld
Не смог найти в поиске нужную мне информацию по USART. Все на С. А мне надо на Асм. Могу я задать свои вопросы здесь? Или нужно создавать новый топик?
Добавлено: Пт ноя 06, 2009 09:32:38
GP1
валяй здесь, разберемся

Добавлено: Пт ноя 06, 2009 09:51:19
AndyWorld
Хочу разобраться с этим USART. Мега 16.
Взял книжку и ДШ. Вроде все как надо, и инициализация и прием - передача. Не пойму как правильно постоить алгоритм работы.
При инициализации, я так понял, любой принятый символ бразует прерывание в котором мы его и обрабатываем.
У меня этот ожидаемый символ $31 на что мне в ответ должен выдаться символ $BF. И он выдается !!! Но только один раз. Потом сколько бы я не посылал символ $31 в ответ тишина. Понимаю, что где то, какие то флаги нужно дернуть но не пойму.
Добавлено: Пт ноя 06, 2009 10:06:20
GP1
тактовая мк?
Добавлено: Пт ноя 06, 2009 10:09:33
AndyWorld
4.096 Мгц
Добавлено: Пт ноя 06, 2009 10:16:44
GP1
в приведенном куске софта нет собственно алгоритма обработки принятого байта и принчия решения об обратной отправке байта, а проблема скорее всего в нем.
Добавлено: Пт ноя 06, 2009 10:22:15
AndyWorld
Один раз он принимает ешение, когда попадает в прерываение RX. И отправляет ответ. Но потом либо прерывание недоступно либо чего еще. Вечерком причешу код. И тогда отпишусь.
Добавлено: Пт ноя 06, 2009 10:23:28
GP1
давай
Добавлено: Сб ноя 07, 2009 11:04:43
AndyWorld
Вобщем, причесав код с 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...
Добавлено: Сб ноя 07, 2009 12:08:43
GP1
хочу напомнить что вектора у меги16 - 2-х словные и имеют только четные адреса
$0002, $0004, $0006 и т.д., просто писать
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 будет показывать цену на дрова в прошлом году а не вершину стека.
Добавлено: Сб ноя 07, 2009 14:39:31
Pooher
Код: Выделить всё
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
Добавлено: Сб ноя 07, 2009 15:20:52
SII
GP1 писал(а):хочу напомнить что вектора у меги16 - 2-х словные и имеют только четные адреса $0002, $0004, $0006 и т.д., просто писать
reti без явного объявления адреса есть полный не-айс.
и на будующее не используй для меги16 и выше в адресах переходов на обработчик команды rjmp - она однословная, что опять без явного задания адреса вектора будет приводить к непредсказуемым результатам.
Чуть дополню. Можно использовать ORG, как Вы указали. Можно писать пару инструкций reti/nop на каждый вектор. Ну а если нужен переход на обработчик, то, конечно, лучше всего написать jmp, а не rjmp/nop или ORG и rjmp.
Добавлено: Пн ноя 09, 2009 13:11:30
AndyWorld
Спасибо всем кто ответил! Конечно "хорошая мысля, приходт опосля", это я к тому как нужно грамотно обработать прерывание. На выходных я уже и сам пришел к тому примеру что предложил Pooher.
Про rjmp и rcall мне известно. Это работает пока моя программа не перевалила за 8к. Просто занимаюсь по книгам, а там примеры под Тини, и я чтобы не запутаться пока использую такие переходы.
Помогите разобраться с циклом subi-sbci-brcc
Добавлено: Пн ноя 09, 2009 18:34:54
Denikmar
Решил изготовить пульт для фотоаппарата, сделал, прошил работает, но решил, что контроллеры это занятная вещь и ... изучаю ассемблер авр
Извиняюсь за примитивный вопрос, но возникло не понимание как работает данный цикл.
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
Добавлено: Пн ноя 09, 2009 22:28:28
smac
Denikmar писал(а):
Не понимаю связку команд
subi tempL,1 (из tempL будет вычитаться 1 )
sbci tempH,0 (непонимаю
brcc loop (тут как я понял если tempH = 0, то выйдем из цикла но)
З.Ы. Сильно не пинайте, AVR занимаюсь всего месяц мануалы смотрел но не доходит.
Да ничего сложного -
Код: Выделить всё
subi tempL,1 (из tempL будет вычитаться 1 )
sbci tempH,0 (непонимаю
это декремент 16-ти битного числа, который работает след. образом. Из млашего байта -tempL вычитается 1, а из старшего tempH - 0 с переносом. Значит, если в младшем байте 0х00 и из него вычитается 1, то после произведенных действий там окажется 0хFF и взведется флаг переноса, который вычтется из сташего байта ( из него также вычтется 0 как следует из команды) , если же флаг переноса не взведен то из старшего байта вычитается только 0 (т. е. ничего). Далее brcc - переход если не взведен флаг переноса (когда из 0x0000 вычтем 1 то флаг переноса взведется и цикл закончится ). Вот как-то так. А вообще все команды для AVR расписаны в документе AVR Instruction Set, который можно легко найти на сайте Atmel.
Добавлено: Вт ноя 10, 2009 04:42:13
SII
Denikmar
Разберитесь с флажком переноса C: он используется для организации сложений, вычитаний и сдвигов чисел с разрядностью больше байта. Для случая вычитания (на Вашем примере) выше уже откомментировали. Для сложений и сдвигов в общем то же самое.
Добавлено: Вт ноя 10, 2009 08:50:00
GP1
Всем мяу!
от себя добавлю, прочитайте книгу Ю.Ревич "Практическое программирование микроконтроллеров Atmel AVR на языке ассемблера", по-моему в библиотке у Светы она есть.
Добавлено: Вт ноя 10, 2009 09:45:32
Denikmar
Спасибо за ответы, буду читать "Практическое программирование микроконтроллеров Atmel AVR на языке ассемблера"
Добавлено: Вс ноя 15, 2009 08:34:37
asd
Подскажите, как запрограмировать отдельные биты в РОНе, но чтобы другие остались прежними.