Коли слід перейти з ASCII на вдосконалені послідовні протоколи?


28

Усі мої мікроконтролерні пристрої, які спілкуються з ПК через UART, використовують рядки ASCII для надсилання команд та отримання даних (як це реалізовано в Arduino). Це я дізнався, коли почав копатися в електроніці, і мені завжди було достатньо, щоб надсилати голі струни. Однак я помітив, що більшість пристроїв, на які я стикався, використовують складні двійкові протоколи, що включають коди функцій, адреси та перевірку помилок CRC.

Коли базовий зв'язок ASCII прийнятний і коли я повинен розглянути щось більш досконале, наприклад Modbus? Чи використовують комерційні пристрої такі ASCII? Промислові?


3
Коротка відповідь: Коли ваша програма потребує цього. Так, комерційні пристрої використовують ASCII. Візьмемо для прикладу GPS NMEA. (І знову ж таки, я тут звернуся до власного питання )
Євген Ш.

1
Modbus має режим ASCII. Дивіться довідник по протоколу Modicon Modbus
Tut

@EugeneSh: Варто відзначити, що в NMEA є контрольна сума, і випадання одного зразка вибуху через збій контрольної суми (що трапляється частіше, ніж ви могли подумати), як правило, не є критичною несправністю. Це, можливо, не стосується інших протоколів ... і використовується багато двійкових протоколів GPS (наприклад, Garmin) для додатків, в яких це може бути критично важливим (або в яких частота вибірки вище 1 ГГц є потрібно, для яких NMEA занадто багатослівний). Хоча це справді лише зміцнює вашу точку зору.
Гонки легкості з Монікою

Відповіді:


28
  1. ASCII та CRC не є взаємовиключними. ASCII - це кодування, а CRC - для перевірки помилок.

  2. ВСЕ може бути надіслано як ASCII. Нам старші, звичайно, пам’ятають UUEncoding, який перетворює що-небудь у рядок ASCII.

  3. А) Для мене, як правило, це питання швидкості та ефективності. Надсилання великого 32-бітного числа ASCII може зайняти багато часу, але для його відправлення у вигляді двійкового через послідовний протокол потрібно лише 4 байти.

    B) Надсилання NUMBERS через ASCII означає, що вам потрібно перетворити число в ASCII, що є явним додатковим кроком (це частина того, що робить "printf").

  4. Якщо ви якимось чином втрачаєте своє місце, викручуєтесь, втрачаєте формат, отримуєте неправильний ендіан тощо. Якщо ви надсилаєте ASCII, відновитись із гвинтів може бути простіше, просто зайшовши та ПОИСКАЙТЕ у потоці даних.


12
+1 для "ASCII - це кодування". Це не протокол; протоколи можна побудувати поверх ASCII.
Піт Бекер

8
Автоматичне відновлення з виправлення не є суттєво простішим для текстового протоколу як двійкового, але перевірка та налагодження цього, безумовно, має бути.
Нік Джонсон

1
@NickJohnson - абсолютно. Опинившись у шістнадцятковому редакторі, ви побачите, що ви можете відновити, ви вже знаходитесь у FUBAR, поки йде SOP
Скотт Сейдман

1
@nickjohnson це не зовсім так. ASCII надає безліч параметрів обрамлення / розділення діапазону для діапазону для сприяння синхронізації та відновлення, що потребує додаткових втечі, набивання бітів, інтервалу часу або інших хитрощів, якщо канал використовується для двійкових даних повної ширини.
Кріс Страттон

2
Я завжди віддаю перевагу ASCII, коли пишуть протоколи для всіх очевидних переваг (читабельність, розбірливість тощо). Є два випадки, коли бінарне має більше сенсу: по-перше, якщо швидкість є проблемою, і вам потрібно двійкові, щоб набити якомога більше даних у потік, а другий, незначно, якщо ви навмисно намагаєтесь придушити або навіть зашифрувати дані потік, щоб перешкоджати або запобігати зворотному проектуванню. Тоді у мене є бінарні протоколи, що були інженерно розробленими, і це значною мірою просто дратувало мене більше, ніж насправді заважало вчинку.
J ...

