|
Непонятка с USART в Tiny2313, В протеусе работает, в контроллере нет |
|
|
|
Feb 26 2008, 07:38
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Подскажите что может быть, в протеусе работает, в контроллере нет, вернее на вывод в комп все пашет, кварц стоит на 4 Мгц, а вот от команд с ПК, типа цифры от 1 до 8, не работает.
#include <avr/io.h> #include <avr/interrupt.h> #include <avr/iotn2313.h> #include <util/delay.h> #include <stdlib.h> #include <stdint.h> #include <stdio.h>
#define BAUD (4000000/16/9600 - 1) #define USART_RXC_vect USART_RX_vect
void sleep(void); volatile unsigned char rxbuff; volatile unsigned int rx_int = 1;
SIGNAL(SIG_USART0_RECV)
{
if (bit_is_clear(UCSRA, FE)) { rxbuff=UDR; rx_int=1; }
}
void sleep(void) { int i; for (i=0; i<=10; i++) _delay_loop_2(30000); }
void RestartPin(int PinNumber) { sleep(); switch (PinNumber) { case 1: PORTB=PORTB | (1<<PB0); sleep(); PORTB=PORTB & (0<<PB0); sendString(" TC1 Ok\0"); break; case 2: PORTB=PORTB | (1<<PB1); sleep(); PORTB=PORTB & (0<<PB1); sendString(" TC2 Ok\0"); break; case 3: PORTB=PORTB | (1<<PB2); sleep(); PORTB=PORTB & (0<<PB2); sendString(" TC3 Ok\0"); break; case 4: PORTB=PORTB | (1<<PB3); sleep(); PORTB=PORTB & (0<<PB3); sendString(" TC4 Ok\0"); break; case 5: PORTB=PORTB | (1<<PB4); sleep(); PORTB=PORTB & (0<<PB4); sendString(" TC5 Ok\0"); break; case 6: PORTB=PORTB | (1<<PB5); sleep(); PORTB=PORTB & (0<<PB5); sendString(" TC6 Ok\0"); break; case 7: PORTB=PORTB | (1<<PB6); sleep(); PORTB=PORTB & (0<<PB6); sendString(" TC7 Ok\0"); break; case 8: PORTB=PORTB | (1<<PB7); sleep(); PORTB=PORTB & (0<<PB7); sendString(" TC8 Ok\0"); break; } }
int main(void) { // DDRA = 0x00; //1 - out, 0 - in DDRB = 0xFF; USARTInit(); sei();
sleep(); sendString("Welcome to Remote Reset\0");
for (;;) { if (rx_int==1) { if (rxbuff == '1') RestartPin(1); if (rxbuff == '2') RestartPin(2); if (rxbuff == '3') RestartPin(3); if (rxbuff == '4') RestartPin(4); if (rxbuff == '5') RestartPin(5); if (rxbuff == '6') RestartPin(6); if (rxbuff == '7') RestartPin(7); if (rxbuff == '8') RestartPin(8); rx_int = 0; } } return 0; }
void USARTInit() {
UBRRL = BAUD; UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(0<<UDRIE); //UCSRC = (1<<UCSZ1)|(1<<UCSZ0); }
void sendChar(unsigned char data) { while (!(UCSRA &(1<<UDRE))) ; UDR = data; }
void sendString(unsigned char s[]) { int i=0; while (i<64) { if (s[i]=='\0') break; sendChar(s[i++]); } }
|
|
|
|
|
Feb 26 2008, 11:03
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Подскажите в какую сторону хоть копать то, fuse - биты выставлены правильно....
|
|
|
|
|
Feb 26 2008, 11:17
|
Частый гость
 
Группа: Новичок
Сообщений: 83
Регистрация: 2-02-06
Пользователь №: 13 912

|
Код switch (PinNumber) { Как я понял ключ сдесь - это принятый байт, который вы генерите нажатием клавиши, так вот клавиши 1, 2 ... - цифры , не возвращают значения 0x01,0x02 ... Поключите в протеусе виртуальный терминал , нажмите на клавишу и посмотрите какой код она возвращает и тогда все поймете . Код PORTB=PORTB | (1<<PB0); замените на PORTB|=(1<<PB0); Код PORTB=PORTB & (0<<PB0); замените на PORTB&=~(1<<PB0); Код #define USART_RXC_vect USART_RX_vect - зачем вот эта строка ?
Сообщение отредактировал URANst - Feb 26 2008, 11:26
|
|
|
|
|
Feb 26 2008, 11:38
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Как я понял в терминале, в виде HEX'a протеуса цифре 1 - соответствует код 31. Но после замены в коже на этот код, результат, что даже протуес не симулирует, а в первоначальном варианте все работает, а вот в железе ни в какую..... Исправленный код для теста: for (;;) { if (rx_int==1) { //RestartPin(8); if (rxbuff == 31) RestartPin(1); ......... rx_int = 0; }
|
|
|
|
|
Feb 26 2008, 12:27
|

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

|
Цитата(vsk @ Feb 26 2008, 07:38)  Подскажите что может быть, в протеусе работает, в контроллере нет, вернее на вывод в комп все пашет, кварц стоит на 4 Мгц, а вот от команд с ПК, типа цифры от 1 до 8, не работает Если правильно понял, вы совсем ничего не принимаете от писюка, верно? 1) Проверьте тот ли адрес стоит для перехода к программе обработки прерывания на приём. 2) Убедитесь, что инструкция if(bit_is_clear(UCSRA, FE)) правильно работает или лучше уберите её временно. 3) Ну и rx_int должен быть равен нулю до входа в цикл for(;;).
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Feb 26 2008, 12:47
|
Частый гость
 
