Pull to refresh

Comments 13

А для чего изобретать велосипед? Есть совершенно обычная процедура называемая byte stuffing например в ppp. Начало и конец пакета обозначаются байтом 0x7E если он встречается в пакете то заменяется на 0x7D 0x5E если встречается 0x7D то заменяется на 0x7D 0x5D (отмечаем что для исключения замен мы инвертируем один бит после признака замены) в конец пакета вставляется контрольная сумма (удобно использовать CRC8
Кстати это очень удобно когда конец пакета может быть началом следующего — оверхед минимальный.
Тут проблема пожалуй в том, что на микроконтроллере нет ppp.
На «большой» машине можно решить эту проблему большим количеством способов.
Хотя, по сути, библиотека все что делает — добавляет автоматом адреса, делает byte stuffing, и считает CRC.
Ну и рассчитана она на 8, 16, 32 битные микроконтроллеры.
Дело не в ppp, а в том, что эта тема уже была исследована и решена много лет назад, и хорошие идеи стоит использовать. Например разделитель пакетов, а не старт стоп, инверсия бита, а не произвольные замены, запрет на заменяемые символы а не просто префиксирование — получаем эффективный протокол.
Большинство этих идей состоит в том что ошибки на канале передачи единичные. (Бит/байт исказился). Когда в канале чрезвычайно много ошибок (более 50% блочных потерь (от 1 до 100 байт), более 5% искажений) не все хорошие идеи работают. А при бинарной передаче как можно ввести запрет на заменяемые символы? Если мне надо передать 20 произвольных float чисел?
Получаем пакет в 16 байт (из-за не очевидного выравнивания), а не 12 как могло бы показаться

Вообще говоря — выравнивание полей в структуре — implementation-defined, т.е. зависит от компилятора. Не стоит на него закладываться в любом случае.
При отправке двоичных данных их можно разделять специально выделенным для этого байтом

Стоит указать, что это называется «byte stuffing»
По способам дробления — можно еще добавить метод применяемый, например, в протоколе Modbus-RTU. Пакеты разделяются интервалами «молчания», линия сохраняется в неактивном состоянии в течении времени необходимого для передачи нескольких символов. В этом случае не требуется обрабатывать каждый байт, что бы разобрать byte stuffing, и можно задействовать DMA приемника, если он, конечно, имеется.
Когда в протоколе появляется время — увеличивается вероятность сбоев, увеличивается сложность отладки, обеспечить времена в хост-компьютере непросто и снижается эффективность канала передачи данных — плохой способ.
А миллионы девайсов на модбасе и не знают, что они плохие :)
Комп далеко не всегда бывает конечной точкой. Про сложность отладки и вероятность сбоев — с потолка взято. Byte-stuffing тоже снижает эффективность канала, так что спорно.

Разные протоколы передачи имеют различную применимость в различных случаях. Нужно уметь использовать разные методы, и выбирать наиболее подходящий под конкретную задачу. Глупо просто заявлять — этот способ плохой, этот хороший.
Я лично как-то раз использовал COBS/ZPE байт-стаффинг. Это вариация на тему RLE. Он довольно быстрый, и главное, известно что размер обработанного пакета не может превышать (n / 254) + 1, где n — размер исходного пакета, а разделитель пакетов — один нулевой символ. На практике обычно происходит даже небольшое сжатие пакетов, на вскидку могу сказать, что на 20-30% для пакетов средних размеров — 128-512 байт. Но это уже вероятностно.
Как раз вчера искал реализацию протокола для arduino-хост соединения. Пока что ковыряю Firmata, уши которого растут из MIDI
Sign up to leave a comment.

Articles