|
AT90CAN128, Проблема с USART |
|
|
|
Sep 1 2007, 21:43
|
Группа: Новичок
Сообщений: 8
Регистрация: 1-09-07
Пользователь №: 30 221

|
Есть AT90CAN128, у которого используется USART1. При написании программы в CV AVR всё отлично пашет. Контроллер посылает данные в порт, гипертерминал их получает и выводит на экран. Т.е. железо в порядке. Но когда я попытался написать аналогичную программу в IAR, ком-порт работать перестал. При этом остальное не пострадало. Ниже приведены функции настройки и передачи данных. Код // Инициализация USART void USART_Init( void ) { // Включить приемник и передатчик UCSR1B = ( 1 << RXEN1 ) | ( 1 << TXEN1 ); // 8 data, no parity, 1 stop UCSR1C = ( 1 << UCSZ11 ) | ( 1 << UCSZ10 ); // 9600 bps при 16 MHz UBRR1 = 103; }
// Передача данных по USART void USART1_Transmit( unsigned char data ) { // Запись в буфер UDR1 = data; // Ожидание завершения передачи while ( ! ( UCSR1A & ( 1 << TXC1 ) ) ); } На ATmega8 данные функции работают после незначительной переделки ( только один USART, против двух у at90can128 ). В чем же дело?
|
|
|
|
|
 |
Ответов
|
Sep 2 2007, 16:03
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(--Ivan-- @ Sep 1 2007, 21:43)  Есть AT90CAN128, у которого используется USART1. При написании программы в CV AVR всё отлично пашет. Контроллер посылает данные в порт, гипертерминал их получает и выводит на экран. Т.е. железо в порядке. Но когда я попытался написать аналогичную программу в IAR, ком-порт работать перестал. При этом остальное не пострадало. Ниже приведены функции настройки и передачи данных.
На ATmega8 данные функции работают после незначительной переделки ( только один USART, против двух у at90can128 ). В чем же дело? Дело в том, что для AT90CAN128 адреса регистров компорта находятся в расширенной зоне адресов ввода-вывода (выше 0х60), а для ATmega8 - в обычной (ниже 0х60). Поменяйте файл с определениями регистров и будет вам щастье. И ещё, при инициализации лучше сначала инициализировать регистры порта, потом разрешать приёмник и передатчик, а не наоборот.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Sep 3 2007, 09:51
|
Группа: Новичок
Сообщений: 8
Регистрация: 1-09-07
Пользователь №: 30 221

|
Файл "iocan128.h", в котором определяются регистры, на первый взгляд без ошибок. Адреса связанных с компортом регистров специально сверил с документацией и не нашел отличий. Цитата(=GM= @ Sep 2 2007, 20:03)  И ещё, при инициализации лучше сначала инициализировать регистры порта, потом разрешать приёмник и передатчик, а не наоборот. Пробовал и так, и этак - никакой разницы.
|
|
|
|
|
Sep 3 2007, 16:26
|
Группа: Новичок
Сообщений: 8
Регистрация: 1-09-07
Пользователь №: 30 221

|
Цитата(=GM= @ Sep 3 2007, 15:59)  Попробуйте в режиме теста вывести данные не по прерыванию, а по ожиданию готовности TXC. Прерывания я не использовал. Код // Передача данных по USART void USART1_Transmit( unsigned char data ) { // Запись в буфер UDR1 = data; // Ожидание завершения передачи while ( ! ( UCSR1A & ( 1 << TXC1 ) ) ); } В основной программе просто циклично вызывается данная функция. Код void main( void ) { asm("cli"); PWM_Init(); USART_Init(); asm("sei");
int i=0, c=1; DDRC = 0xFF; PORTC = 0xFF; while (1) { USART1_Transmit( 'b' ); i += c; if ( i > 165 ) c = -1; if ( i < -165 ) c = 1; PWM_Set( i, i ); } } Судя по тому, что остальной код выполняется правильно, зацикливание из-за TXC1 не происходит. Вообще 90кан128 - довольно большой мк, может есть какие-нибудь хитрости именно с инициализацией. Цитата Так что вам мешает написать простенькую тестовую программу вывода в цикле буквы 'A' и сравнить листинги? Чудес ведь не бывает. Программка у меня примерно того же уровня сложности
|
|
|
|
|
Sep 3 2007, 20:50
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(--Ivan-- @ Sep 3 2007, 16:26)  Судя по тому, что остальной код выполняется правильно, зацикливание из-за TXC1 не происходит. Вообще 90кан128 - довольно большой мк, может есть какие-нибудь хитрости именно с инициализацией Ну, чудес не бывает, давайте посмотрим, что там яровский компилер натворил в асмовом коде.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Sep 4 2007, 18:55
|
Группа: Новичок
Сообщений: 8
Регистрация: 1-09-07
Пользователь №: 30 221

