реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Какова "реальная" скорость UART?
altlogic
сообщение Jun 2 2008, 23:15
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Здравствуйте!

Стояла задача добиться максимальной скорости обмена по UART в Atmega128. Со стороны мк была написана небольшая програмка для измерения скорости обмена. Передача осуществляется в режиме прерывания.
Код
#define TX_BUFFER_SIZE 128
char tx_buffer[TX_BUFFER_SIZE];

#if TX_BUFFER_SIZE<256
unsigned char tx_wr_index,tx_rd_index,tx_counter;
#else
unsigned int tx_wr_index,tx_rd_index,tx_counter;
#endif

// USART0 Transmitter interrupt service routine
interrupt [USART0_TXC] void usart0_tx_isr(void)
{
if (tx_counter)
   {
   --tx_counter;
   UDR0 = tx_buffer[tx_rd_index];
   if (++tx_rd_index == TX_BUFFER_SIZE)
      tx_rd_index=0;
   };
}

// Write a character to the USART0 Transmitter buffer
#pragma used+
int COM_putchar(unsigned char c)
{
while (tx_counter == TX_BUFFER_SIZE);
#asm("cli")
if (tx_counter || ((UCSR0A & DATA_REGISTER_EMPTY)==0))
   {
   tx_buffer[tx_wr_index]=c;
   if (++tx_wr_index == TX_BUFFER_SIZE)
   {        
      tx_wr_index=0;
   }
   ++tx_counter;
   }
else
   UDR0=c;
#asm("sei")
return 1;//<!
}

в main:

unsigned long int tx_cnt; // счётчик переданных байт
_включили_таймер
   if( ++tx_cnt < 65535 )
   {      
      COM_putchar(0x55);    
   }
_остановили_таймер

В теории скорость передачи BAUD = 115200 бит/с. Передаём один старт-бит, 8 бит данных, один стоп-бит, итого 10 бит на передачу одного байта данных.
На деле получаю:
передано 65535 байт;
время: 6,2с.
Считаем BAUD: 65535*10/6,2 = 105702 бит/с.

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

Сообщение отредактировал altlogic - Jun 2 2008, 23:17


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
repairDV
сообщение Jun 3 2008, 00:50
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 578
Регистрация: 7-11-06
Из: Хабаровск
Пользователь №: 22 044



Цитата(altlogic @ Jun 3 2008, 10:15) *
Не дотягивает передатчик до любой из стандартных скоростей, которую я выбирал. Может так и должно быть? Или стоит искать ошибки программы?

Да, и это, скорее всего - потому, что у вас такая большая программа. Пока-то проц это всё обработает. Для обмена по uart нужно всего-то несколько ассемблерных строк. К тому же, если скорость обмена по uart в проце не будет совпадать со скоростью обмена по COM-порту в компьютере IBM, то как будет осуществляться связь между ними?


--------------------
Маленький нанайца. А-а. А-а. Оморочком плыл. Маленький проточка. Осетра ловил.
Go to the top of the page
 
+Quote Post
altlogic
сообщение Jun 3 2008, 01:12
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Цитата(repairDV @ Jun 3 2008, 11:50) *
Да, и это, скорее всего - потому, что у вас такая большая программа.

Не понял если честно... Вы хотите сказать, что мой проц не успевает готовить данные для буфера передатчика?
Цитата
К тому же, если скорость обмена по uart в проце не будет совпадать со скоростью обмена по COM-порту в компьютере IBM, то как будет осуществляться связь между ними?

опять не понял... Скорость обмена по протоколу uart и на компьютере и на мк выставлена 115200 бит/с. Вот я и хочу, чтобы мк при постоянной загрузке буфера передатчика передавал ровно 115200 бит за секунду, а не ~105000, как у меня сейчас. Ясно, что скорость обмена(115200) я менять не собираюсь.

