#c# #serial-port
#c# #последовательный порт
Вопрос:
У меня есть последовательное устройство с двоичным выходом, и я собираю данные, используя следующее.
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int count = sp.BytesToRead;
byte[] data = new byte[count];
sp.Read(data, 0, data.Length);
file.WriteLine(BitConverter.ToString(data));
}
Данные поступают и выглядят примерно так…
06-14-F2-A1-64-2D-62-00-1A-31-00-06-14-F3-84-62-59-01-00-1A-31-00-06-14-F3-85-56-52-55-31
1A-31-00-06-14-F4-18-04-2E-62-00-1A-31-00-06-14-F4-E3-27-5B-01-00-1A-31-00-06-14-F4-E4-1C-51-55-31
1A-31-00-06-14-F5-71-4C-59-71-20-1A-31-00-06-14-F5-8E-A5-2E-62-00-1A-31-00-06-14-F5-F4-47-56-55-31-1A-31-00-06-14-F6-10-1A-1A-31-52-24-1A-31-00-06-14-F6-3D-40-19-70-00-1A-31-00-06-14-F6-3E-9C-4C-55-31-1A-33-00-06-14-F6-F6-11-3D-A0-00-17-B0-C8-4E-42-70-AA-00-00-59-51-1E-1A-31-00-06-14-F7-05-4A-2E-62-00-1A-31-00-06-14-F7-83-5C-56-55-31-1A-31-00-06-14-F7-99-04-5A-01-00-1A-31-00-06-14-F7-99-F8-51-55-31-1A-31-00-06-14-F8-7B-EA-2E-62-00-1A-31-00-06-14-F9-00-CE-56-01-00-1A-31-00-06-14-F9-0E-DF-51-55-31-1A-31-00-06-14-F9-F2-8B-2B-62-00-1A-31-00-06-14-FA-15-1F-1D-05-30-1A-31-00-06-14-FA-62-4D-59-01-00-1A-31-00-06-14-FA-63-41-55-55-31-1A-31-00-06-14-FA-6F-6E-1D-67-67-1A-31-00-06-14-FA-EC-50-2E-72-00-1A-31-00-06-14-FB-22-96-38-62-00-1A-31-00-06-14-FB-3B-7A-40-20-43-1A-31-00-06-14-FB-69-2E-2B-62-00-1A-31-00-06-14-FC-62-F1-2D-72-00-1A-31-00-06-14-FC-DF-D1-2E-62-00-1A-31-00-06
Шестнадцатеричное значение здесь не проблема, поскольку я могу его расшифровать, но оператор, который я ищу, начинается с 1A-31, а затем имеет заданное количество байтов в длину. Как вы можете видеть, последовательный поток в этом случае начинается в середине потока и поэтому не является полным утверждением.
Как я могу найти этот маркер, отбросить начало, а затем начать обработку? Также имейте в виду, что это будет происходить несколько раз, так как буфер чтения в какой-то момент усечет поток, и мне нужно будет снова собрать его вместе?
Комментарии:
1. Да, вы ответили на свой вопрос.
Ответ №1:
Вы почти на месте. Ваша проблема в том, что данные, которые вы передаете, поступают в виде фрагментов, которые не совпадают с тем, где начинаются и заканчиваются инструкции. Я собираюсь предположить, что конец инструкции находится с помощью 1A-31, который идентифицирует начало следующего оператора. Если это не так, интерпретируйте этот ответ соответствующим образом.
Теперь вы не сможете ничего сделать с самыми первыми фрагментами данных в вашем примере, который содержит половину инструкции. Итак, давайте начнем с предположения, что первый фрагмент данных, который вы получаете, действительно начинается с 1A-31 .
Теперь есть два варианта:
- Вы можете найти весь оператор внутри фрагмента (т. Е. Вы сталкиваетесь с другим 1A-31 внутри него). В этом случае съешьте его и делайте с ним все, что захотите (я бы добавил
StatementReceived
событие и отправил его туда или что-то в этом роде). Повторяйте это упражнение до тех пор, пока фрагмент не будет полностью обработан. - Оператор не полностью содержится внутри фрагмента. Скопируйте уже полученные данные во временный буфер и дождитесь следующего
port_DataReceived
вызова.
Если имел место второй вариант, вы знаете, что данные для следующего port_DataReceived
не будут начинаться с 1A-31 (поскольку временный буфер непустой). Однако вы можете выполнить сканирование до конца (до следующего 1A-31), добавить к нему временный буфер (сохраненный в предыдущем port_DataReceived
вызове), а также создать StatementReceived
и стереть временный буфер.
При аналогичном подходе вы также можете иметь дело с операторами, для отправки которых требуется более 2 блоков данных; каждый раз, когда вы не сталкиваетесь с 1A-31, добавляйте полученные данные во временный буфер, пока оператор не будет завершен.
Наконец, если самые первые байты, которые вы читаете при запуске, не начинаются с 1A-31, вам просто придется их отбросить. Нельзя что-то сделать с половиной заявления.