|
Как грамотные люди делают прием пакетов по USART |
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 20)
|
Jun 5 2006, 01:59
|

Местный
  
Группа: Свой
Сообщений: 293
Регистрация: 14-03-06
Пользователь №: 15 254

|
Цитата(kertis @ Jun 5 2006, 05:48)  не очень понял ваше изложение.
Может вам просто буфер создать и спокойно обрабатывать данные когда МК "свооден" ? Буфер нужного размера вам автоматически нарисует CVAVR и пример есть в задаче 5 запрещенного курса. я конечно наченающий но немного соображаю, Буфер у меня 32 байта а информации иной раз и все 200 приходит, поэтому в обработке прерывания по приему байта я делаю так Код interrupt [UART_RXC] void uart_rx_isr(void) { char status,data; int i=2; status=USR; data=UDR; if (data != 0x0A) { if (data != 0x0d) { if ((status & (FRAMING_ERROR | DATA_OVERRUN))==0) { rx_buffer[rx_wr_index]=data; if (++rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0; if (++rx_counter == RX_BUFFER_SIZE) { rx_counter=0; rx_buffer_overflow=1; }; }; } } else; { while(rx_counter != 0x00) { i++; fraza[i]==ReceiveByte(); } } } где fraza переменная в еепроме, но из затого что размер полезных данных может меняться от 4 до 190 байт мне както нужно организовать обработку этих данных, когда начать ??? данные могут идти с разной интенсивностью.
|
|
|
|
|
Jun 5 2006, 02:49
|

Местный
  
Группа: Свой
Сообщений: 293
Регистрация: 14-03-06
Пользователь №: 15 254

|
Цитата(rat @ Jun 5 2006, 06:36)  Принимаемый поток организуете Вы же? Если так, то можно в сообщении передавать длительность посылки, тогда и конец строки не понадобиться. Еще полезно передавать CRC, чтобы ошибки отлавливать. к сожалению не я. Цитата(kertis @ Jun 5 2006, 06:40)  Щас наверно более опытные товарищи подскажут, но я б сделал буфер на 200 символов во-первых. Вы меня натолкнули на мысль что нужно добавить выгрузку и при переполнении буфера. на 200 не могу поскольку 2313 столько не имеет.
|
|
|
|
|
Jun 5 2006, 03:44
|

Местный
  
Группа: Свой
Сообщений: 293
Регистрация: 14-03-06
Пользователь №: 15 254

|
Цитата(haker_fox @ Jun 5 2006, 07:04)  Может быть эта ссылка Вам поможет? Да нет спасибо, протокол не я делаю, есть готовое устройство с которым надо общаться, а вейк я както давно под дельфи реализовывал.
|
|
|
|
|
Jun 5 2006, 05:24
|

Профессионал
    
Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380

|
Идея правильная, вот пример кода который кочует из проекта в проект: Код struct { volatile BYTE mode; volatile WORD timeout; volatile BYTE errc; volatile WORD tx_cnt; volatile WORD tx_len; BYTE* tx_buf; volatile WORD rx_cnt; volatile WORD rx_len; BYTE* rx_buf; } UCB; //UART control block
SIGNAL(SIG_UART_RECV) { //wdt_reset(); SET_RX_BUSY;
UCB.timeout = 0; UCB.rx_buf[UCB.rx_cnt] = UDR;
if(hRxProc) hRxProc();
UCB.rx_cnt++;
if(UCB.rx_cnt >= UCB.rx_len) { CLR_RX_BUSY; if(hRxEnd) hRxEnd(); UCB.rx_cnt = 0; } } Здесь: SET_RX_BUSY - установка флажка занятости UART (пакет в процессе приема) hRxProc() вызов функции для анализа пришедшего байта проинициализиоравна как NULL hRxEnd() вызов функции обработки заполненного буфера. BYTE* tx_buf,rx_buf указатели на объявленные глобально буфера. Теперь самое интересное- UCB.timeout. Один из таймеров умеющий работать в режиме CTC, настроен на генерацию миллисекунд, в его прерывании ин(де)крементируются счетчики задержек, счетчики секунд и UCB.timeout который проверяеться либо в основном контексте либо в hRxProc(), смотря по протоколу. И последнее не надо складывать данные сразу в EEPPROM - он не вечен.
--------------------
Вони шукають те, чого нема, Щоб довести, що його не існує.
|
|
|
|
|
Jun 5 2006, 05:59
|
Знающий
   
Группа: Свой
Сообщений: 550
Регистрация: 16-06-04
Из: Казань
Пользователь №: 32

|
Цитата(TamTam @ Jun 5 2006, 05:11)  Ну написал с горем пополам обработку прирывания по окончанию приема байта, процедурку копирования из буфера в eeprom В курсе, что ресурс EEPROM AVR - 100 тыс. записей? Цитата(TamTam @ Jun 5 2006, 05:11)  Правильно ли я мыслю или может есть способ по приличней, ведь таймер нужная и без этого весчь. Трех стандартных AVR таймеров вполне хватит для чего угодно.
--------------------
Главная линия этого опуса ясна мне насквозь!
|
|
|
|
|
Jun 5 2006, 08:44
|

Профессионал
    
Группа: Свой
Сообщений: 1 065
Регистрация: 8-10-05
Из: Kiev, UA
Пользователь №: 9 380

|
Насколько я понял человек пишет во внутреннюю EEPROM, так-что FRAM в данном случае отдыхает. Я так понял речь идет о записии каких-то параметров или лога, 100 000 циклов за глаза хватит.Поэтому просто надо убедится, что да, данные заехали правильные, в полном объеме, а потом сбрасывать в EEPROM. И еще один нюанс - писать, что во внешнюю, что во внутреннюю память надо вне прерывания - это же время. Вот так вот выходит боком пресловутый "курс".
--------------------
Вони шукають те, чого нема, Щоб довести, що його не існує.
|
|
|
|
|
Jun 5 2006, 09:22
|
Местный
  
Группа: Свой
Сообщений: 232
Регистрация: 22-02-06
Из: Воронеж
Пользователь №: 14 589

|
Цитата(WHALE @ Jun 5 2006, 11:56)  а почем нынче fram ? Пару месяцев назад FM24CL64-S мне привезли по 81.81р. вообщем: http://www.efind.ru/icsearch/?search=FM24
--------------------
Истина рождается в спорах; но когда страсти кипят, истина испаряется.
|
|
|
|
|
Jun 6 2006, 02:06
|

Местный
  
Группа: Свой
Сообщений: 293
Регистрация: 14-03-06
Пользователь №: 15 254

|
Цитата(WHALE @ Jun 5 2006, 09:44)  Судя по 0A,0D-это модем.Действительн,в eeprom зачем постоянно складывать-рано илипоздно откажет. А если нужно энергозависимое с большим обьемом-можно 537ру10 с развязкой по питанию и cs на диодах,а в качесте резервного источника можно конденсатор или аккумулятор-потребление минимально и количество циклов записи неограниченно. kertisДостал,зараза  Да имено модем. Почему именно eeprom ??? да только лиш по тому что ситуация при котором может что то появиться крайне редко может возникнуть, да и лучшебы ей вовсе не возникать, а то люди потеряют баксы, а баксы это для людей святое :-))))
|
|
|
|
|
Jun 6 2006, 09:15
|
Участник