Сообщение отредактировал altlogic - Jun 3 2008, 01:21


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
repairDV
сообщение Jun 3 2008, 02:58
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 578
Регистрация: 7-11-06
Из: Хабаровск
Пользователь №: 22 044



Цитата(altlogic @ Jun 3 2008, 12:12) *
бит за секунду, а не ~105000, как у меня сейчас. Ясно, что скорость обмена(115200) я менять не собираюсь.

Тут, вероятно, просто нужна настройка. Уже давно не общался с AVR, позабыл, как там настраивается uart. Скорее всего, у вас просто рассогласование по частоте. Нужно подбирать кварц, чтобы не было круглой цифры в мГц. Например, для 51серии стандартная частота кварца - 11,0592 мГц, а не 12 мГц - и только для обеспечения точного согласования для модуля uart. Поэтому, если вы предусматриваете использование асинхронного передатчика, то нужно подбирать кварцы, кратные этому значению - 11,0592. Скажем, 3,6864 мГц вместо 4 мгц, и т.п. Для большей точности лучше, конечно, подбирать частоту по осциллографу, перебирая те данные, которые вы записывете в таймер, если у вас uart работает от таймера.


--------------------
Маленький нанайца. А-а. А-а. Оморочком плыл. Маленький проточка. Осетра ловил.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 3 2008, 03:03
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(altlogic @ Jun 3 2008, 03:15) *
Не дотягивает передатчик до любой из стандартных скоростей, которую я выбирал. Может так и должно быть? Или стоит искать ошибки программы?

Используйте вместо прерывания по завершению передачи (TXC) прерывание по опустошению DATA-регистра (DRE). Так Вы убиваете даже ту мизерную буферизацию, что имеется в Меге.
Go to the top of the page
 
+Quote Post
altlogic
сообщение Jun 3 2008, 03:14
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Цитата(repairDV @ Jun 3 2008, 13:58) *
Тут, вероятно, просто нужна настройка. Уже давно не общался с AVR, позабыл, как там настраивается uart. Скорее всего, у вас просто рассогласование по частоте. Нужно подбирать кварц, чтобы не было круглой цифры в мГц. Например, для 51серии стандартная частота кварца - 11,0592 мГц, а не 12 мГц - и только для обеспечения точного согласования для модуля uart. Поэтому, если вы предусматриваете использование асинхронного передатчика, то нужно подбирать кварцы, кратные этому значению - 11,0592. Скажем, 3,6864 мГц вместо 4 мгц, и т.п. Для большей точности лучше, конечно, подбирать частоту по осциллографу, перебирая те данные, которые вы записывете в таймер, если у вас uart работает от таймера.

