Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
08.04.2010, 12:49
|
|
Частый гость
Регистрация: 15.01.2007
Сообщений: 20
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
AVR USART+прерывания=потеря данных
Всем привет, коллеги.
Неприятно удивлен размером буфера UART на ATMega32 - похоже он всего 1 байт.
К МК (кристалл 8 Мгц) подключена клавиатура PC и эмуляция клавиатуры для PC.
Помимо этого прием данных с UART. То есть МК работает в режиме прозрачности для данных с клавиатуры, пересылая их на ПК, но может "добавить" пересылаемые данные теми, что поступают на UART.
Все работает, но если данные поступают на UART интенсивно (38400 8N1), то я вижу потерю данных, и это не радует.
Прерывания таймера и INT0 упрощать уже просто некуда, но передача и прием сигналов клавиатуры в случае приема - от меня не зависит - когда идет тогда и обрабатывай, а в случае передачи требовательна к таймингам. После двух дней жесткого мониторинга у самого меня идеи концились, видите ли вы выход ?
В качестве альтернативы я вижу ввод CTS-RTS, но очень ломает переделывать устройство. Альтернатива - ввести обратную связь по UART чтобы PC при необходимости повторял пропущеные байты. Тоже не радость, в основном по причине кривизны такого решения.
Еще мнения ?
|
|
|
|
08.04.2010, 13:05
|
|
Временная регистрация
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
|
Re: AVR USART+прерывания=потеря данных
Пиши данные при приёме байта с UART в прерывании в буффер, лучше кольцевой, читай из этого буфера когда надо. Передачу тоже можно буфферизировать. И не запрещай прерывания дольше чем принимается/передаётся один байт.
|
|
|
|
08.04.2010, 13:13
|
|
Частый гость
Регистрация: 15.01.2007
Сообщений: 20
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: AVR USART+прерывания=потеря данных
Буфер есть.. Я не идиот) Два, на передачу тоже. PS два кольцевых на 256 байт без условий для пойнтеров начала и конца - все ровно и правильно )
Не запрещать - это как ? приоритет прерываний не может быть изменен - он просто есть и все. И в этом приоритете UART занимает одно из последних мест.
То есть: передача идет, буфер собирает данные, в это время щелкает таймер, по мере накопления идет передача с ноги, в то же время поступают прерывания на INT0. И в какой-то момент наступет ситуация, когда время выполнения внутри обработчиков прерывания (при этом другие прерывания запрещены разумеется) становится слишком велико и не считаный байт в буфере UART заменяется вновь поступающим.
|
|
|
|
08.04.2010, 13:18
|
|
Временная регистрация
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
|
Re: AVR USART+прерывания=потеря данных
Тогда код в студию.
У меня USART в похожих условиях отлично работает на 115200.
|
|
|
|
08.04.2010, 13:22
|
|
Временная регистрация
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
|
Re: AVR USART+прерывания=потеря данных
Чтобы при такой скорости были потери данных нужно не читать буффер ка минимум 260 мкс - это долго.
|
|
|
|
08.04.2010, 13:29
|
|
Частый гость
Регистрация: 15.01.2007
Сообщений: 20
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: AVR USART+прерывания=потеря данных
UART: 38400 8N1
#pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC
void uart0_rx_isr(void)
{
char ch=0;
//uart has received a character in UDR
// получили данные
ch=UDR;
if ((ch›=0x61) && (ch‹=0x7A)) ch=ch-0x20;
// ну типа поехали...
if (ch==0x0A) return;
if (ch==0x0D)
{
received++;
ch=0; // сделали zero-terminated строку
}
rx_buffer[rx_tale]=ch;
rx_tale++;
}
TIMER2 10uSec
#pragma interrupt_handler timer2_ovf_isr:iv_TIM2_OVF
void timer2_ovf_isr(void)
{
TCNT2 = 0xFF; //reload counter value
if (timer›0) timer--;
if (key_timeout›0) key_timeout--;
}
TIMER0 40uSec
#pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
void timer0_ovf_isr(void)
{
TCNT0 = 0xFB; //reload counter value
if (cmp2›0)
{
cmp2--;
if (cmp2==0)
{
PORTA=0;
PORTC=0;
}
}
}
INT0 - периодически, с частотой 10uSec, 24 раза за сессию (12 на спад фронта и 12 на старт фронта).
#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{
//external interupt on INT0
if ((MCUCR & 0x01)==0) // falling edge ?
{
MCUCR = MCUCR | 0x01;
bitcount++;
if (iscmd==0)
{
if ((bitcount›1) && (bitcount‹10))
{
keybkey=keybkey››1;
keybkey=keybkey | (PIND & 0x20) ‹‹ 2;
}
if (bitcount==11)
{
bitcount=0;
rx_key_buff[rx_key_tale]=keybkey;
rx_key_tale++;
}
}
}
else
{ // rising edge
MCUCR = MCUCR & 0xFE;
if (iscmd)
{
if ((bitcount›0) && (bitcount‹9))
{
PORTD=(PORTD & 0xDF) | ((cmds & 0x01) ‹‹ 5); // данные
if (cmds & 0x01) cmdp=cmdp^0x01;
cmds=cmds››1;
}
if (bitcount==9)
{
if (cmdp) PORTD&=0xDF; else PORTD|=0x20;
iscmd=2;
}
}
}
}
В теле стандартно если счетчик принятых не ноль - обработка что за строка, работа с буферами нажатий-команд, по мере необходимости - готовности отправка из буферов на ноги побитно и прочая муть, к сути проблемы этот фрагмент кода уже не относится, так как запретов прерываний там нет.
Последний раз редактировалось umgah; 08.04.2010 в 13:48.
|
|
|
|
08.04.2010, 14:00
|
|
Временная регистрация
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
|
Re: AVR USART+прерывания=потеря данных
У тебя случаем не первый(ые) байт в строке теряется?
Мне кажется, что во время обработки принятой строки данные продолжают записываться в буффер, а по окончании обработки строки сбрасывается rx_tale и всё что принялось в это время висит в буффере на правах мусора.
Попробуй именно кольцевой буффер использовать с индексами начала и конца валидных данных.
|
|
|
|
08.04.2010, 14:04
|
|
Временная регистрация
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
|
Re: AVR USART+прерывания=потеря данных
|
|
|
|
08.04.2010, 14:05
|
|
Частый гость
Регистрация: 15.01.2007
Сообщений: 20
Сказал спасибо: 3
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: AVR USART+прерывания=потеря данных
не первый, типично - седьмой и далее.
С буфером все просто изумительно. rx_head и rx_tale образуют кольцевую работу на rx_buff ввиду того что rx_buff у меня 256 байт, а rx_head и rx_tale это unsigned char.
То есть, обращение rx_buff[rx_head] ВСЕГДА указывает на определенный байт в буфере, а при переполнении rx_head++ свыше размерности буфера он автоматически по переполнению становится равен 0 и смотрит в начало. Аналогично с rx_tale.
На всякий популярно:
rx_head был равен 255 (0xFF) и смотрел на последний элемент в кольце.
rx_head++
он стал равен нулю по переполнению и смотрит на начало. компактное совершенное решение.
Последний раз редактировалось umgah; 08.04.2010 в 14:08.
|
|
|
|
08.04.2010, 14:07
|
|
Временная регистрация
Регистрация: 30.07.2007
Сообщений: 51
Сказал спасибо: 1
Сказали Спасибо 12 раз(а) в 7 сообщении(ях)
|
Re: AVR USART+прерывания=потеря данных
Да, действительно кольцевой - это хорошо. rx_head в приведенном коде не видно.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 05:30.
|
|