Ошибка FE по USART (atmega8, Си)

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Сообщения: 42
Зарегистрирован: Пт ноя 11, 2011 23:05:59

Сообщение Кот Lancer »

Доброго времени суток! Реализую циклическую асинхронную передачу байта по USART на Си (8 бит, 9600 bod, 2 stop-бита; F_CPU=8 МГц). Проверяю на светодиодах. Чтобы не загружать процессор на ожидание пересылки, прием/передачу данных повесил на прерывания... Передатчик вроде отрабатывает нормально. Но при симуляции в Протеусе в логе появляется ошибка Frame Error (ошибка кадрирования) на приемнике. Я так понимаю это рассинхронизация, хотя скорости обмена одинаковые... (однако в общем пакеты доходят и нужные светодиоды загораются). Если в обработке прерывания добавить блок обработки флагов ошибок (закомменчен), то светодиоды приемника вообще не реагируют... Помогите разобраться, что я делаю не так?

Код приемника:

Код: Выделить всё

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

unsigned char word=0x00;

ISR(USART_RXC_vect)
{
 cli();
/*---------------------------*/

/*
 unsigned char status;
 
 status=UCSRA;
 if(status & (1<<FE)|(1<<DOR)|(1<<PE))
 {
  while(UCSRA&(1<<RXC))status=UDR;
  return;
 } 
*/
 
 word=UDR;

 
/*---------------------------*/
 sei();

 return;
}

int main(void)
{
 /*Port C - LEDs*/
 DDRC=0xFF;
 PORTC=0x00;

 /*Speed: 9600 BOD*/
 UBRRH=0;
 UBRRL=51;

 /*Inicial UCSRA*/
 UCSRA=0x00;

 /*UCSRB*/
 UCSRB=0x00;
 UCSRB=(1<<RXCIE)|(1<<RXEN);

 /*UCSRC: 8 bit;*/
 UCSRC=(1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);

 sei();

 while(1)
 {
   PORTC=word;

   _delay_ms(10);
 }

 return 0;
}

Изображение

п.с. не смог загрузить файл протеуса(
Вложения
Receiver.c
Код приемника
(765 байт) 122 скачивания
Transmitter.c
Код передатчика
(944 байт) 130 скачиваний
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Код: Выделить всё

ISR(USART_TXC_vect)
{
 cli();
/*---------------------------*/
 while(!(UCSRA&(1<<UDRE)));
 UDR=word; 
 
/*---------------------------*/
 sei();
}
В прерывании запрещать прерывания (что и так сделано аппаратно), так потом еще и разрешать! В приемнике та же ошибка (именно ошибка!).
Какой смысл в прерывании по окончании передачи проверять еще и UDRE? Что мешало на него прерывание и повесить?
Может, не стоит слать данные вообще без перерыва?
UCSRC=(1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0);
Возможно, стоит пошаманить с этой строкой и записью в UBRRH: что Студия, что Протеус такого не понимают. У первого запись идет параллельно в оба, независимо от флага, у второго - только в один, опять-таки независимо. У меня работало заполнение сначала UCSRC, без флага, потом UBRRH.
Реклама
Открыл глаза
Сообщения: 42
Зарегистрирован: Пт ноя 11, 2011 23:05:59

Сообщение Кот Lancer »

спасибо, COKPOWEHEU! Учел ваши замечания по отключению прерываний и переместил задержку delay из основного цикла в прерывание - теперь ошибок нет))) Это я действительно переборщил с бесперерывной передачей (хотя вроде и так должна была работать). В перспективе будет схема управления в реальном времени (кодер-декодер на мк), соответственно и посылал байт друг за другом для нормального отклика...

хм, при малых значениях задержки ошибка все равно появляется... получается подбирать ее экспериментально, чтобы не было ошибок и отклик нормальный был?

Код: Выделить всё

ISR(USART_TXC_vect)
{
 _delay_ms(10);
 
 UDR=word;
}
И еще, будет ли лучше сделать отправку байта по истечению определенного времени (например прерывание по Т/С0) - так же по идее мк не будет простаивать как в случае ожидания в прерывании?
Ответить

Вернуться в «AVR»