Протоколы, используемые для связи между встроенным процессором и ПК.

StackOverflow https://stackoverflow.com/questions/310826

Вопрос

Я создаю небольшое устройство с собственным процессором (AVR Mega8), которое должно подключаться к ПК.Предполагая, что физическое соединение и передача байтов завершены, какой протокол лучше всего использовать поверх этих байтов?Компьютер должен иметь возможность устанавливать определенные напряжения на устройстве и считывать определенные другие напряжения.

На данный момент я думаю о полностью управляемом хостом синхронном протоколе:компьютер отправляет запросы, встроенный процессор отвечает.Есть еще идеи?

Это было полезно?

Решение

Modbus может быть тем, что вы ищете. Он был разработан именно для вашей проблемы. Существует много кода / инструментов, и соблюдение стандарта может означать легкое повторное использование позже. Он также поддерживает удобочитаемый ASCII, поэтому его все еще легко понять / проверить.

См. FreeModBus для окон и встроенного источника.

Другие советы

Многое можно сказать об архитектуре клиент-сервер и синхронных протоколах. Простота и надежность, для начала. Если скорость не является проблемой, вы можете рассмотреть компактный, понятный человеку протокол, чтобы помочь с отладкой. Я думаю о модемных AT-командах: «пробуждение» последовательность, за которой следует команда set / get, за которой следует терминатор.

Host -->  [V02?]      // Request voltage #2
AVR  -->  [V02=2.34]  // Reply with voltage #2
Host -->  [V06=3.12]  // Set voltage #6
AVR  -->  [V06=3.15]  // Reply with voltage #6

У каждой стороны может быть тайм-аут, если она не видит закрывающую скобку, и они будут синхронизироваться на следующей открытой скобке, которая не может появиться в самом сообщении.

В зависимости от требований к скорости и надежности вы можете закодировать команды в один или два байта и добавить контрольную сумму.

Всегда полезно отвечать с фактическим напряжением, а не просто повторять команду, поскольку она сохраняет последующую операцию чтения.

Также полезно для определения сообщений об ошибках, если вам нужно отладить.

Мой голос - за удобочитаемое человеком.

Но если вы перешли на двоичный код, попробуйте поместить байт заголовка в начало, чтобы отметить начало пакета. Мне всегда не везло с синхронизацией последовательных протоколов. Байт заголовка позволяет встроенной системе выполнить повторную синхронизацию с ПК. Кроме того, добавьте контрольную сумму в конце.

Я сделал такие вещи в простом двоичном формате

struct PacketHdr
{
  char syncByte1;
  char syncByte2;
  char packetType;
  char bytesToFollow;  //-or- totalPacketSize
};

struct VoltageSet
{ 
   struct PacketHdr;
   int16 channelId;
   int16 voltageLevel; 
   uint16 crc;
};

struct VoltageResponse
{
   struct PacketHdr;
   int16 data[N];  //Num channels are fixed
   uint16 crc;
}

Синхронизирующие байты менее важны в синхронном протоколе, чем в асинхронном, но они все же помогают, особенно когда встроенная система впервые включается, и вы не знаете, является ли первый байт, который она получает, серединой сообщение или нет.

Тип должен быть перечислением, которое сообщает, как интерпретировать пакет. Размер можно определить по типу, но если вы отправите его явно, то получатель может обрабатывать неизвестные типы без удушья. Вы можете использовать «общий размер пакета» или «количество следов байтов»; последний может сделать код приемника немного чище.

CRC в конце добавляет дополнительную гарантию того, что у вас есть действительные данные. Иногда я видел CRC в заголовке, что облегчает объявление структур, но добавление его в конце позволяет избежать лишнего прохода по данным при отправке сообщения.

Отправитель и получатель должны иметь тайм-ауты, начинающиеся после получения первого байта пакета, в случае сброса байта. Сторона ПК также нуждается в тайм-ауте для обработки случая, когда встроенная система не подключена и отклик вообще отсутствует.

Если вы уверены, что обе платформы используют числа с плавающей запятой IEEE-754 (у ПК) и имеют одинаковый порядок байтов, то вы можете использовать числа с плавающей запятой в качестве типа данных. В противном случае безопаснее использовать целые числа, либо необработанные биты A / D, либо предустановленную шкалу (т. Е. 1 бит = .001V дает диапазон +/- 32,267 В)

Адам Лисс делает много замечательных моментов. Простота и надежность должны быть в центре внимания. Читаемые человеком передачи ASCII помогают МНОГО при отладке. Отличные предложения.

Они могут быть излишними для ваших нужд, но HDLC и / или PPP добавляют концепцию канального уровня и все преимущества (и затраты), связанные с канальным уровнем. Управление ссылками, кадрирование, контрольные суммы, порядковые номера, повторные передачи и т. Д. - все это обеспечивает надежную связь, но добавляет сложность, обработку и размер кода, и может не потребоваться для вашего конкретного приложения.

USB-шина удовлетворит все ваши требования. Это может быть очень простое USB-устройство с единственным каналом управления для отправки запроса на ваше устройство, или вы можете добавить канал прерывания, который позволит вам уведомлять хост об изменениях в вашем устройстве. Можно использовать несколько простых контроллеров usb, например Cypress или микрочип

Протокол поверх передачи действительно соответствует вашим требованиям. Из вашего описания кажется, что простого синхронного протокола вполне достаточно. Что заставляет вас бродить и искать дополнительный подход? Поделитесь своими сомнениями и мы постараемся помочь :).

Если бы я не ожидал, что мне понадобятся эффективные двоичные передачи, я бы пошел на уже предложенный интерфейс в стиле терминала.

Если я действительно хочу сделать двоичный формат пакета, я склонен использовать что-то свободно, основанное на формате PPP byte-asnc HDLC, который чрезвычайно прост и прост в отправке, в основном:

Пакеты начинаются и заканчиваются на 0x7e Вы избегаете символа, добавляя к нему префикс 0x7d и переключая бит 5 (т.е. xor с 0x20) Таким образом, 0x7e становится 0x7d 0x5e и 0x7d становится 0x7d 0x5d

Каждый раз, когда вы видите 0x7e, тогда, если у вас есть какие-либо данные, вы можете обработать их.

Обычно я делаю синхронную работу, управляемую хостом, если у меня нет веской причины поступать иначе. Это техника, которая распространяется от простого точечного RS232 до многоточечного RS422 / 485 без хлопот - часто это бонус.

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

Итак, это заставило меня задуматься, и вот несколько моих мыслей:

Учитывая, что этот чип имеет 6 каналов АЦП, скорее всего, вы используете последовательную связь Rs-232 (догадка из вашего вопроса), и, конечно, ограниченное пространство кода, определение простой структуры команд поможет, как указывает Адам - ​​Вы Возможно, вы захотите свести обработку ввода к минимуму на чипе, поэтому двоичный код звучит привлекательно, но компромисс заключается в простоте разработки И обслуживания (возможно, вам придется устранить неработающий ввод через 6 месяцев) - гипертерминал - это мощный инструмент отладки - и это заставило меня задуматься о том, как реализовать простую структуру команд с хорошей надежностью.

Несколько общих соображений.

сохраняйте команды одинакового размера — упрощает декодирование.

Как отмечает Адам, структуру команд и дополнительную контрольную сумму можно легко обернуть вокруг ваших команд.(при небольших командах простая контрольная сумма XOR/ADD выполняется быстро и безболезненно)

Я бы порекомендовал хосту объявить о запуске с указанием версии прошивки при сбросе - например, «HELLO;Версия прошивки 1.00z» — сообщит хосту, что цель только что запустилась и что работает.

Если вы в первую очередь осуществляете мониторинг, возможно, вы захотите рассмотреть режим «свободного хода», в котором цель будет просто циклически перебирать аналоговые и цифровые показания — конечно, это не обязательно должно быть непрерывным, оно может быть размещено с интервалом 1, 5, 10 секунд или просто по команде.Ваш микроконтроллер всегда слушает, поэтому отправка обновленного значения — это независимая задача.

Завершение каждой выходной строки символом CR (или другим символом) упрощает синхронизацию на хосте.

например, ваш микро может просто выводить строки;

  V0=3.20
  V1=3.21
  V2= ...
  D1=0
  D2=1
  D3=...
  and then start over -- 

Кроме того, команды могут быть очень простыми —

?- Прочтите все значения — их не так много, поэтому получите их все.

X = 12.34 - Чтобы установить значение, первый байт - это порт, а затем напряжение и я рекомендую сохранить «=» и «». в качестве кадрирования, чтобы обеспечить действительный пакет, если вы отказались от контрольной суммы.

Другая возможность: если ваши выходные данные находятся в заданном диапазоне, вы можете предварительно масштабировать их.Например, если вывод не обязательно должен быть точным, вы можете отправить что-то вроде

5=0 
6=9
2=5  

что приведет к отключению порта 5, включению порта 6 на полную мощность и половинному значению порта 2. При таком подходе ascii и двоичные данные находятся примерно на одном уровне в отношении вычислительных/декодирующих ресурсов на микроконтроллере.Или для большей точности сделайте выходные данные 2 байтами, например, 2 = 54 - ИЛИ добавьте таблицу внешних ссылок, и значения даже не обязательно должны быть линейными, поскольку байт данных является индексом в справочной таблице. .

Как я люблю говорить;простое обычно лучше, если только это не так.

Надеюсь это немного поможет.


Во время перечитывания возникла еще одна мысль;добавление команды «*» может запросить данные, заключенные в html-теги, и теперь ваше хост-приложение может просто перенаправить вывод с вашего микро-браузера в браузер и, наконец, браузер готов —

:)

scroll top