Перейти к содержанию
    

Как грамотные люди делают прием пакетов по USART

Мне понравилось как у Атмела сделано. Я такую конструкцию не только для уарта применяю, но и вообще где надо стыковать асинхронные процессы. Также в примерах исходников prottos привел классный драйверок - аналог. На прием естественно надо таймаут ставить - после приема каждого байта заряжать таймер. Если нет данных в течение опеределенного времени - сбрасываем стэк. Кроме кольцевого буфера нужен буфер для сборки принимаемых пакетов и буфер для сборки отправляемых пакетов. А на будущее - haker_fox далл ссылку на прекрасный на мой субъективный взгляд протокол. Сам его повсеместно использую. Четко и стабильно работает. Програмная реализация тоже есть в исходниках.

avr306.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне понравилось как у Атмела сделано. Я такую конструкцию не только для уарта применяю, но и вообще где надо стыковать асинхронные процессы. Также в примерах исходников prottos привел классный драйверок - аналог. На прием естественно надо таймаут ставить - после приема каждого байта заряжать таймер. Если нет данных в течение опеределенного времени - сбрасываем стэк. Кроме кольцевого буфера нужен буфер для сборки принимаемых пакетов и буфер для сборки отправляемых пакетов. А на будущее - haker_fox далл ссылку на прекрасный на мой субъективный взгляд протокол. Сам его повсеместно использую. Четко и стабильно работает. Програмная реализация тоже есть в исходниках.

 

Да WAKE штука хорошая. Я его тоже однажды применял. но железо не моё было я токо под дельфю переписывал. Хотел библу с исходником выложить да так и потерял сурц а библа гдето лежит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, обратите внимание на фразу, что в обработчиках прерывания должны быть краткие функции, и не в коем случае писать незя в ЕЕПРОМ, потому что процесс достаточно длителен (мс на байт), выставьте битовую переменную, что нужный пакет в буфере обмена и готовьте следующее окно (я использую двухоконные буфера), когда один заполняется, второй готов и константен для целевой функции - все довольны, а оперирую двумя битовыми флагами, один показывает, что новый буфер подготовлен и ожидает, а второй что какое окно надо пользовать в данный момент целевой функцией, первое может менять в активное состояние прерывание приемника, в пассивное возвращает целевая функция, а окна переключаются в инверсии, да два буфера хватит если есть простой в конце заполнения второго буфера и ждать пока не будет сброшен обработки первого буфера в целевой функции.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, обратите внимание на фразу, что в обработчиках прерывания должны быть краткие функции, и не в коем случае писать незя в ЕЕПРОМ, потому что процесс достаточно длителен (мс на байт), выставьте битовую переменную, что нужный пакет в буфере обмена и готовьте следующее окно (я использую двухоконные буфера), когда один заполняется, второй готов и константен для целевой функции - все довольны, а оперирую двумя битовыми флагами, один показывает, что новый буфер подготовлен и ожидает, а второй что какое окно надо пользовать в данный момент целевой функцией, первое может менять в активное состояние прерывание приемника, в пассивное возвращает целевая функция, а окна переключаются в инверсии, да два буфера хватит если есть простой в конце заполнения второго буфера и ждать пока не будет сброшен обработки первого буфера в целевой функции.

 

Советик дельный, а вот что делать с размерностью буферов, ведь как известно памяти в AT90S2313

всего 128 байт надеюсь 2Х32 мне хватит через глаза.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, обратите внимание на фразу, что в обработчиках прерывания должны быть краткие функции, и не в коем случае писать незя в ЕЕПРОМ, потому что процесс достаточно длителен (мс на байт), выставьте битовую переменную, что нужный пакет в буфере обмена и готовьте следующее окно (я использую двухоконные буфера), когда один заполняется, второй готов и константен для целевой функции - все довольны, а оперирую двумя битовыми флагами, один показывает, что новый буфер подготовлен и ожидает, а второй что какое окно надо пользовать в данный момент целевой функцией, первое может менять в активное состояние прерывание приемника, в пассивное возвращает целевая функция, а окна переключаются в инверсии, да два буфера хватит если есть простой в конце заполнения второго буфера и ждать пока не будет сброшен обработки первого буфера в целевой функции.

 

Советик дельный, а вот что делать с размерностью буферов, ведь как известно памяти в AT90S2313

всего 128 байт надеюсь 2Х32 мне хватит через глаза.

 

Вообще все просто - надо брать размер буфера не менее чем максимальная длина пакета (он у вас наверное переменно

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да, обратите внимание на фразу, что в обработчиках прерывания должны быть краткие функции, и не в коем случае писать незя в ЕЕПРОМ, потому что процесс достаточно длителен (мс на байт), выставьте битовую переменную, что нужный пакет в буфере обмена и готовьте следующее окно (я использую двухоконные буфера), когда один заполняется, второй готов и константен для целевой функции - все довольны, а оперирую двумя битовыми флагами, один показывает, что новый буфер подготовлен и ожидает, а второй что какое окно надо пользовать в данный момент целевой функцией, первое может менять в активное состояние прерывание приемника, в пассивное возвращает целевая функция, а окна переключаются в инверсии, да два буфера хватит если есть простой в конце заполнения второго буфера и ждать пока не будет сброшен обработки первого буфера в целевой функции.

 

Советик дельный, а вот что делать с размерностью буферов, ведь как известно памяти в 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); <- ваша целевая функция над текущем байтом

}

}

 

 

Удачи

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...