Вероятно это моя ощибка. Недостаточно чётко изложил свою проблему. Действительно я использую кварц 3,6864МГц, осцилографом не проверял, но сбоев при приёме/передаче за время отладки ни разу не наблюдал. Рассогласование по частоте здесь ни при чём. С уарта я просто пихаю данные "в никуда", то есть на приёмной стороне их никто не принимает(упростим задача, на самом деле конечно не такsmile.gif Так вот я не могу добиться скорости выставления данных "в никуда" на 115200.

Цитата(aaarrr @ Jun 3 2008, 14:03) *
Используйте вместо прерывания по завершению передачи (TXC) прерывание по опустошению DATA-регистра (DRE). Так Вы убиваете даже ту мизерную буферизацию, что имеется в Меге.

А вот это уже похоже на истину... Попробую проверить!


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Jun 3 2008, 04:04
Сообщение #7


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(altlogic @ Jun 3 2008, 03:15) *
В теории скорость передачи BAUD = 115200 бит/с. Передаём один старт-бит, 8 бит данных, один стоп-бит, итого 10 бит на передачу одного байта данных.

на самом деле 11.
забыли бит четности. Если проверка на четность не включена, это ещё не значит, что бит не передаётся.
Так что подкорректируем ваш результат: 105000*11/10=115500. Где-то так.

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


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
altlogic
сообщение Jun 3 2008, 04:45
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Цитата(MrYuran @ Jun 3 2008, 15:04) *
на самом деле 11.
забыли бит четности. Если проверка на четность не включена, это ещё не значит, что бит не передаётся.
Так что подкорректируем ваш результат: 105000*11/10=115500. Где-то так.

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

Если считать, что передано 11 бит, то скорость действительно сходится ( если учесть погрешность таймера). Коэффициент целый, частота делится без погрешности (3 686 400 / 115200 = 32).
Бит чётности проверю на осцилографеsmile.gif ДШ как-то невнятно пишет. А вот заставить работать мегу по прерыванию опустошения DATA-регистра у меня не получается.
переписал свой обработчик прерывания с
Код
interrupt [ USART0_TXC] void usart0_TXC_isr(void)

на
Код
interrupt [ USART0_DRE ] void usart0_UDRE_isr(void)

вектора объявлены в стандартном хидере
Код
#define USART0_DRE 20
#define USART0_TXC 21

Результат: мк сбрасывается при передаче семи символов. Может надо было не только объявление прерывания поменять?..

Сообщение отредактировал altlogic - Jun 3 2008, 04:47


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 3 2008, 04:54
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(MrYuran @ Jun 3 2008, 08:04) *
на самом деле 11.
забыли бит четности. Если проверка на четность не включена, это ещё не значит, что бит не передаётся.

Это, ИМХО, из разряда гадания на кофейной гуще. Код инициализации мы не видели.

Цитата(altlogic @ Jun 3 2008, 08:45) *
мк сбрасывается при передаче семи символов. Может надо было не только объявление прерывания поменять?..

Разрешение TXC убрали?

С точки зрения обработки разница только в том, что DRE активно еще до начала передачи.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jun 3 2008, 06:00
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(altlogic @ Jun 3 2008, 02:15) *
Стояла задача добиться максимальной скорости обмена по UART в Atmega128. ...
Код
...
#asm("cli")
if (tx_counter || ((UCSR0A & DATA_REGISTER_EMPTY)==0))
   {
   tx_buffer[tx_wr_index]=c;
   if (++tx_wr_index == TX_BUFFER_SIZE)
   {        
      tx_wr_index=0;
   }
   ++tx_counter;
   }
else
   UDR0=c;
#asm("sei")
return 1;//<!
}
...
C буфером передачи Вы, ИМХО, намудрили... По всей вероятности переменная tx_counter инициируется нулём, поэтому выражение в операторе if будет ложным всегда. (P.S. Тут я немного соврал, но правильность условия в первом if - очень сомнительна!) Использовать желательно прерывание UDE для добавления аппаратной буферизации.
Цитата(altlogic @ Jun 3 2008, 07:45) *
Результат: мк сбрасывается при передаче семи символов. Может надо было не только объявление прерывания поменять?..
Вероятно, добавили UDE, исправили прерывание, но не убрали разрешение прерывания по TXC, а обработчика прерывания уже - нет! Если разрешено какое-либо прерывание, а соответствующего обработчика нет, микроконтроллер попадает на адрес 0, и всё - заново.
Go to the top of the page
 
+Quote Post
altlogic
сообщение Jun 3 2008, 07:15
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Цитата(aaarrr @ Jun 3 2008, 15:54) *
Код инициализации мы не видели.

