В моем сообщении UART мне нужно знать начальный байт и конечный байт отправленного сообщения. Стартовый байт легкий, но стоповый, не так уж и много. Я реализовал два стоп-байта в конце моего сообщения, то есть \ n и \ r (десятичное и десятичное). UART работает только со значениями 0-255 байтов, так насколько это безопасно? Я могу себе представить, хотя и с низкой вероятностью, что мое сообщение может содержать значения «10 и 13» друг за другом, когда они не являются байтами остановки.
Есть ли лучший способ реализовать это?
"\x0D\x0A"
.\r\n\r\n
который содержит\n\r
последовательность в середине ...Ответы:
Есть разные способы предотвратить это:
Если ваши сообщения не более 256 байт, отправьте:
Итак, после получения 6 байтов данных вы знаете, что это конец; Вам не нужно отправлять 10 13 впоследствии. И вы можете отправить 10 13 внутри сообщения. Если ваши сообщения могут быть длиннее, вы можете использовать 2 байта для размера данных.
Обновление 1: еще один способ определения пакетов
Другой альтернативой является отправка команд, которые имеют определенную длину и могут иметь много отклонений, например
Обновление 2: плохое соединение / потеря байтов
Все вышеперечисленное работает только тогда, когда линия UART правильно отправляет байты. Если вы хотите использовать более надежные способы отправки, есть также много возможностей. Ниже приведены несколько:
Обратите внимание, что все вышеперечисленные механизмы могут быть простыми или настолько сложными, насколько вы хотите (или должны) быть. В случае повторной отправки сообщения также необходим механизм идентификации сообщений (например, добавление порядкового номера в пакет).
источник
Если вы отправляете отправку произвольных данных ->, вероятно, недостаточно надежно.
Распространенным решением является использование экранирования:
Давайте определим, что символы 0x02 (STX - начало кадра) и 0x03 (ETX - конец кадра) должны быть уникальными в потоке передаваемых данных. Таким образом, начало и конец сообщения могут быть безопасно обнаружены.
Если один из этих символов должен быть отправлен внутри фрейма сообщения, он заменяется префиксом escape-символа (ESC = 0x1b) и добавлением 0x20 к исходному символу.
Оригинальный персонаж заменен на
Получатель полностью изменяет этот процесс: каждый раз, когда он получает escape-символ, этот символ удаляется, а следующий символ вычитается 0x20.
Это только добавляет некоторые накладные расходы на обработку, но на 100% надежно (при условии отсутствия ошибок передачи, которые вы могли бы / должны проверить, дополнительно внедрив механизм контрольной суммы).
источник
'\x10'
DLE (Data Link Escape). Некоторые страницы Википедии предполагают, что DLE часто использовался противоположным образом: сказать, что следующий байт был управляющим символом, а не байтом данных. По моему опыту, это вообще противоположное значение для побега.Вы знаете, ASCII уже имеет байты для этих функций.
У этого также есть коды для различного использования в полезной нагрузке.
В вашем протоколе должна быть указана самая высокая степень детализации ACK (0x06) и NAK (0x15), чтобы отрицательно подтвержденные данные могли быть переданы повторно. Вплоть до этой тончайшей детализации целесообразно иметь поле длины сразу после любого (неэкранированного) индикатора запуска и (как объяснено в других ответах) целесообразно следовать за любым (неэкранированным) индикатором остановки с помощью CRC.
источник
UART не является отказоустойчивым по своей природе - мы говорим здесь о технологиях 1960-х годов.
Корень проблемы в том, что UART синхронизируется только один раз на 10 битов, что позволяет много тарабарщины проходить между этими периодами синхронизации. В отличие, например, от CAN, который дискретизирует каждый отдельный бит несколько раз.
Любая двухбитовая ошибка, возникающая внутри данных, повредит кадр UART и пройдет незамеченным. Битовые ошибки в стартовых / стоповых битах могут обнаруживаться или не обнаруживаться в форме ошибок переполнения.
Следовательно, независимо от того, используете ли вы необработанные данные или пакеты, всегда существует вероятность того, что переворот в битах, вызванный EMI, приведет к неожиданным данным.
Существуют многочисленные способы «традиционного шарлатанства UART», чтобы хоть немного улучшить ситуацию. Вы можете добавить байты синхронизации, биты синхронизации, четность, биты двойного стопа. Вы можете добавить контрольные суммы, которые подсчитывают сумму всех байтов (а затем инвертировать ее - потому что почему бы нет), или вы можете посчитать количество двоичных единиц в качестве контрольной суммы. Все это широко используется, крайне ненаучно и с большой вероятностью пропущенных ошибок. Но это было то, что люди делали с 1960-х по 1990-е годы, и многие странные вещи, подобные этим, происходят сегодня.
Наиболее профессиональный способ обеспечения безопасной передачи по UART - наличие 16-битной контрольной суммы CRC в конце пакета. Все остальное не очень безопасно и имеет высокую вероятность пропущенных ошибок.
Тогда на аппаратном уровне вы можете использовать дифференциал RS-422 / RS-485, чтобы радикально улучшить надежность передачи. Это необходимо для безопасной передачи на большие расстояния. Уровень UART TTL должен использоваться только для связи на борту. RS-232 не должен использоваться для каких-либо других целей, кроме обратной совместимости со старым материалом.
В целом, чем ближе к оборудованию механизм обнаружения ошибок, тем эффективнее он работает. С точки зрения эффективности, дифференциальные сигналы добавляют больше всего, с последующей проверкой ошибок кадрирования / переполнения и т. Д. CRC16 добавляет немного, а затем добавляет «традиционное шарлатанство UART».
источник
Ситуация, когда часть данных равна завершающей последовательности, должна учитываться при разработке формата пакета последовательных данных. Еще одна вещь, которую следует учитывать, это то, что любой персонаж может быть поврежден или потерян во время передачи. Стартовый символ, символ остановки, байт полезной нагрузки данных, байт контрольной суммы или CRC, байт прямого исправления ошибок не защищены от повреждения. Механизм кадрирования должен уметь обнаруживать, когда в пакете есть поврежденные данные.
Есть несколько способов подойти ко всему этому.
Я делаю рабочее предположение, что пакеты обрамлены только последовательными байтами. Линии рукопожатия не используются для кадрирования. Задержки не используются для кадрирования.
Длина отправляемого пакета
Отправьте длину пакета в начале вместо [или в дополнение к] завершающего символа в конце.
Плюсы: полезная нагрузка отправляется в эффективном двоичном формате.
минусы: нужно знать длину пакета в начале передачи.
Избежать специальных символов
Избегайте специальных символов при отправке данных полезной нагрузки. Это уже объяснено в предыдущем ответе .
Плюсы: отправителю не нужно знать длину пакета в начале передачи.
минусы: немного менее эффективны, в зависимости от того, сколько байтов полезной нагрузки необходимо экранировать.
Данные полезной нагрузки закодированы так, что они не могут содержать начальные и конечные символы
Полезная нагрузка пакета кодируется таким образом, что он не может содержать символы начала и окончания. Обычно это делается путем отправки чисел в виде их представления ASCII или Hex-ASCII.
Плюсы: человекочитаемый с обычными терминальными программами. Нет необходимости в коде для обработки экранирования. Не нужно знать длину пакета в начале передачи
минусы: низкая эффективность. Для одного байта данных полезной нагрузки отправляется несколько байтов.
источник