|
Цитата(=GM= @ Sep 4 2007, 00:50)  Ну, чудес не бывает, давайте посмотрим, что там яровский компилер натворил в асмовом коде. Знать бы ещё как этот код достать...
|
|
|
|
|
Sep 5 2007, 17:32
|
Группа: Новичок
Сообщений: 8
Регистрация: 1-09-07
Пользователь №: 30 221

|
Код \ In segment CODE, align 2, keep-with-next \ __nearfunc __version_3 void USART_Init() \ USART_Init: \ 00000000 E108 LDI R16, 24 \ 00000002 930000C9 STS 201, R16 \ 00000006 E006 LDI R16, 6 \ 00000008 930000CA STS 202, R16 \ 0000000C E607 LDI R16, 103 \ 0000000E E010 LDI R17, 0 \ 00000010 931000CD STS 205, R17 \ 00000014 930000CC STS 204, R16 \ 00000018 9508 RET \ 0000001A REQUIRE _A_UBRR1 \ 0000001A REQUIRE _A_UCSR1C \ 0000001A REQUIRE _A_UCSR1B
\ In segment CODE, align 2, keep-with-next \ __nearfunc __version_3 void USART1_Transmit(unsigned char) \ USART1_Transmit: \ 00000000 930000CE STS 206, R16 \ ??USART1_Transmit_0: \ 00000004 910000C8 LDS R16, 200 \ 00000008 FF06 SBRS R16, 6 \ 0000000A CFFC RJMP ??USART1_Transmit_0 \ 0000000C 9508 RET \ 0000000E REQUIRE _A_UDR1 \ 0000000E REQUIRE _A_UCSR1A
|
|
|
|
|
Sep 6 2007, 04:33
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(--Ivan-- @ Sep 5 2007, 20:32)  Код \ In segment CODE, align 2, keep-with-next Отлично. А теперь, чтобы не ломать голову приведите листинг второй программы: Цитата(--Ivan-- @ Sep 2 2007, 00:43)  При написании программы в CV AVR всё отлично пашет. Контроллер посылает данные в порт, гипертерминал их получает и выводит на экран.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 6 2007, 16:01
|
Группа: Новичок
Сообщений: 8
Регистрация: 1-09-07
Пользователь №: 30 221