Группа: Новичок
Сообщений: 83
Регистрация: 2-02-06
Пользователь №: 13 912

|
Вот побыстрому набросал тоже что и вы, все работает !! там файл пртеуса, .с, hex. При нажатии клавиши "1" загорается светодиод на PB0 и через 1 сек гаснет, контроллер назад отправляет код клавиши.
Сообщение отредактировал URANst - Feb 26 2008, 12:50
Прикрепленные файлы
1.rar ( 26.7 килобайт )
Кол-во скачиваний: 27
|
|
|
|
|
Feb 26 2008, 12:58
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Да, в протеусе все работает, а в живом железе, никак.... В прерывание попадает, и если символ сразу отсылать обратно, все ок, может в сравнении что не так?....
---- Убедитесь, что инструкция if(bit_is_clear(UCSRA, FE)) правильно работает или лучше уберите её временно. Это пробовал по разному.
---- Ну и rx_int должен быть равен нулю до входа в цикл for(;;). С этим да, не досмотрел, в 0 надо выставить.
|
|
|
|
|
Feb 26 2008, 13:46
|

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

|
Цитата(vsk @ Feb 26 2008, 12:58)  В прерывание попадает, и если символ сразу отсылать обратно, все ок, может в сравнении что не так?... Ага, значит у вас приём сам по себе идёт, что ж вы нас дезинформируете(:-)? 1) Попробуйте вместо void RestartPin(int PinNumber) поставить void RestartPin(char PinNumber). Кстати, странно, что у вас нет описания прототипа функции RestartPin. 2) Поставьте в операторе switch вариант по default: <что-то сделать>. 3) Если уж ничего не помогает, попробуйте временно вместо switch поставить вывод некой строки, типа "превед медвед".
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Feb 26 2008, 14:00
|

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

