@UporotayaPanda

Как прочитать данные, постоянно поступающие через com-порт?

Всем доброго времени суток!

Небольшая вводная:
Имеется система, которая постоянно высылает сообщения об состоянии самой системы и элементах, которые входят в нее.
Условно назовем эти сообщения "посылками". Размер посылки не фиксирован. Все посылки состоят из фреймов, каждая посылка может содержать любое количество фреймов, но обязательным является наличие стартового и финального фрейма. Все виды фреймов имеют строго фиксированную длину и уникальный первый байт.
Стартовый фрейм - 11.
Финальный фремй - С9.

Теперь немного аппаратной части:
Скорость передачи - 19200, стартовые биты -1, стоповые биты - 2, контроль четности - нет. Между "посылками" имеется пауза в 1.5 байта. Если в этот промежуток нужное устройство не отправило сообщение, линию занимает следующее за ним.

Теперь сам вопрос:

Как принимать всю "посылку" от паузы до паузы???

Пробовал несколько способов:
1. Просто читать данные через Read и писать это в массив, а затем уже определять известные флаги и делить на посылки и фреймы. Но данный способ не очень нравится, тк нет никакой информации о моменте паузы в передаче, а без нее в будущем не возможно будет отправлять данные в систему.
2. Использовал port.DataReceived += new SerialDataReceivedEventHandler(DataReceviedHandler). Все остальные попытки были проделаны именно таким способом. Менялась только логика DataReceviedHandler.
Тестировал на консоли, выводил данные из буфера в новую строку, но посылки разорваны, например конец первой может содержаться в следующей строке и тд.

Настройки порта:
port.BaudRate = 19200;
port.DataBits = 8;
port.Parity = System.IO.Ports.Parity.None;            
port.StopBits = System.IO.Ports.StopBits.Two;


Остальные настройки пробовал менять, но никаких изменений. Не смог понять как обрабатывать стартовый бит, тк ранее в подобных системах его не было, или все работало без него, а на мдсн такой информации не нашел. Еще хотелось бы попробовать изменить ReadTimeout, но не смог разобраться какое значение выставить.

Вот пример работы. В середине строки видим флаг 11 - это указывает на начало стартового фрейма, и, собственно начало посылки. Ошибки в данных нет, проверяю через расчет CRC. Через 8 байт идет флаг C9 - это финальный фрейм. Но почему его окончание идет в следующей посылке??
2a122c18930e4ee09553045b8dc16038.PNG

Буду признателен и благодарен за помощь!
  • Вопрос задан
  • 2095 просмотров
Пригласить эксперта
Ответы на вопрос 1
@d-stream
Готовые решения - не подаю, но...
Гм... если бы не пауза "1.5 байта" - все бы было легко и хорошо, на так - несколько неестественное использование... со всеми вытекающими...
Если меня склероз не обманывает - у 8251 буфер в пределах 15 байт. То бишь если пакет/фрейм больше - он должен фрагментироваться.

p/s/ по бреду: упасть на уровень-другой ниже до эмуляции 8251, выключить буффер и ловить побайтно данные и паузы отслеживать по таймеру... только, боюсь, первыми непреодолимыми граблями окажется частичная эмуляция интерфейса...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы