Все мои микроконтроллерные устройства, которые связываются с ПК через UART, используют строки ASCII для отправки команд и получения данных (как реализовано в Arduino). Это то, что я узнал, когда я начал копаться в электронике, и я всегда находил достаточным посылку голых струн. Однако я заметил, что большинство устройств, с которыми я сталкивался, используют сложные двоичные протоколы, которые включают коды функций, адреса и проверку ошибок CRC.
Когда приемлема базовая связь ASCII и когда мне следует рассмотреть что-то более продвинутое, например, Modbus? Коммерческие устройства используют такие ASCII? Промышленные?
microcontroller
serial
communication
uart
protocol
Я не имею понятия что я делаю
источник
источник
Ответы:
ASCII и CRC не являются взаимоисключающими. ASCII - это кодировка, а CRC - для проверки ошибок.
НИЧЕГО можно отправить как ASCII. Мы, старики, наверняка помним UUEncoding, который превращает что-либо в строку ASCII.
А) Для меня это обычно вопрос скорости и эффективности. Отправка большого 32-разрядного числа с помощью ASCII может занять много времени, но для его передачи в двоичном виде через последовательный протокол требуется всего 4 байта.
B) Отправка NUMBERS через ASCII означает, что вам нужно преобразовать число в ASCII, что является явным дополнительным шагом (это часть того, что делает «printf»).
Если вы каким-то образом потеряете свое место, облажаетесь, теряете формат, получаете неправильный порядковый номер и т. Д., Бинарный протокол связи может облажаться. Если вы отправляете ASCII, вам будет проще восстановиться после взлома, просто войдя в систему и посмотрев на поток данных.
источник
Вот несколько мыслей по этому поводу:
источник
На простейшем уровне можно сказать, что простой протокол связи имеет три уровня: физический, транспортный и прикладной. (Есть модели с большим количеством, таких как OSI с 7 или TCP / IP с 4. Количество уровней не очень важно в контексте этого вопроса.)
Прикладной уровень - это уровень, с которым вы работаете непосредственно в своем коде, и фокус вопроса. Что касается транспортного уровня, то байт, который вы передали ему в send_data, является просто двоичным шаблоном, но вы можете интерпретировать его в коде приложения как букву «A». Расчет CRC или контрольной суммы будет одинаковым независимо от того, считаете ли вы, что байт равен «A», «0x41» или «0b01000001».
Транспортный уровень - это уровень пакета, где у вас есть заголовки сообщений и проверка ошибок, будь то CRC или базовая контрольная сумма. В контексте прошивки у вас может быть такая функция, как send_data, где вы передаете ей байт для отправки. Внутри этой функции она помещается в пакет, который говорит: «Эй, это нормальное сообщение, требуется подтверждение, контрольная сумма равна 0x47, текущее время - X». Этот пакет отправляется через физический уровень принимающему узлу.
На физическом уровне определяются электроника и интерфейс: разъемы, уровни напряжения, синхронизация и т. Д. Этот уровень может варьироваться от пары трассировок, запускающих сигналы TTL для базового UART на печатной плате, до полностью изолированной дифференциальной пары, как в некоторых CAN реализации.
На принимающем узле пакет поступает на физическом уровне, распаковывается на транспортном уровне, и затем ваш двоичный шаблон становится доступным для прикладного уровня. Прикладной уровень принимающего узла должен знать, должен ли этот шаблон интерпретироваться как «A», «0x41» или «0b01000001», и что с ним делать.
В заключение, почти всегда приемлемо посылать символы ASCII, если этого требует приложение. Важно понять вашу схему связи и включить механизм проверки ошибок.
источник
Еще не упоминалось о том, что, независимо от того, используете ли вы ASCII или двоичный протокол, отправка символа исключения перед каждым пакетом гарантирует, что даже если шум строки или ошибки кадрирования появляются до начала пакета, все символы после преобразования выход будет правильно оформлен при отсутствии дальнейшего шума. В противном случае, если кто-то отправляет пакеты непрерывно и не содержит каких-либо символов, которые гарантированно обеспечивают повторную синхронизацию, возможно, что один сбой может повредить все, что следует, до следующей паузы в передаче. Символ 0xFF хорош, потому что он гарантирует, что любой получатель сможет выполнить повторную синхронизацию по следующему символу.
(*) 0xFF - называется уничтожением, потому что тот, кто вводит ошибочный символ при вводе данных на бумажную ленту, может нажать кнопку «пошаговая лента назад» и нажать «потер», чтобы заменить ошибочно перфорированный символ на 0xFF, что игнорируется большинством получателей).
источник
Одним из преимуществ отправки строк ASCII является то, что управляющие коды могут затем использоваться для сигнализации начала / конца сообщения. например, STX (символ 2) и ETX (символ 3) могут сигнализировать о начале и окончании передачи. В качестве альтернативы вы можете добавить простой перевод строки, чтобы отметить конец передачи.
При отправке двоичных данных это становится более сложным, поскольку для управляющего кода не может быть зарезервировано никакой конкретной битовой комбинации (без каких-либо дополнительных служебных данных или сложности), поскольку действительный байт данных может иметь такую же схему.
источник
ASCII просто отлично, я использую его почти во всех проектах. Это значительно облегчает отладку для мониторинга порта, и это станет проблемой только при наличии большого количества данных для отправки.
Еще один бонус - я использую последовательные радиоустройства для передачи сообщений между arduinos, и я могу использовать последовательный монитор, подключенный к моему ноутбуку, и вводить сообщения, чтобы определенные вещи происходили. Отлично подходит для тестирования.
Кроме того, отправка данных в двоичном виде не является невозможной для отладки, и в зависимости от ваших инструментов вы можете извлечь двоичный файл и преобразовать его во что-нибудь удобочитаемое человеком. Или, если вы знаете, что ищете, вы можете визуально проверить поток данных и распознать значения там, где они должны быть, и найти неисправность таким способом, хотя и не так просто. т.е. вы узнаете шаблоны байтов и узнаете ожидаемые значения
источник
Вместо Modbus рассмотрим HDLC . Вы получаете обнаружение ошибок (что важно на шумных последовательных линиях). Синхронизация надежна, экранирование надежно.
Я использовал HDLC в сетях RS-485 без проблем, и PPP также использует его.
источник
ASCII над UART является наиболее популярным отчасти потому, что:
Он удобен для чтения при отладке (мне еще предстоит увидеть логический анализатор, который не декодирует ASCII).
Это очень легко реализовать, у вас есть ASCII-таблица через быстрый Google, который хорошо стандартизирован.
Он имеет встроенную синхронизацию со стартовыми / стоповыми битами.
Практически весь мир хобби настроен на использование ASCII вместо серийного, поэтому любые новые методы будут иметь дело с этим, а это непросто.
Затем вы попадаете в ситуацию, когда начинаете отправлять определенную кодировку, такую как отправка в памяти представления числа с плавающей запятой по сравнению с преобразованием числа с плавающей запятой в ASCII, отправка этого по последовательному каналу, длина которого может превышать 4 байта, и затем преобразование этого обратно в представлении в памяти на хосте. Вместо этого вы просто отправляете 4-байтовое представление каждый раз. Конечно, вы можете начать обрабатывать кодировку самостоятельно, но затем вам нужно установить начальный / конечный теги, порядок и т. Д.
Вместо этого можно использовать такие вещи, как Protobuf . Это на самом деле использовалось в проекте, над которым я работал, и это было чрезвычайно полезно, оно делает сообщения переменной длины, обрабатывает для вас порядок байтов и некоторые другие интересные функции. Он также не так велик по размеру кода, и вы можете указать все, что будет статически выделено при запуске. Вы должны были бы добавить контрольную сумму, хотя, если вам это нужно.
источник