имеется железка, которая раз в 20мс шлет пакетик длительностью 1.5-2.0мс (18 байт) по com-порту. собрал схему (код прилагается):
по таймеру раз в 50мс (точнее не нужно) опрашивается порт, читается 18 байт, скидывается в символьный массив, затем посимвольно передается на обработку (на схеме не показано). первые два символа должны быть с кодами 85, 252, если это не так - строка забраковывается.
проблема в том, что как не игрался с задержками и таймаутами процент ошибок довольно велик, 10-15% всех принятых строк начинаются не с ключевых символов. причем если просматривать строку целиком, то видно, что ловится конец одной посылки и начало второй. вопрос: можно как-то точнее синхронизировать сей процесс?
вторая ситуация, эта же железка в другом режиме посылает подряд 5 пакетов с разной длиной (13, 12, 12, 12, 15 байт), причем маркер начала есть только в первом пакете, а контрольная сумма только в последнем. из-за вышеописанной потери строки приходится долго ждать правильно принятых пакетов, ибо какая-нить одна строка возьмет и скосячится.
может есть более точный механизм чтения com-порта?
code_16508.txt
Этот топик читают: Гость
Ответов: 499
Рейтинг: 1
|
|||
карма: 0 |
| ||
файлы: 1 | code_16508.txt [2.2KB] [134] |
Разработчик
Ответов: 26160
Рейтинг: 2127
|
|||
После окончания времени кадра (если это не непрерывная последовательность), автоматически выставляется пустой символ, почему нельзя его использовать Это первое, второе: строка должна читаться всегда целиком, а затем браковаться, а не останавливаться накопление в середине цикла чтения, что у тебя сделано, иначе -- будет полная рассинхронизация в твоем случае, тк ты не используешь пустой символ для дополнительной синхронизации с концом посылки
|
|||
карма: 22 |
|
Ответов: 8926
Рейтинг: 823
|
|||
HikeR, кроме того, если читать именно по 18 байт, да через 50 мсек, нечего удивляться, что попадает окончание предыдущей строки и начало следующей
Всё принятое в этом случае надо сцеплять в одну строку и уже её парсить, удаляя просчитанное |
|||
карма: 19 |
|
Разработчик
Ответов: 26160
Рейтинг: 2127
|
|||
Вот такой модуль у меня работает для синхронизации по пустому символу
Леонид писал(а): кроме того, если читать именно по 18 байт, да через 50 мсек, нечего удивляться, что попадает окончание предыдущей строки и начало следующейБрехня. Я считываю 21 байт каждые 10 msес и никуда у меня ничего не пропадает и нет никакой рассинхронизации. Ты забыл про буфер FIFO, который автоматически накапливает принятую информацию, а уже ты ее считывешь из этого буфера |
|||
карма: 22 |
|
Ответов: 499
Рейтинг: 1
|
|||
nesco писал(а): строка должна читаться всегда целиком, а затем браковаться, а не останавливаться накопление в середине цикла чтениястрока и так читается целиком, а прерывается только ее обработка, т.к. обрабатывать некорректные данные бесмысленно. Леонид писал(а): если читать именно по 18 байт, да через 50 мсек, нечего удивляться, что попадает окончание предыдущей строки и начало следующейсама посылка длится 2мс максимум, попасть в ее середину - это намного меньше 10-15%. с пустым символом надо пробовать. |
|||
карма: 0 |
|
Администрация
Ответов: 15295
Рейтинг: 1519
|
|||
nesco писал(а): Ты забыл про буфер FIFO, который автоматически накапливает принятую информацию, а уже ты ее считывешь из этого буфераналичие или отсутствие fifo буфера в данной проблеме ни при чем(насколько я понимаю данные не пропадают, а выдаются порциями не в той комбинации, которая ожидалась), и как правильно говорит Леонид, необходимо в своей схеме накапливать строку, после чего уже искать в ней последовательность длинною в 18 байт с началом 85, 252. |
|||
карма: 27 |
|
Ответов: 8926
Рейтинг: 823
|
|||
nesco, так и я про буфер из которого считываются по 18 байт
|
|||
карма: 19 |
|
Разработчик
Ответов: 26160
Рейтинг: 2127
|
|||
Dilma писал(а): необходимо в своей схеме накапливать строку, после чего уже искать в ней последовательность длинною в 18 байт с началом 85, 252Не надо у себя ничего накапливать, оно и так в буфере висит. Достаточно считать 18 байт до пустого символа, проверить ее на валидность и пропустить дальше или забраковать. У меня похожая система, и не на один канал, уже три года тарахтит и никаких рассинхронизаций я не наблюдал. С пакетами история похожая, надо считать все 5 пакетов, проверить валидность и дальше по теме. Сложность в данном случае, тут только в том, что если накапливать инфу в буфере FIFO, то нет никакой гарантии, что у нас не обрежется конец посылки, те, попадет нечетное количество кадров, тогда кусок последней посылки обратно уже в буфер не вернешь и его надо сохранять у себя, а к нему дальше уже приклеивать данные, это потребует усложненния контроля длины оставшегося массива после обработки кадра. Самое простое, это не допускать чтения в FIFO больше, чем длина кадра, тогда появиться гарантия, что следующий кадр не обрежется. В данном случае, делается, как описано ниже ------------ Дoбавленo в 14.22: HikeR писал(а): по таймеру раз в 50мс (точнее не нужно)А вот с эти я не согласен, для нормальной синхронизации по пустому символу читать надо быстрее, нежели устройство подает свои данные, но медленне, чем сама посылка, тогда гарантировано будут пустые символы на выходе и ничего никуда не пропадет ------------ Дoбавленo в 14.26: Если пытаться читать по 50 мсек, то получится, что за это время устройство выдаст 2,5 кадра информации (вот откуда и получается, что попадаем, где-то, в середину, и прет рассинхронизация) HikeR, короче, тебе надо менять концепцию схемы, иначе -- ничего у тебя не получится |
|||
карма: 22 |
|
Администрация
Ответов: 15295
Рейтинг: 1519
|
|||
"пустой" символ это с кодом 0 видимо? И откуда информация о том, что им заканчиваются 18ти байтные пакеты?
|
|||
карма: 27 |
|
Разработчик
Ответов: 26160
Рейтинг: 2127
|
|||
Dilma писал(а): И откуда информация о том, что им заканчиваются 18ти байтные пакеты?Я этого не говорил, что им закончится посылка в 18 байт, и описал, как получать пустые символы nesco писал(а): для нормальной синхронизации по пустому символу читать надо быстрее, нежели устройство подает свои данные, но медленне, чем сама посылка, тогда гарантировано будут пустые символы на выходе и ничего никуда не пропадетHikeR писал(а): имеется железка, которая раз в 20мс шлет пакетик длительностью 1.5-2.0мсВот тут, при потере кадра, если установить время меньше, чем длительностть между посылками (это время у нас в компоненте определяет и тйамаут потери кадра, оно на все у нас там стоит), устройством будет обнаружена потеря кадра и выставлен нулевой символ конца посылки |
|||
карма: 22 |
|
Гость
Ответов: 17029
Рейтинг: 0
|
|||
Редактировалось 1 раз(а), последний 2017-03-05 04:42:42 |
|||
карма: 0 |
|
Ответов: 499
Рейтинг: 1
|
|||
вобщем, это я был.
про изменение SetLength(Buffer,256); можно не читать, это дезинформация ;) |
|||
карма: 0 |
|
Разработчик
Ответов: 26160
Рейтинг: 2127
|
|||
HikeR писал(а): вобщем, это я былТы хочешь сказать, что у тебя, при интрвале <20 мсек и длине считывания буфера 18 байт (кстати, а у тебя сколько стоит), не появляются пустые символы, такого быть не может. При считывании буфера FIFO, автоматически происходит его уменьшение на количество считанных байт, и если их только 18, и считываем их только 18, то в буфере FIFO будет 0, до следующей посылки. Ты можешь дать последовательность твоего устройства, записей, этак, на 100, ну на крайняк -- 50, естественно, разных. Специально врублю виртуалку, сделаю эмулятор посылок и проверю, но вечером, дома. Если тебе, конечно, это очень интересно и нужна моя помощь. Можешь еще и схемку прицепить, что бы меньше возни было |
|||
карма: 22 |
|
Ответов: 499
Рейтинг: 1
|
|||
пустые символы не появляются. идет бурст в 18 байт, через ~20мс он повторяется, в перерывах - ничего нет. если не обнулять буфер порта через точку doRXClear - он будет просто увеличиваться.
nesco писал(а): можешь дать последовательность твоего устройства, записей, этак, на 100а есть какой-нить порт-монитор, который в лог накидал бы все что идет с порта с временными отметками? без него только так последовательность могу описать: ... 85 252 (еще 16 байт) ~20 мс пауза 85 252 (еще 16 байт) ~20 мс пауза 85 252 (еще 16 байт) ~20 мс пауза 85 252 (еще 16 байт) ~20 мс пауза ... если быть точнее, то вот что я захватываю (выборка из сотни пакетов):
подозреваю что это из-за того, что я очищаю буфер во время его заполнения, вот он и режется. наверное остается понять, в какой момент времени нужно очищать буфер. |
|||
карма: 0 |
|
Разработчик
Ответов: 26160
Рейтинг: 2127
|
|||
HikeR писал(а): пустые символы не появляются. идет бурст в 18 байт, через ~20мс он повторяется20mc пауза же есть, значит, можно выловить пустой буфер А что, терминалку подключить не вариант и записать потом полученные данные |
|||
карма: 22 |
|