Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Введение
На сегодняшний день существует много способов организовать обмен данными между Desktop-приложением и устройствами на микроконтроллерах: Wi-Fi, Bluetooth, RF, USB, преобразователи интерфейсов и т.д.
В большинстве из вышеперечисленных вариантов реализован пакетный обмен данными между хостом и устройством. Передаваемые данными с гарантией целостности и доставки будут переданы от передатчика к приемнику.
В случае использования интерфейсов RS-232, RS-485, RS-422 или чистого UART организация пакетного обмена данными ложится на программиста.
В данной статье я хотел бы рассказать о своей реализации обмена данными между устройствами
Постановка задачи
Нужно отправить из Qt-приложения пакет данных на устройство с микроконтроллером STM8. К компьютеру присоединён USB-RS485 преобразователь, а на устройстве соответственно преобразователь RS485-UART. Нужно учесть, что на линии связи возможен высокий уровень помех. В этой ситуации было принято решение написать быструю и легкую библиотеку для гарантии целостности принятых данных. *Гарантию доставки данных брала на себе бизнес-логика. Библиотеку решил назвать Sheller.
Требования к разрабатываемой библиотеки были следующие:
Фиксированная длинна пакета: количество байт, которые пользователь хочет передать не влияют на общую длину пакета, она остается фиксированной;
Минимальное количество внутренних буферов;
Наличие надежной, быстровычисляемой контрольной суммы;
Побайтного занесения данных;
Возможность работы в условиях поврежденных и потерянных байт в пакете;
Выполнение задачи
Принцип работы: определимся с понятием пакета. Пакет представляет собой стартовый байт, данные пользователя и два байта контрольной суммы CRC-16:
В начале использовался алгоритм контрольной суммы CRC8, однако в ходе тестов было выяснено, что при длине пакета в 8 байт количество коллизий было слишком высоким. Тест заключался в следующем: некоторые пакеты специально отправлялись битыми (менялись значения или вовсе удалялся байт из пакета). В итоге на каждый 50000й пакет происходила коллизия CRC и неправильный пакет передавался в бизнес-логику.
Первый случай коллизии происходил, когда значения байтов в пакете были изменены таким образом, что их контрольная сумма осталась прежней:
А во втором случае часть побитого пакета с частью целого пакета соединялись в один пакет, который проходил по контрольной сумме:
Поэтому было принято решение перейти на CRC16. При запуске тоже теста было пройдено более 2млн пакетов без коллизий и тест был завершен удачно. Вычисление контрольной суммы происходит по табличному методу для ускорения работы.
В качестве StartByte используется значение 0x23. С помощью этого числа парсер делает предположение, что с этого места начинается пакет. Далее парсер проверяет количество байт в буфере и если их столько же или больше чем длинна пакета, то производится подсчет контрольной суммы. Если подсчитанная и принятая контрольные суммы совпадают, то пакет выдается и бизнес логику приложения.
При приеме байтов мы записываем их в циклический буфер, в основном я это делаю в обработчике прерывания принятого байта.
Работу всей библиотеки можно описать следующей схемой:
Данная библиотека реализована на Си и на C++. C++ версия предназначена в основном для Arduino.
Для проверки работы Sheller на микроконтроллере был написан ShellerTerminal:
Информацию по использованию библиотеку вы можете найти на GitHub.