|
Непонятка с 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 - аналогично.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|