Код
//#define _USART0_TXC_INTERRUPT_
void COM_init( unsigned int ubrr )
{
    UBRR0H = (unsigned char) (ubrr>>8);                       //Setting baudrate
    UBRR0L = (unsigned char) ubrr;                            //Setting baudrate
    #ifdef _USART0_TXC_INTERRUPT_
      UCSR0B = ( 1 << RXEN0 ) | ( 1 << TXEN0 );                     //Enable receiver and transmitter
    #else
      UCSR0B = ( 1 << RXEN0 )  ( 1 << TXEN0 ) | (1 << UDRIE0) |;                     //Enable receiver
    #endif
    UCSR0C = ( 1 << UCSZ01 ) | ( 1 << UCSZ00 );  //8N1...see Datasheet for more information
    UCSR0A=0x00;
    COM_rx_reset();
    COM_tx_reset();                                               //Reset buffers etc.        
}
void COM_rx_reset( void )
{
    COM_rx_off();       // Disable RX interrupt
    rx_i = rx_wr_i = 0;           //Init variables
    rx_overflow = rx_ack = 0;     //Zero overflow flag
    rx_buffer[ rx_wr_i ] = '\0';  //Buffer init.
}  

void COM_tx_reset( void )
{
    COM_tx_off();       // Disable RX interrupt
    tx_wr_index = 0;
    tx_rd_index = 0;
    tx_counter = 0;    
}

void COM_rx_on( void )
{
    UCSR0B |= ( 1 << RXCIE0 );  // Enable RX interrupt
}


void COM_rx_off( void )
{
    UCSR0B &= ~( 1 << RXCIE0 ); // Disable RX interrupt
}

void COM_tx_on( void )
{    
    UCSR0B |= ( 1 << TXCIE0 );  // Enable TX interrupt
}

void COM_tx_off( void )
{
    UCSR0B &= ~( 1 << TXCIE0 ); // Disable TX interrupt
}

#ifdef _USART0_TXC_INTERRUPT_

//<! USART0_TXC - tx complete

interrupt [ USART0_TXC ] void usart0_TXC_isr(void)
{
if ( tx_counter )
   {
   --tx_counter;
   UDR0 = tx_buffer[tx_rd_index];
   if (++tx_rd_index == TX_BUFFER_SIZE)
      tx_rd_index=0;
   };
}

#else

//<! USART0_DRE - usart data register emptry

interrupt [ USART0_DRE ] void usart0_UDRE_isr(void)
{
if ( tx_counter )
   {
   --tx_counter;
   UDR0 = tx_buffer[tx_rd_index];
   if (++tx_rd_index == TX_BUFFER_SIZE)
      tx_rd_index=0;
   };
}

#endif

...
void main(void)
{
...
//<! USART0 initialization (UBRR = 0x01 = 115200 @ 3.6864MHz)
COM_init(0x01);  
...
}

С объявленным _USART0_TXC_INTERRUPT_ передатчик работает в четыре раза быстрее.

Цитата(Палыч @ Jun 3 2008, 17:00) *
C буфером передачи Вы, ИМХО, намудрили... По всей вероятности переменная tx_counter инициируется нулём, поэтому выражение в операторе if будет ложным всегда. (P.S. Тут я немного соврал, но правильность условия в первом if - очень сомнительна!) Использовать желательно прерывание UDE для добавления аппаратной буферизации.
Вероятно, добавили UDE, исправили прерывание, но не убрали разрешение прерывания по TXC, а обработчика прерывания уже - нет! Если разрешено какое-либо прерывание, а соответствующего обработчика нет, микроконтроллер попадает на адрес 0, и всё - заново.

Про прерывания по TXC вы правильно заметили


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jun 3 2008, 07:56
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



По-моему, Вам уже всё обьяснили... Или остались вопросы?
Максимальной скорости (той, что выставлена в USART) передачи байтов можно добиться, если программа в МК будет класть очередной байт в UDR до того, как освободится сдвиговый регистр USART. При этом, по окончанию передачи байта из сдвигового регистра, в него будет взят следующий байт из UDR и немедленно начнется его передача. Можно ли положить очередной байт в UDR? - определяется флагом и прерыванием UDRE. Ваша программа должна как можно скорее положить данные в UDR при его освобождении. Как быстро Вы это сможите обеспечить определяется тактовой частотой МК и как долго закрыты прерывания (при работе по прерываниям).
На практике реализовал скорость в 2Мбод, так-что 115К - не такая уж и высокая скорость и выжать из неё всё, что можно не большая проблема...
Go to the top of the page
 
