|
|
  |
Помогите с инициализацией UART, ASM (AVR GCC), AT90S8535, 8 МГц |
|
|
|
Jul 28 2009, 20:12
|
Участник

Группа: Участник
Сообщений: 15
Регистрация: 25-07-08
Из: Киев
Пользователь №: 39 212

|
У меня возник вопрос по инициализации UART в AT90S8535. Компилируется нормально, прошивается тоже. При включении мигает синий светодиод (т.е. нормально функционирует основной цикл программы - LOOP1). Но стоит только послать что то по юарту - МК "виснет" (т.е. вместо загорания зелёного светодиода мигающий синий останавливается в том состоянии, на которое пришллось прерывание). Помогите, пожалуйста, определить, в чём проблема. Подозреваю, что намудрил с инициализацией UART'а... Пишу на ассемблере. Вот текст программы (для компиляции использую AVR GCC, частота кварца 8 МГц). Код .nolist #define __SFR_OFFSET 0 #include <avr/io.h> #include <avr/interrupt.h> .list
#define RED 0b11111011 #define BLUE 0b11110111 #define GREEN 0b11101111 #define OFF 0b11111111
tmp1 = 16 tmp2 = 17 led_color = 18
.global main
main:
.org 0 rjmp RESET ; Reset Handler reti; EXT_INT0 ; IRQ0 Handler reti; EXT_INT1 ; IRQ1 Handler reti; TIM2_COMP ; Timer2 Compare Handler reti; TIM2_OVF ; Timer2 Overflow Handler reti; TIM1_CAPT ; Timer1 Capture Handler reti; TIM1_COMPA ; Timer1 CompareA Handler reti; TIM1_COMPB ; Timer1 CompareB Handler reti; TIM1_OVF ; Timer1 Overflow Handler reti; TIM0_OVF ; Timer0 Overflow Handler reti; SPI_STC ; SPI Transfer Complete Handler rjmp UART_RXC ; UART RX Complete Handler reti; UART_DRE ; UDR Empty Handler reti; UART_TXC ; UART TX Complete Handler reti; ADC ; ADC Conversion Complete Interrupt reti; EE_RDY ; EEPROM Ready Handler reti; ANA_COMP ; Analog Comparator Handler
RESET: ldi tmp1, lo8(RAMEND); Stack setup out SPL, tmp1 ldi tmp1, hi8(RAMEND) out SPH, tmp1
ldi tmp1, 51; set uart baudrate to 9600 baud out UBRR, tmp1
ldi tmp1, (1<<TXEN)|(1<<RXEN)|(1<<RXCIE); enable RXint and enable tx/rx out UCR, tmp1
ser tmp1 out DDRC, tmp1; set all PORTC bits as output
ldi led_color, BLUE; turn on blue led by default ldi tmp2, OFF
sei ; global enable interrupts
LOOP1: out PORTC, led_color; LED on rcall wait_some_time out PORTC, tmp2 ; LED off rcall wait_some_time rjmp LOOP1 ; repeat
wait_some_time: push r24 push r25 ldi r24, 0xFF ldi r25, 0xFF
wait_some_time_loop: sbiw r24, 1 brne wait_some_time_loop pop r25 pop r24 ret
UART_RXC: ldi led_color, GREEN reti
|
|
|
|
|
Jul 28 2009, 21:17
|
Знающий
   
Группа: Свой
Сообщений: 614
Регистрация: 12-06-09
Из: рядом с Москвой
Пользователь №: 50 219

|
Цитата(TwisteR @ Jul 29 2009, 00:12)  У меня возник вопрос по инициализации UART в AT90S8535.
Компилируется нормально, прошивается тоже. При включении мигает синий светодиод (т.е. нормально функционирует основной цикл программы - LOOP1). Но стоит только послать что то по юарту - МК "виснет" (т.е. вместо загорания зелёного светодиода мигающий синий останавливается в том состоянии, на которое пришллось прерывание).
Помогите, пожалуйста, определить, в чём проблема. Подозреваю, что намудрил с инициализацией UART'а...
Пишу на ассемблере. Вот текст программы (для компиляции использую AVR GCC, частота кварца 8 МГц). По приходу данных флаг RXC устанавливается в 1, что вызывает прерывание. Но этот флаг сбрасывается только при чтении регистра UDR, а у вас оно отсутствует - поэтому прерывание начинает генерироваться снова и снова - что приводит к зависанию. Вставьте в обработчик прерывания команду Код in R7, UDR; и всё случится
Сообщение отредактировал VladimirB - Jul 28 2009, 21:18
|
|
|
|
|
Jul 28 2009, 22:11
|
Участник

Группа: Участник
Сообщений: 15
Регистрация: 25-07-08
Из: Киев
Пользователь №: 39 212