10

Ось кілька думок з цього приводу:

  • ASCII приємно, тому що ви можете використовувати послідовний монітор, щоб мати ручний погляд на те, що надсилати.
  • якщо ваше з'єднання не є надійним, ви повинні очікувати помилок передачі і використовувати CRC для перевірки цілісності кожного отриманого повідомлення. Це також можна зробити на ASCII-повідомленнях.
  • якщо ваш зв’язок занадто повільний, ви можете зменшити розмір повідомлень, перейшовши на бінарний формат
  • Спеціалізований бінарний формат може бути простішим для декодування на стороні приймача, ніж ASCII

7

На найпростішому рівні, можна сказати, простий протокол зв'язку має три шари: фізичний, транспортний та прикладний. (Є моделі з більшою кількістю таких, як OSI з 7 або TCP / IP з 4. Кількість шарів не дуже важлива в контексті цього питання.)

Прикладний шар - це шар, з яким ви безпосередньо працюєте у своєму коді, і фокус питання. Що стосується транспортного шару, то байт, який ви передали йому у send_data, є лише бінарним шаблоном, але ви можете інтерпретувати його у коді програми як букву "A". Розрахунок CRC або контрольної суми буде однаковим, незалежно від того, чи вважаєте ви байт "A", 0x41 або 0b01000001.

Транспортний шар - це рівень пакету, де у вас є заголовки повідомлень та перевірка помилок, чи це CRC, чи основна контрольна сума. У контексті вбудованого програмного забезпечення у вас може бути така функція, як send_data, де ви передаєте його байт для надсилання. Всередині цієї функції він помістив у пакет, який говорить: "Ей, це звичайне повідомлення, потрібне підтвердження, а контрольна сума - 0x47, поточний час - X." Цей пакет надсилається через фізичний рівень до приймального вузла.

У фізичному шарі визначаються електроніка та інтерфейс: роз'єми, рівні напруги, синхронізація тощо. Цей шар може варіюватися від пари слідів, що виконують TTL-сигнали для базового UART на друкованій платі, до повністю ізольованої диференціальної пари, як у деяких МОЖЕТЕ реалізації .

На вузлі прийому пакет надходить на фізичний рівень, розпаковується на транспортному шарі, і тоді ваш бінарний візерунок доступний для рівня додатків. Із шаром програми прийому вузла залежить, чи слід інтерпретувати цей шаблон як "A", 0x41 або 0b01000001, і що з ним робити.

На закінчення, надто завжди прийнятно надсилати символи ASCII, якщо для цього потрібна програма. Важливим є розуміння вашої схеми зв'язку та включення механізму перевірки помилок.


Протоколи Ascii можуть також включати контрольну суму. Я стикався з варіаціями Hex-as-ascii, використовуючи ascii-представлення чисел.
Євген Ш.

@EugeneSh. Уточнив цю точку
Метт Янг

Не для нитпика, але TCP не чотири шари; це сприймається як вміщення в четвертому шарі моделі OSI. Послідовна комунікація не дуже добре відповідає моделі OSI.
batsplatsterson

@batsplatsterson Це нітрохи, і це дуже не має ніякого відношення до моменту, який я роблю.
Метт Янг

5

Ще не згаданий момент полягає в тому, що будь-який користується ASCII або двійковим протоколом, надсилання символу відмивання перед кожним пакетом забезпечить, що навіть якщо шум рядка або помилки обрамлення з'являються перед початком пакету, всі символи після руб- Вихід буде правильно оформлений за відсутності подальших шумів. В іншому випадку, якщо один відсилає пакети постійно і не містить жодних символів, які гарантовано досягають ресинхронізації, можливо, один глюк може зіпсувати все, що випливає, до наступної паузи в передачі. Символ 0xFF є приємним, оскільки він гарантує, що будь-який одержувач зможе повторно синхронізуватись із таким символом.

(*) 0xFF - називається витримкою, тому що той, хто вводить помилковий символ під час введення даних на паперову стрічку, може натиснути кнопку «крок стрічки назад» і натиснути на тертку, щоб замінити помилково пробитий символ на 0xFF, який буде ігнорується більшістю одержувачів).