+Quote Post
lolful
сообщение Jun 3 2008, 17:49
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 106
Регистрация: 27-11-07
Из: Пермь
Пользователь №: 32 732



Я наверно скажу глупость, но мне всегда казалось, что "стартовый бит" длится 2 бита...Поправьте, если это действительно ересь.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 3 2008, 17:59
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Ересь smile.gif
Стартовый бит всегда один, количество стоповых может отличаться.
Go to the top of the page
 
+Quote Post
altlogic
сообщение Jun 3 2008, 21:53
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Всем участникам спасибо! Сегодня утром на свежую голову разобрался в вопросе, сделал НОРМАЛЬНО прерывания по пустому Data Register, и получил свои 115 200 на передатчике. Вот теперь встанет следующий вопрос - добиться 115 200 на приёмникеsmile.gif У меня там тоже прерывания по окончанию приёма. Пока не проверял, но боюсь и там будет та же картина.
Код
interrupt [USART1_RXC] void usart1_rx_isr(void)
{
char status,data;
status=UCSR1A;
data=UDR1;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer1[rx_wr_index1]=data;
   if (++rx_wr_index1 == RX1_BUFFER_SIZE) rx_wr_index1=0;
   if (++rx_counter1 == RX1_BUFFER_SIZE)
      {
      rx_counter1=0;
      rx_buffer_overflow1=1;
      };
   };
}


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
LeonY
сообщение Jun 3 2008, 22:37
Сообщение #16


Знающий
****

Группа: Админы
Сообщений: 689
Регистрация: 24-06-04
Из: South Africa
Пользователь №: 164



Цитата(MrYuran @ Jun 3 2008, 06:04) *
на самом деле 11.
забыли бит четности. Если проверка на четность не включена, это ещё не значит, что бит не передаётся.
Так что подкорректируем ваш результат: 105000*11/10=115500. Где-то так.

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

Можно пояснить выделенное? А то как-то не понятно: сам ваял UART-ы (неоднократно) и всегда делал так что, если не включена то и не передается. С приемом на самых разных устройствах проблем никогда не было... А когда рассогласуешь Rx/Tx по контролю на PARITY - сразу FRAMING ERRORS валятся как из рога изобилия (Tx передает PARITY, а Rx его не ожидает). Ну и еще куча всяких побочных эффектов...

11 битов могут возникать при установке 2-х STOP Bits (их может быть 1, 1.5, 2)


--------------------
"В мире есть две бесконечные вещи: Вселенная и человеческая глупость. За Вселенную, впрочем, поручиться не могу". (С)

А. Эйнштейн.
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Jun 4 2008, 03:48
Сообщение #17


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Бит четности не передается, если четность не включена. Разумеется.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
WHALE
сообщение Jun 4 2008, 05:54
Сообщение #18


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



а зачем 2 индекса-rx_wr_index1 и rx_counter1?


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
altlogic
сообщение Jun 4 2008, 07:02
Сообщение #19


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Там вообще три переменных под индексы: rx_wr_index1 , rx_rd_index1, rx_counter1.
Таким образом реализовано безконфликтное обращение двух потоков функций к одному буферу.
rx_counter1 - количество несчитанных символов в программном буфере rx_buffer1
rx_wr_index1 - индекс для записи символа из регистра UDR1 в rx_buffer1 во время прерывания
rx_rd_index1 - индекс для чтения символа из rx_buffer1 функцией getchar()

К слову сказать передатчик пришлось "доделать". Прерывания по DRE необходимо отключать после того, как [b]программный[b] буфер UART пуст. А то прерывание постоянно возникает, и не даёт работать системе. И соответственно включать его надо всякий раз при выводе символа функцией putchar.


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 4 2008, 09:45
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(altlogic @ Jun 4 2008, 01:53) *
Вот теперь встанет следующий вопрос - добиться 115 200 на приёмникеsmile.gif У меня там тоже прерывания по окончанию приёма. Пока не проверял, но боюсь и там будет та же картина.

