Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Непонятка с USART в Tiny2313
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
vsk
Подскажите что может быть, в протеусе работает, в контроллере нет, вернее на вывод в комп все пашет, кварц стоит на 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++]);
}
}
vsk
Подскажите в какую сторону хоть копать то, fuse - биты выставлены правильно....
URANst
Код
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
- зачем вот эта строка ?
vsk
Как я понял в терминале, в виде HEX'a протеуса цифре 1 - соответствует код 31.
Но после замены в коже на этот код, результат, что даже протуес не симулирует, а в первоначальном варианте все работает, а вот в железе ни в какую.....
Исправленный код для теста:
for (;;)
{
if (rx_int==1)
{
//RestartPin(8);
if (rxbuff == 31) RestartPin(1);
.........
rx_int = 0;
}
=GM=
Цитата(vsk @ Feb 26 2008, 07:38) *
Подскажите что может быть, в протеусе работает, в контроллере нет, вернее на вывод в комп все пашет, кварц стоит на 4 Мгц, а вот от команд с ПК, типа цифры от 1 до 8, не работает

Если правильно понял, вы совсем ничего не принимаете от писюка, верно?

1) Проверьте тот ли адрес стоит для перехода к программе обработки прерывания на приём.

2) Убедитесь, что инструкция if(bit_is_clear(UCSRA, FE)) правильно работает или лучше уберите её временно.

3) Ну и rx_int должен быть равен нулю до входа в цикл for(;;).
URANst
Вот побыстрому набросал тоже что и вы, все работает !!
там файл пртеуса, .с, hex.
При нажатии клавиши "1" загорается светодиод на PB0 и через 1 сек гаснет, контроллер назад отправляет код клавиши.
vsk
Да, в протеусе все работает, а в живом железе, никак....
В прерывание попадает, и если символ сразу отсылать обратно, все ок, может в сравнении что не так?....


---- Убедитесь, что инструкция if(bit_is_clear(UCSRA, FE)) правильно работает или лучше уберите её временно.
Это пробовал по разному.

---- Ну и rx_int должен быть равен нулю до входа в цикл for(;;).
С этим да, не досмотрел, в 0 надо выставить.
=GM=
Цитата(vsk @ Feb 26 2008, 12:58) *
В прерывание попадает, и если символ сразу отсылать обратно, все ок, может в сравнении что не так?...

Ага, значит у вас приём сам по себе идёт, что ж вы нас дезинформируете(:-)?

1) Попробуйте вместо void RestartPin(int PinNumber) поставить void RestartPin(char PinNumber). Кстати, странно, что у вас нет описания прототипа функции RestartPin.

2) Поставьте в операторе switch вариант по default: <что-то сделать>.

3) Если уж ничего не помогает, попробуйте временно вместо switch поставить вывод некой строки, типа "превед медвед".
Сергей Борщ
Цитата(vsk @ Feb 26 2008, 14:58) *
---- Ну и rx_int должен быть равен нулю до входа в цикл for(;;).
С этим да, не досмотрел, в 0 надо выставить.
Достаточно его не инициализировать при объявлении. Неинициализированные глобальные переменные обнуляются перед вызовом main(). Зачем вы его объявили как int? Достаточно char - код будет короче.

Судя по исходному коду, вы используете WinAVR. Какую версию? В последних надо вместо SIGNAL() использовать ISR(). SIGNAL() при входе в обработчик разрешает прерывания, а поскольку вы не вычитали UDR, то снова вызывается прерывание и вы снова заходите в обработчик. И так пока стек не закончится.
=GM=
Цитата(Сергей Борщ @ Feb 26 2008, 14:00) *
SIGNAL() при входе в обработчик разрешает прерывания, а поскольку вы не вычитали UDR, то снова вызывается прерывание и вы снова заходите в обработчик. И так пока стек не закончится

А если rxbuff=UDR; поставить первым?
vsk
Странно, код подкрутил, но теперь в терминале буквы теряются.....
и на 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++]);
}
}
URANst
При таких настройках UARTa будут ошибки передачи, смотри в даташит на описание UART (самый конец), возможно из-за этого в протеусе работало а в железке нет, хотя нигде не должно правильно работать.
Сергей Борщ
Цитата(=GM= @ Feb 26 2008, 16:09) *
А если rxbuff=UDR; поставить первым?
А толку? К моменту исполнения первой команды С - функции-обработчика прерывания уже будут разрешены.

P.S. Ой... Сам залез в документацию и обнаружил, что SIGNAL() и ISR() в последних версиях - одно и то же, но пользование SIGNAL() не рекомендуется - она будет исключена в следующих версиях. Что-то в память запало из предыдущих версий. Автору - проверьте, как объявлен SIGNAL() в заголовочном файле - attribute((interrupt)) или attribute((signal)). Если interrupt - обязательно замените в своей программе SIGNAL() на ISR().
=GM=
Цитата(vsk @ Feb 26 2008, 14:19) *
Странно, код подкрутил, но теперь в терминале буквы теряются..

Попробуйте прямое эхо организовать, типа такого
Код
SIGNAL(SIG_USART0_RECV)
{
  rxbuff=UDR;
  UDR = rxbuff;   //эхо
  rx_int=1;
}

Будут символы теряться?
vsk
Цитата(=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 - аналогично.
defunct
Цитата
Как я понял в терминале, в виде HEX'a протеуса цифре 1 - соответствует код 31.
Но после замены в коже на этот код, результат, что даже протуес не симулирует, а в первоначальном варианте все работает, а вот в железе ни в какую.....

Неправильно понял. Не 31, а 0x31.

if (rxbuff == 0x31)
vsk
Цитата(defunct @ Feb 27 2008, 15:03) *
Неправильно понял. Не 31, а 0x31.

if (rxbuff == 0x31)

И так тоже уже пробовал, результат такой же, в протеусе все живет.... а вот на макетке нет...
bodja74
vsk

Если даже в протеусе работает ,то на компе должно по любому пахать.

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

sendString("Welcome to Remote Reset\0");
В реальном железе эта строка выводится правильно или криво?
если она выводится криво, то приведите, что именно вы получаете в терминале (для наглядности в hex).

Цитата
Если даже в протеусе работает ,то на компе должно по любому пахать.

Протеус это не показатель.
но должен согласиться с Вами, что если в симуляторе что-то работает, а в железе нет, может означать проблему тактирования.
надо проверить тактируется ли чип реально 4Mhz (а не от 4Mhz / 8), и соответвует ли делитеть для UART'a.
vsk
Цитата(bodja74 @ Feb 27 2008, 15:27) *
vsk

Если даже в протеусе работает ,то на компе должно по любому пахать.

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

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


В терминале получаем строку Welcoe to emote Rese - приблизительно этого вида.
А делитель uart вроде корректно расчитывается по формуле.
defunct
Цитата(vsk @ Feb 27 2008, 17:28) *
В терминале получаем строку Welcoe to emote Rese - приблизительно этого вида.
А делитель uart вроде корректно расчитывается по формуле.

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

В результате замены еще меньше символов принимаю.
Все варианты вроде перепробовал, но на tiny2313 не катят, хотя на atmega всегда работает и работало.
Еще такой маленький вопрос, если кварц стоит керамический, может быть большой уход частоты, что работает не корректно?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.