|
Цитата(vsk @ Feb 26 2008, 14:58)  ---- Ну и rx_int должен быть равен нулю до входа в цикл for(;;). С этим да, не досмотрел, в 0 надо выставить. Достаточно его не инициализировать при объявлении. Неинициализированные глобальные переменные обнуляются перед вызовом main(). Зачем вы его объявили как int? Достаточно char - код будет короче. Судя по исходному коду, вы используете WinAVR. Какую версию? В последних надо вместо SIGNAL() использовать ISR(). SIGNAL() при входе в обработчик разрешает прерывания, а поскольку вы не вычитали UDR, то снова вызывается прерывание и вы снова заходите в обработчик. И так пока стек не закончится.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 26 2008, 14:19
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Странно, код подкрутил, но теперь в терминале буквы теряются..... и на switch defaut не переходит..... Вот умеченный код: #include <avr/io.h> #include <avr/interrupt.h> #include <avr/iotn2313.h> #include <util/delay.h> #include <stdlib.h> #include <stdint.h> #include <stdio.h> #include "commutator.h"
#define BAUD (4000000/16/9600 - 1)
void sleep(void); volatile unsigned char rxbuff; volatile unsigned int rx_int = 0;
SIGNAL(SIG_USART0_RECV) { // if (bit_is_clear(UCSRA, FE)) // while ( !(UCSRA & (1<<RXC)) ); //{ rxbuff=UDR;//c; rx_int=1; //} }
void sleep(void) { int i; for (i=0; i<=10; i++) _delay_loop_2(30000); }
void RestartPin(unsigned char PinNumber) { sleep(); switch (PinNumber) { case 0x31: PORTB=PORTB | (1<<PB0); sleep(); PORTB=PORTB & (0<<PB0); sendString(" TC1 Ok\0"); break; case 0x32: PORTB=PORTB | (1<<PB1); sleep(); PORTB=PORTB & (0<<PB1); sendString(" TC2 Ok\0"); break; case 0x33: PORTB=PORTB | (1<<PB2); sleep(); PORTB=PORTB & (0<<PB2); sendString(" TC3 Ok\0"); break; case 0x34: PORTB=PORTB | (1<<PB3); sleep(); PORTB=PORTB & (0<<PB3); sendString(" TC4 Ok\0"); break; case 0x35: PORTB=PORTB | (1<<PB4); sleep(); PORTB=PORTB & (0<<PB4); sendString(" TC5 Ok\0"); break; case 0x36: PORTB=PORTB | (1<<PB5); sleep(); PORTB=PORTB & (0<<PB5); sendString(" TC6 Ok\0"); break; case 0x37: PORTB=PORTB | (1<<PB6); sleep(); PORTB=PORTB & (0<<PB6); sendString(" TC7 Ok\0"); break; case 0x38: PORTB=PORTB | (1<<PB7); sleep(); PORTB=PORTB & (0<<PB7); sendString(" TC8 Ok\0"); break; default: sendString(" Error Code\0"); break; } }
int main(void) { //1 - out, 0 - in USARTInit(); DDRB = 0xFF; sei();
sleep(); sendString("Welcome to Remote Reset\0");
for (;;) { if (rx_int==1) { RestartPin(rxbuff); rx_int = 0; } } return 0; }
void USARTInit() {
UBRRL = BAUD; UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE); //UCSRC = (1<<UCSZ1)|(1<<UCSZ0); }
void sendChar(unsigned char data) { while (!(UCSRA &(1<<UDRE))) ; UDR = data; }
void sendString(unsigned char s[]) { int i=0; while (i<64) { if (s[i]=='\0') break; sendChar(s[i++]); } }
|
|
|
|
|
Feb 26 2008, 15:41
|

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

|
Цитата(=GM= @ Feb 26 2008, 16:09)  А если rxbuff=UDR; поставить первым? А толку? К моменту исполнения первой команды С - функции-обработчика прерывания уже будут разрешены. P.S. Ой... Сам залез в документацию и обнаружил, что SIGNAL() и ISR() в последних версиях - одно и то же, но пользование SIGNAL() не рекомендуется - она будет исключена в следующих версиях. Что-то в память запало из предыдущих версий. Автору - проверьте, как объявлен SIGNAL() в заголовочном файле - attribute((interrupt)) или attribute((signal)). Если interrupt - обязательно замените в своей программе SIGNAL() на ISR().
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 26 2008, 16:00
|

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

|
Цитата(vsk @ Feb 26 2008, 14:19)  Странно, код подкрутил, но теперь в терминале буквы теряются.. Попробуйте прямое эхо организовать, типа такого Код SIGNAL(SIG_USART0_RECV) { rxbuff=UDR; UDR = rxbuff; //эхо rx_int=1; } Будут символы теряться?
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Feb 27 2008, 05:47
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Цитата(=GM= @ Feb 26 2008, 19:00)  Попробуйте прямое эхо организовать, типа такого Код SIGNAL(SIG_USART0_RECV) { rxbuff=UDR; UDR = rxbuff; //эхо rx_int=1; } Будут символы теряться? После reset'a выдается слово с потерянными символами, при нажатии клавиш в терминале, с предложенным кодом эха символы не возвращаются. Вместо Signal пробовал ставить ISR, результат аналогичен, а в заголовочном файле код: #ifdef __cplusplus #define ISR(vector) \ extern "C" void vector(void) __attribute__ ((signal)); \ void vector (void) #else #define ISR(vector) \ void vector (void) __attribute__ ((signal)); \ void vector (void) #endif /** \def SIGNAL(signame) \ingroup avr_interrupts \code#include <avr/interrupt.h>\endcode Introduces an interrupt handler function that runs with global interrupts initially disabled. This is the same as the ISR macro. \note Do not use anymore in new code, it will be deprecated in a future release. */ #ifdef __cplusplus #define SIGNAL(signame) \ extern "C" void signame(void) __attribute__ ((signal)); \ void signame (void) #else #define SIGNAL(signame) \ void signame (void) __attribute__ ((signal)); \ void signame (void) #endif При SIGNAL(SIG_USART0_RECV) { // if (bit_is_clear(UCSRA, FE)) // while ( !(UCSRA & (1<<RXC)) ); //{ rxbuff=UDR; UDR = rxbuff; //эхо rx_int=1; //} } в терминале появляется текст и сразу за ним бегут символы с мусором без остановки, при нажатии кнопок, все замирает, и символов нет. При ISR - аналогично.
|
|
|
|
|
Feb 27 2008, 12:23
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Цитата(defunct @ Feb 27 2008, 15:03)  Неправильно понял. Не 31, а 0x31.
if (rxbuff == 0x31) И так тоже уже пробовал, результат такой же, в протеусе все живет.... а вот на макетке нет...
|
|
|
|
|
Feb 27 2008, 12:27
|
Знающий
   
Группа: Свой
Сообщений: 543
Регистрация: 22-10-05
Пользователь №: 9 984

|
vskЕсли даже в протеусе работает ,то на компе должно по любому пахать. 1 Проверте еще раз правильное ли тактирование. 2 Осцилл + прозвонка схемы ,на своем веку я одних только глюкавых МАХ наколлекционировал пол дюжины.Или один канал не работал или минус не выдавал .Естественно не помешает проверить питание,шнуры,пайку ,дорожки и т.д. Все это решается за 15 минут
|
|
|
|
|
Feb 27 2008, 12:30
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(vsk @ Feb 27 2008, 14:23)  И так тоже уже пробовал, результат такой же, в протеусе все живет.... а вот на макетке нет... sendString("Welcome to Remote Reset\0"); В реальном железе эта строка выводится правильно или криво? если она выводится криво, то приведите, что именно вы получаете в терминале (для наглядности в hex). Цитата Если даже в протеусе работает ,то на компе должно по любому пахать. Протеус это не показатель. но должен согласиться с Вами, что если в симуляторе что-то работает, а в железе нет, может означать проблему тактирования. надо проверить тактируется ли чип реально 4Mhz (а не от 4Mhz / 8), и соответвует ли делитеть для UART'a.
|
|
|
|
|
Feb 27 2008, 12:37
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Цитата(bodja74 @ Feb 27 2008, 15:27)  vskЕсли даже в протеусе работает ,то на компе должно по любому пахать. 1 Проверте еще раз правильное ли тактирование. 2 Осцилл + прозвонка схемы ,на своем веку я одних только глюкавых МАХ наколлекционировал пол дюжины.Или один канал не работал или минус не выдавал .Естественно не помешает проверить питание,шнуры,пайку ,дорожки и т.д. Все это решается за 15 минут  Max232 работает, я ему заворачивал сигнал, контроллер тоже пашет, на своей частоте должно быть, в комп хоть мусор но вижу(вернее текст, но с потерями букв, если убрать полностью прерывание, и сразу в цикле писать в порт, то ни символа не теряется). Если поставить в прерывании подергать ножкой, то тоже работает, значит что то получает.
|
|
|
|
|
Feb 27 2008, 15:28
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Цитата(defunct @ Feb 27 2008, 15:30)  sendString("Welcome to Remote Reset\0"); В реальном железе эта строка выводится правильно или криво? если она выводится криво, то приведите, что именно вы получаете в терминале (для наглядности в hex). Протеус это не показатель. но должен согласиться с Вами, что если в симуляторе что-то работает, а в железе нет, может означать проблему тактирования. надо проверить тактируется ли чип реально 4Mhz (а не от 4Mhz / 8), и соответвует ли делитеть для UART'a. В терминале получаем строку Welcoe to emote Rese - приблизительно этого вида. А делитель uart вроде корректно расчитывается по формуле.
|
|
|
|
|
Mar 25 2008, 06:36
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 11-01-08
Пользователь №: 33 988

|
Цитата(defunct @ Feb 27 2008, 18:33)  1. Попробуйте проверять вместо UDRE, !TXC флаг. 2. Раз символов меньше чем ожидалось можно предположить, что скорость UART'a получилась выше ожидаемых 9600 - попробуйте понизить частоту МК или увеличить значение UBRR. В результате замены еще меньше символов принимаю. Все варианты вроде перепробовал, но на tiny2313 не катят, хотя на atmega всегда работает и работало. Еще такой маленький вопрос, если кварц стоит керамический, может быть большой уход частоты, что работает не корректно?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|