Страница 1 из 1

Проблема с приёмом по UART

Добавлено: Сб апр 09, 2011 10:34:27
ladik
Доброго времени суток!) В МК пока чайник( по учёбе появилась необходимость разобраться в UART. Всё как бы насторил. Запустил симуляцию...Выставил RXD=1-прерывание по приёму. В UDR вбил данные, к примеру 0xFF. Нажал F11, выполнилось прерывание по приёму, и сразу очистился регистр UDR, :o т.е. я даже не успел перейти в тело обработчика. Понял, что это происходит из за UDRE=1. Почему он равен 1 не понимаю. :roll: Таким образом, приём как бы и не осуществляется :cry: Ещё вопрос в том, что при моделировании в протеусе, при нажатии клавиши на клавиатуре светодиоды загораются, только их код не соответствует коду клавиши. Подскажите, мне, чайнику в чём тут ошибка.

Файлы AVR Studiuo и Proteus-a прилагаю.

Спасибо, кто откликнется! :)

Re: Проблема с приёмом по UART

Добавлено: Сб апр 09, 2011 11:08:24
Jack_A
Насчет Противуса не скажу, не пользуюсь, а в Студии - какая версия ? Помню, в одной из не самых свежих версий у меня даже таймер не работал, в последующих - уже ОК.
Вообще, периферию предпочитаю отлаживать в железе, в симуляторе - только логику и подпрограммы обработки. Но - у каждый индус свой вкус.
В порядке бреда : а если попробовать считывать UDR раньше UCSR ?

Re: Проблема с приёмом по UART

Добавлено: Сб апр 09, 2011 11:12:28
ladik
4 версия AVR. А, что по поводу считывания регистров очистка происходит до считывания, в момент прихода прерывания.

Re: Проблема с приёмом по UART

Добавлено: Вт апр 12, 2011 21:49:52
coredumped
Дам пару советов, которые облегчат жизнь
Используйте псевдонимы для регистров, текст будет читаться легче, ошибок станет меньше :)

Код: Выделить всё

.def	A			= r16
.def	B			= r17
Это стандартный кусок для UART. Подправить значения частоты кварца и поставить желаемую скорость.
Это гораздо удобнее, чем шарить по таблицам или считать на калькуляторе. Пусть компилятор сделает работу за вас - у него башка железная :)

Код: Выделить всё

.equ    clock       = 14745600   ;clock frequency 
.equ    baudrate    = 9600     ;choose a baudrate 
.equ    baudconst   = (clock/(16*baudrate))-1
Вот кусочек, который инициализирует UART с использованием вышеописанных констант. Просто и удобно, не правда ли? И главное, понятно.

Код: Выделить всё

;init UART
		ldi 	A, high(baudconst)
		out 	UBRRH, A
		ldi 	A, low(baudconst)
		out 	UBRRL, A
		ldi 	A, (1<<RXCIE)|(1<<RXEN)|(1<<TXEN)	; enable receiver and transmitter
		out 	UCSRB,A
		ldi 	A, (1<<USBS)|(3<<UCSZ0)	; set frame format: 8data, 2stop bit
		out 	UCSRC,A
		sei
Теперь по коду. Инициализацию UART я не смотрел, потому как лень считать (я уже выше писал). К тому-же непонятно какая частота тактового генератора. Остальное выглядит нормально.
По обработке прерываний UART - все у Вас правильно сделано.
Вот табличка векторов мне не нравится. Я вам приведу примерчик, правда он для tiny2313. Рекомендую всегда описывать все векторы прерываний, это позволит избежать многих ошибок.

Код: Выделить всё

.cseg
.org    $000                   ;Reset Vector
        rjmp    Reset
   
 ;Interrupt vectors

.org    INT0addr				;External Interrupt0 Vector
        reti
.org    INT1addr				;External Interrupt1 Vector
        reti
.org    ICP1addr				;Input Capture1 Interrupt Vector
        reti
.org	OC1addr					;Output Compare1 Interrupt Vector 
        reti
.org    OVF1addr				;Overflow1 Interrupt Vector
        reti
.org    OVF0addr				;Overflow0 Interrupt Vector
        reti
.org    URXC0addr				;UART0 Receive Complete Interrupt Vector
        rjmp	uart_receive
.org    UDRE0addr				;UART0 Data Register Empty Interrupt Vector
        rjmp	uart_send_int
.org    UTXC0addr				;UART0 Transmit Complete Interrupt Vector
        reti
.org    ACIaddr					;Analog Comparator Interrupt Vector
        reti
.org	PCIaddr					;Pin Change Interrupt Vector
		reti
.org	OC1Baddr				;Timer/Counter1 Compare Match B Interrupt Vector
		reti
.org	OC0Aaddr				;Timer/Counter0 Compare Match A Interrupt Vector    
		reti
.org	OC0Baddr				;Timer/Counter0 Compare Match B Interrupt Vector    
		reti
.org	USI_STARTaddr			;USI start Interrupt Vector
		rjmp	usi_start
.org	USI_OVFaddr				;USI overflow Interrupt Vector
		rjmp	usi_ovf						
.org	ERDYaddr				;EEPROM write complete Interrupt Vector
		reti
.org	WDTaddr					;Watchdog Timer Interrupt Vector
		reti
		
Reset:

Последний совет: Купите макетку, детальки, соберите. Сделайте или купите программатор. А протеусу доверять не стоит.

Re: Проблема с приёмом по UART

Добавлено: Ср апр 13, 2011 11:17:20
ladik
спасибо за советы! Так и поступлю! а то, что-то этот протеус какой то косячный. УАРТ уже настроил к этому времени. Теперт проблема с подключением ЛСД. :(

Re: Проблема с приёмом по UART

Добавлено: Ср апр 13, 2011 19:02:22
murzila
Возможно, в новых версиях ошибку эмуляции LCD так и не поправили. Я тоже пробовал пользоваться протеусом (еще 6-й версией), поимел проблемы с симуляцией, грохнул это глюкало и с тех пор не смотрю в его сторону. В железе все работало идеально. Все сказанное конечно IMHO.

Re: Проблема с приёмом по UART

Добавлено: Ср апр 13, 2011 21:17:52
coredumped
ladik писал(а):спасибо за советы! Так и поступлю! а то, что-то этот протеус какой то косячный. УАРТ уже настроил к этому времени. Теперт проблема с подключением ЛСД. :(
ЛСД не подключают, а под язык кладут :))
По поводу LCD: если речь идет о модуле, под управлением HD44780 (типа BC1602...) - есть готовая либлиотека на С. Могу запостить, если нада. Был гдето кусок кода на ASM, если сильно надо - кричите "help", пороюсь, найду :)

Re: Проблема с приёмом по UART

Добавлено: Чт апр 14, 2011 14:34:03
ladik
на Си ваще никак((( На АСМ написал код, чето в протеусе не работает вашпе((( Вот не пойму я, когда мы команды посылаем. между ними Е нужно перебрасывать и задержки ставить, аль нет?) На асм если не затруднит, пришлите))) и ишоо, у меня шина должна быть 4х разрядная :)

Re: Проблема с приёмом по UART

Добавлено: Чт апр 14, 2011 22:27:52
coredumped
Вот маленькая прожка на ASM, правда под tiny2313. Я ее притырил где-то в сети, точно не помню, по крайней мере - работает, я проверял. Более того, я даже на ее основе пару проектиков сделал. Подключение LCD здесь через регистр, зато экономия ног МК, в принципе легко переделать (перепишите инициадизацию и процедурку PutByte). Прикладую прожку и схемку :)