2

Однією з переваг передачі рядків ASCII є те, що коди управління можуть використовуватися для подачі сигналу про початок / кінець повідомлення. наприклад, STX (char 2) та ETX (char 3) можуть сигналізувати про початок передачі та кінцеву передачу. Крім того, ви можете додати просту стрічку для позначення кінця передачі.

При надсиланні двійкових даних це ускладнюється, оскільки жоден конкретний бітовий зразок не може бути зарезервований для коду управління (без якоїсь додаткової накладних витрат або складності), оскільки дійсний байт даних може мати той самий шаблон.


3
Багато двійкових протоколів DO резервують один або кілька бітових шаблонів як контрольні коди, але вони також включають механізм відходу для обробки цих кодів, коли вони з'являються в даних.
Трейд Дейва

Ви можете зарезервувати будь-який шаблон, щоб позначити все, що завгодно, у двійковій формі. Наприклад, я перебуваю на проектах із швидким потоком даних та повільним потоком даних, що виходить з того самого uart. Я зарезервував найбільший негативний int32 як прапор для моїх повільних даних, і просто наситив свої негативні дані на найбільшому мінусі + 1.
Скотт Сейдман

Домовились. Я уточнив це у відредагованій відповіді, сподіваюся.
Транзистор

2

ASCII просто чудово, я використовую його майже у всіх проектах. Це налагоджує налагодження набагато простіше для моніторингу порту, і це стане проблемою лише в тому випадку, якщо буде надіслано багато даних.

Ще один бонус: я використовую серійні радіопристрої, щоб отримувати повідомлення між ардуїно, і можу використовувати послідовний монітор, підключений до мого ноутбука, і вводити повідомлення, щоб зробити певні речі. Відмінно підходить для тестування.

Крім того, надсилання речей у вигляді бінарних даних неможливо налагодити, і залежно від ваших інструментів, ви можете вилучити бінарне та перетворити його на щось читабельне для людини. Або якщо ви знаєте, що шукаєте, ви зможете візуально перевірити потік даних і розпізнати значення там, де вони повинні бути, і помилку знайти так, хоч і не так легко. тобто ви розпізнаєте шаблони байтів і розпізнаєте очікувані значення


2

Замість Modbus розгляньте HDLC . Ви отримуєте виявлення помилок (що важливо в галасливих послідовних лініях). Синхронізація є надійною, втеча - надійною.

Я без проблем використовував HDLC в мережах RS-485, і PPP також використовує його.


2
Було б добре, якби ви вказали, чому ви пропонуєте це через Modbus.
Я поняття не маю, чим я займаюся

1

ASCII над UART є найбільш популярним частково тому, що:

  • Це легко читається при налагодженні (я ще не бачив логічного аналізатора, який не розшифровує ASCII).

  • Це дуже просто втілити, у вас є таблиця ASCII за допомогою швидкого google, який добре стандартизований.

  • Він вбудований в синхронізацію зі стартами / стоп-бітами.

  • Насправді весь світ хобістів налаштувався на ASCII за допомогою серійних, тому будь-які нові методи повинні мати справу з цим, а це непросто в будь-яких випадках.

Тоді ви потрапляєте в ситуацію, коли ви починаєте надсилати конкретне кодування, наприклад, надіслати подання в пам'яті поплавця порівняно з перетворенням поплавця в ASCII, надіслати те по послідовності, яке може бути набагато більше, ніж 4 байти, а потім перетворити це назад в уявлення пам'яті на хості. Натомість ви просто надсилаєте 4-байтне представлення кожного разу. Звичайно, ви можете почати обробляти кодування самостійно, але тоді вам потрібно налаштувати початкові / кінцеві теги, замовити і т.д.

Натомість можна використовувати такі речі, як Protobuf . Це було фактично використано в проекті, над яким я працював, і це було надзвичайно вигідно, він робить повідомлення різної довжини, обробляє для вас ендіан та кілька інших цікавих функцій. Він також не настільки великий за розміром коду, і ви можете вказати все, що має статично розподілятися при запуску. Якщо вам знадобиться, вам доведеться кинути контрольну суму.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.