|
Из-за кодвизарда в коде много лишнего. Выкладываю основное Код ; 280 // USART1 initialization ; 281 // Communication Parameters: 8 Data, 1 Stop, No Parity ; 282 // USART1 Receiver: On ; 283 // USART1 Transmitter: On ; 284 // USART1 Mode: Asynchronous ; 285 // USART1 Baud rate: 9600 ; 286 UCSR1A=0x00; STS 0xC8,R30 ; 287 UCSR1B=0xD8; LDI R30,LOW(216) STS 0xC9,R30 ; 288 UCSR1C=0x06; LDI R30,LOW(6) STS 0xCA,R30 ; 289 UBRR1H=0x00; LDI R30,LOW(0) STS 0xCD,R30 ; 290 UBRR1L=0x67; LDI R30,LOW(103) STS 0xCC,R30 Код ; 328 putchar1('a'); LDI R30,LOW(97) ST -Y,R30 RCALL _putchar1 Код ; 96 // USART1 Transmitter interrupt service routine ; 97 interrupt [USART1_TXC] void usart1_tx_isr(void) ; 98 {
.CSEG _usart1_tx_isr: ST -Y,R30 ST -Y,R31 IN R30,SREG ST -Y,R30 ; 99 if (tx_counter1) TST R7 BREQ _0xA ; 100 { ; 101 --tx_counter1; DEC R7 ; 102 UDR1=tx_buffer1[tx_rd_index1]; MOV R30,R6 LDI R31,0 SUBI R30,LOW(-_tx_buffer1) SBCI R31,HIGH(-_tx_buffer1) LD R30,Z STS 0xCE,R30 ; 103 if (++tx_rd_index1 == TX_BUFFER_SIZE1) tx_rd_index1=0; INC R6 LDI R30,LOW(8) CP R30,R6 BRNE _0xB CLR R6 ; 104 }; _0xB: _0xA: ; 105 } LD R30,Y+ OUT SREG,R30 LD R31,Y+ LD R30,Y+ RETI ; 106 ; 107 // Write a character to the USART1 Transmitter buffer ; 108 #pragma used+ ; 109 void putchar1(char c) ; 110 { _putchar1: ; 111 while (tx_counter1 == TX_BUFFER_SIZE1); _0xC: LDI R30,LOW(8) CP R30,R7 BREQ _0xC ; 112 #asm("cli") cli ; 113 if (tx_counter1 || ((UCSR1A & DATA_REGISTER_EMPTY)==0)) TST R7 BRNE _0x10 LDS R30,200 ANDI R30,LOW(0x20) BRNE _0xF _0x10: ; 114 { ; 115 tx_buffer1[tx_wr_index1]=c; MOV R30,R5 LDI R31,0 SUBI R30,LOW(-_tx_buffer1) SBCI R31,HIGH(-_tx_buffer1) LD R26,Y STD Z+0,R26 ; 116 if (++tx_wr_index1 == TX_BUFFER_SIZE1) tx_wr_index1=0; INC R5 LDI R30,LOW(8) CP R30,R5 BRNE _0x12 CLR R5 ; 117 ++tx_counter1; _0x12: INC R7 ; 118 } ; 119 else RJMP _0x13 _0xF: ; 120 UDR1=c; LD R30,Y STS 0xCE,R30 ; 121 #asm("sei") _0x13: sei ; 122 } ADIW R28,1 RET ; 123 #pragma used- ; 124
|
|
|
|
|
Sep 6 2007, 16:39
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(Сергей Борщ @ Sep 6 2007, 15:14)  Ну тогда бы сразу и сказали, кто из отвечавших должен сравнить эти листинги и найти в них отличия из-за которых не работает  Похоже, товарисч сам не знает, чего хочет. Привёл кусок программы с прерыванием, а ранее - кусок программы без прерывания, думайте мол сами. То --Ivan--. Я ж вам сказал, где у вас ошибка, чего проще, поставить сброс ТХС и проверить. А команда RETI сбрасывает ТХС! Что ж вы нас путаете?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Sep 7 2007, 16:18
|
Группа: Новичок
Сообщений: 8
Регистрация: 1-09-07
Пользователь №: 30 221

|
Цитата(=GM= @ Sep 6 2007, 20:39)  То --Ivan--. Я ж вам сказал, где у вас ошибка, чего проще, поставить сброс ТХС и проверить. А команда RETI сбрасывает ТХС! Что ж вы нас путаете? To =GM=. Извините за поздний ответ, написал перед тем как проверить. Сейчас добавил одну строку в функцию передачи, теперь она выглядит так: Код void USART1_Transmit( unsigned char data ) { UDR1 = data; while ( ! ( UCSR1A & ( 1 << TXC1 ) ) ); UCSR1A = ( 1 << TXC1 ); } Появился небольшой прогресс, но правильно данные все равно не передаются. Если перебирать все значения от 1 до 250 и посылать их в компорт, то в окне терминала иногда добавляется буква "А", и никаких других символов нет. До того как стал сбрасывать флаг терминал вообще не реагировал.
|
|
|
|
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|