|
Цитата(VladimirB @ Jul 28 2009, 23:17)  Вставьте в обработчик прерывания команду Код in R7, UDR; и всё случится  "Это слишком хорошо, чтобы быть правдой" =) Код UART_RXC: in r19, UDR; reti К сожалению, не помогло  МК по прежнему виснет при посылке байта на PD0 (RXD). Какие ещё могут быть варианты?
|
|
|
|
|
Jul 28 2009, 22:30
|
Участник

Группа: Участник
Сообщений: 15
Регистрация: 25-07-08
Из: Киев
Пользователь №: 39 212

|
Цитата(singlskv @ Jul 29 2009, 00:26)  Обясните пожалуйста что Вы делаете таким оператором ? В начале файла обьявлено: Код #define GREEN 0b11101111 Следовательно, эта инструкция загружает значение 0b11101111 в регистр led_color (r18), откуда я в основном цикле вывожу его на порт, к которому подпаян трёхцветный светодиод с общим анодом.
Сообщение отредактировал TwisteR - Jul 28 2009, 22:35
|
|
|
|
|
Jul 29 2009, 05:06
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Линкуете "вручную" или вызывая avr-gcc "и пусть он заботится"? Дизассемблировать avr-objdump -ом уже собранную программу целиком пробовали? Дело в том, что если идёт стандартная линковка, то обычный "сишный" startup-код подлинковывается и таблица прерываний в нём, Ваша ничего не делает и её можно убрать. А метку обработчика прерываний объявить так, как этого ждёт стартап-код. Ну и UDR вынимать нужно Код .global main main: ; .org 0 и таблицу векторов выбросить ; тут то, что у Вас идёт после метки RESET ... ...
; имя обработчика прерываний - как и в C-программах, ; брать из io*.h для нужного контроллера .global UART_RX_vect UART_RX_vect: ... reti
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jul 29 2009, 07:36
|
Участник

Группа: Участник
Сообщений: 15
Регистрация: 25-07-08
Из: Киев
Пользователь №: 39 212

|
Цитата(ReAl @ Jul 29 2009, 07:06)  Дизассемблировать avr-objdump -ом уже собранную программу целиком пробовали? Пробовал конечно, но всегда настораживало вот это (вижу, что таблица прерываний, но не понимаю, почему она вся однородная, ведь я использовал одно из них): Код Disassembly of section .text:
00000000 <__vectors>: 0: 10 c0 rjmp .+32 ; 0x22 <__ctors_end> 2: 17 c0 rjmp .+46 ; 0x32 <__bad_interrupt> 4: 16 c0 rjmp .+44 ; 0x32 <__bad_interrupt> 6: 15 c0 rjmp .+42 ; 0x32 <__bad_interrupt> 8: 14 c0 rjmp .+40 ; 0x32 <__bad_interrupt> a: 13 c0 rjmp .+38 ; 0x32 <__bad_interrupt> c: 12 c0 rjmp .+36 ; 0x32 <__bad_interrupt> e: 11 c0 rjmp .+34 ; 0x32 <__bad_interrupt> 10: 10 c0 rjmp .+32 ; 0x32 <__bad_interrupt> 12: 0f c0 rjmp .+30 ; 0x32 <__bad_interrupt> 14: 0e c0 rjmp .+28 ; 0x32 <__bad_interrupt> 16: 0d c0 rjmp .+26 ; 0x32 <__bad_interrupt> 18: 0c c0 rjmp .+24 ; 0x32 <__bad_interrupt> 1a: 0b c0 rjmp .+22 ; 0x32 <__bad_interrupt> 1c: 0a c0 rjmp .+20 ; 0x32 <__bad_interrupt> 1e: 09 c0 rjmp .+18 ; 0x32 <__bad_interrupt> 20: 08 c0 rjmp .+16 ; 0x32 <__bad_interrupt> Ну, думаю, пускай так и будет (не знал ведь, как оно должно быть на самом деле  ) Последовал вашему совету (про _vect не знал  ) и с удивлением обнаружил вот что  : Код 14: 0e c0 rjmp .+28 ; 0x32 <__bad_interrupt> 16: 32 c0 rjmp .+100 ; 0x7c <__vector_11> 18: 0c c0 rjmp .+24 ; 0x32 <__bad_interrupt> Прошил МК и всё заработало 8) Век живи, век учись... Цитата(ReAl @ Jul 29 2009, 07:06)  Дело в том, что если идёт стандартная линковка, то обычный "сишный" startup-код подлинковывается и таблица прерываний в нём, Ваша ничего не делает и её можно убрать. А метку обработчика прерываний объявить так, как этого ждёт стартап-код. Ну и UDR вынимать нужно Спасибо большое за обьяснение, так и знал, что не до конца разобрался с синтаксисом. В Сети море примеров, но очень мало именно на ассемблере (для GCC). Руководствовался тем, что удалось найти, в частности этой программой генератора простейших сигналов. Как я понял, её автор линкует вручную?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|