Как обозначить конец потока на USB

Я создаю устройство передачи данных Lora-USB с помощью Arduino и хочу каким-то образом указать, что поток данных завершен.

На данный момент я сделал:

void onLoRaReceive(int packetSize) {
  if (packetSize == 0) return;          // если пакета нет, возвращаем

  byte[packetSize] buffer=[];

  while (LoRa.available()) {
    site_t recievedData=LoRa.readBytes(buffer,packetSize);
    Serial.write(buffer,recievedData);
  }
}

Итак, я хочу узнать, как программное обеспечение, считывающее данные с последовательного интерфейса, узнает, что пакет закончился. Я думал, что один из способов — это отправка байта EOF, но я опасаюсь «мошеннических» значений EOF в данных пакета.

Еще один способ — отправить размер пакета через последовательный интерфейс, но как дать ему понять, что я сейчас отправляю именно размер, и ожидать X-размер данных?

, 👍2


2 ответа


Лучший ответ:

1

LoRa имеет среднюю скорость передачи данных и, как правило, значительные промежутки между пакетами, поэтому вы можете просто отправить данные в виде печатаемого шестнадцатеричного кода ASCII с символами переноса строки или другими разделителями.

Это почти вдвое увеличит объем данных, которые необходимо переместить, но сделает это очень простым и детерминированным способом, и вы сможете увеличить скорость последовательной передачи данных для обработки, особенно с учетом того, что скорость передачи данных фактически «существует» только между двумя микросхемами ATmega внутри Uno.

Еще одним плюсом является то, что данные становятся удобочитаемыми для человека, что удобно для отладки, особенно если вам нужно смешивать информационные сообщения и данные.

,

1

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

Большинство последовательных протоколов используют определенные символы для обозначения определенных вещей, и, действительно, набор символов ASCII содержит определенные символы, предназначенные для определенных задач в коммуникации, поэтому имеет смысл использовать их.

Один из возможных вариантов — EOT (конец передачи) — символ 0x04. Примечание: такого понятия, как «символ конца файла 'EOF'», не существует. Это чисто структурная конструкция DOS.

И да, вы можете задуматься о ложном символе 0x04 в потоке данных, вызывающем завершение, и вы не первый, кто об этом подумал. Именно поэтому существует символ 0x10 — DLE. Это Data Link Escape. Его цель — сообщить принимающей стороне: «Следующий отправляемый мной символ — символ данных. Не воспринимайте его как управляющий символ».

Таким образом, вместо каждого символа 0x04 в потоке данных следует отправлять 0x10,0x04. Приёмник обнаружит 0x10 и отметит, что следующий символ следует интерпретировать не как управляющий, а как необработанные данные.

Проблема решена.

Но что, спросите вы, если в потоке данных есть нестандартное значение 0x10? Разве это не вызовет ту же проблему?

Да. И вы обрабатываете его точно так же. Просто добавляете к нему префикс 0x10. Поскольку получатель должен знать, что следующий символ всегда нужно интерпретировать как данные, независимо от того, что это такое, он воспримет следующие 0x10 как данные.

В качестве примера отправим следующий поток данных:

0x06,0x31,0xc7,0x04,0x91,0x10,0x04,0x73

будет сделано как:

0x06,0x31,0xc7,[0x10],0x04,0x91,[0x10],0x10,[0x10],0x04,0x73

(Добавлены значения 0x10, выделенные скобками).

Может быть полезно использовать и другие управляющие байты, например, SOH (начало заголовка), STX (начало текста), ETX (конец текста) и т. д. Это позволит, например, сообщить получателю начало пакета и его состав. Добавление заголовка с длиной и контрольной суммой также может быть полезным для повышения надёжности и целостности данных.

,