Группа: Новичок
Сообщений: 26
Регистрация: 29-05-06
Из: Netherlands (Delft)/Ukraine (Odessa)
Пользователь №: 17 547

|
Да, обратите внимание на фразу, что в обработчиках прерывания должны быть краткие функции, и не в коем случае писать незя в ЕЕПРОМ, потому что процесс достаточно длителен (мс на байт), выставьте битовую переменную, что нужный пакет в буфере обмена и готовьте следующее окно (я использую двухоконные буфера), когда один заполняется, второй готов и константен для целевой функции - все довольны, а оперирую двумя битовыми флагами, один показывает, что новый буфер подготовлен и ожидает, а второй что какое окно надо пользовать в данный момент целевой функцией, первое может менять в активное состояние прерывание приемника, в пассивное возвращает целевая функция, а окна переключаются в инверсии, да два буфера хватит если есть простой в конце заполнения второго буфера и ждать пока не будет сброшен обработки первого буфера в целевой функции. Когда позволяет выбрать протокол - выбор вообще делаю в пользу битовой синхронизации начала пакета, работает не просто железно, а супержелезно. По таймауту тоже применяю, когда надо минимальная длина пакета с простой упаковкой. Применять шапочную синхронизацию по голове и-или хвосту без таймаутной проверки не стал бы - рискуете потерять часть пакетов и рассинхронизироваться, когда в секторе данных будут шапки - поймете их за служебные - а это только данные на самом деле. Но когда нить конечно синхронизация будет восстановлено, но пакеты патеряны для вас. Можно синхронизировать тройками, когда в секторе данных есть синхросимволы, то повторять их подряд три раза, это знак что это данные. Но это немного увеличит трафик и распаковку пакетов. Да, при таймаутах учитывайте особенности программирования под винду. Обрамляйте процесс передачи пакета в Делфи или Билдере где вы там пишете в РиалТайм процесс, это делается парой строчкой на Делфи но значительно понижает вероятность ложного таймаута внутри пакета. Хотя шанс маленький все равно остается, иногда больший (на раком установленных операционках, высокоприоритетных задачах, выполняемых одновременно с вашим приложением - запись, форматирование дисков  .
|
|
|
|
|
Jun 6 2006, 09:38
|

Местный
  
Группа: Свой
Сообщений: 293
Регистрация: 14-03-06
Пользователь №: 15 254

|
Цитата(Sergiy @ Jun 6 2006, 13:15)  Да, обратите внимание на фразу, что в обработчиках прерывания должны быть краткие функции, и не в коем случае писать незя в ЕЕПРОМ, потому что процесс достаточно длителен (мс на байт), выставьте битовую переменную, что нужный пакет в буфере обмена и готовьте следующее окно (я использую двухоконные буфера), когда один заполняется, второй готов и константен для целевой функции - все довольны, а оперирую двумя битовыми флагами, один показывает, что новый буфер подготовлен и ожидает, а второй что какое окно надо пользовать в данный момент целевой функцией, первое может менять в активное состояние прерывание приемника, в пассивное возвращает целевая функция, а окна переключаются в инверсии, да два буфера хватит если есть простой в конце заполнения второго буфера и ждать пока не будет сброшен обработки первого буфера в целевой функции. Советик дельный, а вот что делать с размерностью буферов, ведь как известно памяти в AT90S2313 всего 128 байт надеюсь 2Х32 мне хватит через глаза.
|
|
|
|
|
Jun 7 2006, 08:03
|
Участник

Группа: Новичок
Сообщений: 26
Регистрация: 29-05-06
Из: Netherlands (Delft)/Ukraine (Odessa)
Пользователь №: 17 547

|
Цитата(TamTam @ Jun 6 2006, 11:38)  Цитата(Sergiy @ Jun 6 2006, 13:15)  Да, обратите внимание на фразу, что в обработчиках прерывания должны быть краткие функции, и не в коем случае писать незя в ЕЕПРОМ, потому что процесс достаточно длителен (мс на байт), выставьте битовую переменную, что нужный пакет в буфере обмена и готовьте следующее окно (я использую двухоконные буфера), когда один заполняется, второй готов и константен для целевой функции - все довольны, а оперирую двумя битовыми флагами, один показывает, что новый буфер подготовлен и ожидает, а второй что какое окно надо пользовать в данный момент целевой функцией, первое может менять в активное состояние прерывание приемника, в пассивное возвращает целевая функция, а окна переключаются в инверсии, да два буфера хватит если есть простой в конце заполнения второго буфера и ждать пока не будет сброшен обработки первого буфера в целевой функции.
Советик дельный, а вот что делать с размерностью буферов, ведь как известно памяти в AT90S2313 всего 128 байт надеюсь 2Х32 мне хватит через глаза. Вообще все просто - надо брать размер буфера не менее чем максимальная длина пакета (он у вас наверное переменно
|
|
|
|
|
Jun 7 2006, 08:15
|
Участник

Группа: Новичок
Сообщений: 26
Регистрация: 29-05-06
Из: Netherlands (Delft)/Ukraine (Odessa)
Пользователь №: 17 547

|
Цитата(TamTam @ Jun 6 2006, 11:38)  Цитата(Sergiy @ Jun 6 2006, 13:15)  Да, обратите внимание на фразу, что в обработчиках прерывания должны быть краткие функции, и не в коем случае писать незя в ЕЕПРОМ, потому что процесс достаточно длителен (мс на байт), выставьте битовую переменную, что нужный пакет в буфере обмена и готовьте следующее окно (я использую двухоконные буфера), когда один заполняется, второй готов и константен для целевой функции - все довольны, а оперирую двумя битовыми флагами, один показывает, что новый буфер подготовлен и ожидает, а второй что какое окно надо пользовать в данный момент целевой функцией, первое может менять в активное состояние прерывание приемника, в пассивное возвращает целевая функция, а окна переключаются в инверсии, да два буфера хватит если есть простой в конце заполнения второго буфера и ждать пока не будет сброшен обработки первого буфера в целевой функции.
Советик дельный, а вот что делать с размерностью буферов, ведь как известно памяти в AT90S2313 всего 128 байт надеюсь 2Х32 мне хватит через глаза. Вообще все просто - надо брать размер буфера не менее чем максимальная длина пакета (он у вас наверное переменной длины - выберите максимальный вариант) - если же пакет больше, то такая буферизация вам не подходит. Странный выбор контроллера на 2006 год, надеюсь что выбор продиктован только тем, что у вас есть какая то готовая плата пятилетней давности, и вы ее хотите использовать. Потому что щас можно дешевле купить то, что получше, например Атмега8 - стоит в Украине чуть больше евро - интересно сколько стоит ваш кристалл. Так вот если все таки максимально длинная команда больше размера того, что вы ей можете предложить, то замедляйте обмен (скорость, интервалы между байтами в одном пакете), используйте буферизацию, но выполнение выгрузки из буфера прийдется начинать тогда, когда вы не дошли до конца пакета. В основном цикле сканируйте флаг наличия нового байта в буфере (буфер должен быть кольцевой), если есть - делайте выемку байта - сдвиг указателя кольцевого буфера на -1 и запись в ЕЕПРОМ, и так постоянно. Выбор невелик. Пример реализации кольцевого буфера на cvavr: #define RX_BUFFER_SIZE1 32 //size of rx buffer unsigned char rx_buffer[RX_BUFFER_SIZE1+1]; register unsigned char rxr_pntr=0, rxw_pntr = 0; // UART Receiver interrupt service routine //-------------------------------------------------------------------------- // Procedure of RXD interrupt processing //-------------------------------------------------------------------------- interrupt [USART_RXC] void uart_rx_isr(void) { unsigned char temp_byte; temp_byte=UDR; rx_buffer[rxw_pntr]=temp_byte; if (rxw_pntr < RX_BUFFER_SIZE1-1) rxw_pntr++; else rxw_pntr=0; } //-------------------------------------------------------------------------- // Extract a byte from rx-buffer if buffer isn't empty //-------------------------------------------------------------------------- void check_rx_buffer() { unsigned char current_byte_from_buffer; if (rxr_pntr != rxw_pntr) { #asm("cli"); current_byte_from_buffer=rx_buffer[rxr_pntr]; if (rxr_pntr < RX_BUFFER_SIZE1-1) rxr_pntr++; else rxr_pntr=0; #asm("sei"); rx_buffer_processor(current_byte_from_buffer); <- ваша целевая функция над текущем байтом } } Удачи
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|