Проверку FRAMING-PARITY-OVERRUN можно смело выбросить - толку от нее никакого, а время сожрет.
С приемом проблем быть не должно.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jun 4 2008, 10:38
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(aaarrr @ Jun 4 2008, 12:45) *
Проверку FRAMING-PARITY-OVERRUN можно смело выбросить - толку от нее никакого, а время сожрет.

Толк весьма существенен. Например экономия времени smile.gif
Если произошла одна из ошибок, автомат приема можно сразу перевести на ожидание нового пакета, не дожидаясь окончания приема пакета, проверки контрольной суммы и проч.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 4 2008, 10:48
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Dog Pawlowa @ Jun 4 2008, 14:38) *
Толк весьма существенен. Например экономия времени smile.gif
Если произошла одна из ошибок, автомат приема можно сразу перевести на ожидание нового пакета, не дожидаясь окончания приема пакета, проверки контрольной суммы и проч.

Ага, сэкономите, как же smile.gif
Представьте: принимаем пакет из 16 байт, в 7-м Framing Error - и что делать? Считать следующий байт началом нового пакета? Кричать караул?

Правильным решением будет наплевать на ошибки и принять пакет до конца - пусть верхний уровень разбирается, нормальный пришел пакет, или нет. Как раз с помощью контрольной суммы, CRC и т.п.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jun 4 2008, 11:20
Сообщение #23


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(aaarrr @ Jun 4 2008, 13:48) *
Ага, сэкономите, как же smile.gif
Представьте: принимаем пакет из 16 байт, в 7-м Framing Error - и что делать? Считать следующий байт началом нового пакета? Кричать караул?

Правильным решением будет наплевать на ошибки и принять пакет до конца - пусть верхний уровень разбирается, нормальный пришел пакет, или нет. Как раз с помощью контрольной суммы, CRC и т.п.

Я думаю, что правильное решение для каждой ситуации свое и ситуация сильно зависит от протокола.
Например:
- контрольная сумма простая, вероятность ее случайного совпадения достаточно велика, не контролировать паритет при приеме рискованно. Не хочется переходить на начало - можно флаг поставить.
- есть протоколы, где EOT в потоке должно прекращать прием, то есть эта ветка(перехода на начало) все равно существует.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 4 2008, 11:51
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Ну, если специально придумать плохой протокол и добавить к нему передачу с контролем паритета (которую никто не использует обычно), то смысл может быть.

Но это именно из разряда придумывания себе проблем, ИМХО.
Go to the top of the page
 
+Quote Post
altlogic
сообщение Jun 4 2008, 12:14
Сообщение #25


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Цитата(aaarrr @ Jun 4 2008, 20:45) *
Проверку FRAMING-PARITY-OVERRUN можно смело выбросить - толку от нее никакого, а время сожрет.
С приемом проблем быть не должно.

Спасибо за замечание. У меня никакого потокола верхнего уровня нет. UART используется для обмена между мк и gsm-модемом в пределах одной платы. Поэтому я исхожу из предположения, что ошибок быть не может в принципе.


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Jun 5 2008, 10:37
Сообщение #26


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Протокол верхнего уровня, это когда вы принятую строку от модема анализируете. И если пришло что-то вам непонятное (в результате какой-либо ошибки)- то отвергаете с негодованием и считаете предыдущую команду невыполненной. При этом природа ошибки вас не интересует (все равно природу не изменишь и вариантов тут нет.)
Ну или еще как-то...


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
altlogic
сообщение Jun 5 2008, 11:35
Сообщение #27


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Что-то просел я с реализацией RTS/CTS протокола. Никак не могу придумать алгоритм быстрой связи. Почитал http://electronix.ru/forum/index.php?act=P...amp;qpid=133018 понял, так, что RTS/CTS не обязательно обрабатывать в режиме прерывания. Можно сделать буфер передатчика скажем байт на восемь, и не записывать в него, пока CTS равен единице(модем не готов). А вот прерывание по пустому DATA REGISTER пусть крутится, но до тех пор пока программный буфер не пуст.
В общем пока что я теряю байты при передаче их модему, не могу понять где.
Приведу сразу и переписанный код
Код
int COM_tx_on( void )
{
   UCSR0B |= ( 1 << UDRIE0 );  // Enable TX UDRE interrupt
   return 1;
}

void COM_tx_off( void )
{                                
      UCSR0B &= ~( 1 << UDRIE0 );  // Disable TX interrupt
}

//<! USART0_DRE - usart data register emptry
interrupt [ USART0_DRE ] void usart0_UDRE_isr(void)
{  
   if ( tx_counter > 0 )
   {                  
      #asm("cli")
      --tx_counter; //<! неделимая операция
      #asm("sei")
      UDR0 = tx_buffer[tx_rd_index];
      if (++tx_rd_index == TX_BUFFER_SIZE)
         tx_rd_index=0;
   }
   else
   {
      COM_tx_off();
   }  
}

int COM_putchar(unsigned char c)
{          
   char tx = 0;
   while( !tx )
   {
      if( !CTS )
      {          
         if( tx_counter != TX_BUFFER_SIZE )
         {      
            tx_buffer[tx_wr_index]=c;
            COM_tx_on();        
            if (++tx_wr_index == TX_BUFFER_SIZE)
            {        
               tx_wr_index=0;
            }  
            #asm("cli")          
            ++tx_counter;            
            #asm("sei")
            tx = 1; //<! break from while
         }  
      }      
   }      
   return 1;
}


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 5 2008, 13:02
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(altlogic @ Jun 5 2008, 15:35) *


Код
//<! USART0_DRE - usart data register emptry
interrupt [ USART0_DRE ] void usart0_UDRE_isr(void)
{  
   if ( tx_counter > 0 )
   {                  
    //  #asm("cli")    <-- aaarrr Лишнее действие: прерывания уже запрещены
      --tx_counter; //<! неделимая операция
    //  #asm("sei")    <-- aaarrr А это уже просто опасно
      UDR0 = tx_buffer[tx_rd_index];
      if (++tx_rd_index == TX_BUFFER_SIZE)
         tx_rd_index=0;
   }
   else
   {
      COM_tx_off();
   }  
}

int COM_putchar(unsigned char c)
{          
   char tx = 0;
   while( !tx )
   {
      if( !CTS )
      {          
         if( tx_counter != TX_BUFFER_SIZE )
         {      
            tx_buffer[tx_wr_index]=c;
//            COM_tx_on();    <-- aaarrr Здесь включать передатчик рано, он может тут же запретить UDR        
            if (++tx_wr_index == TX_BUFFER_SIZE)
            {        
               tx_wr_index=0;
            }  
            #asm("cli")          
            ++tx_counter;            
            #asm("sei")
            COM_tx_on();
            tx = 1; //<! break from while
         }  
      }      
   }      
   return 1;
}
Go to the top of the page
 
+Quote Post
altlogic
сообщение Jun 5 2008, 13:40
Сообщение #29


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 2-12-06
Из: г. Хабаровск
Пользователь №: 23 035



Спасибо, теперь вроде ничего не теряюsmile.gif Только я не понял
Код
//  #asm("cli")    <-- aaarrr Лишнее действие: прерывания уже запрещены

При входе в прерывание происходит глобальное запрещение прерываний? Т.е. из одного прерывания в другое меня не выбросит, если не делать так?
Код
//  #asm("sei")    <-- aaarrr А это уже просто опасно


--------------------
С уважением, Вячеслав
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 5 2008, 13:54
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Да, при входе в прерывание прерывания запрещаются глобально.
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 10:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01728 секунд с 7
ELECTRONIX ©2004-2016