Протоколы, используемые для связи между встроенным процессором и ПК - PullRequest
18 голосов
/ 22 ноября 2008

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

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

Ответы [ 8 ]

6 голосов
/ 26 ноября 2008

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

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

6 голосов
/ 22 ноября 2008

Многое можно сказать об архитектуре клиент-сервер и синхронных протоколах. Простота и надежность, для начала. Если скорость не является проблемой, вы можете рассмотреть компактный, понятный человеку протокол, чтобы помочь с отладкой. Я размышляю по аналогии с модемными 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

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

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

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

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

5 голосов
/ 25 ноября 2008

Мой голос за читабельного человека.

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

4 голосов
/ 25 ноября 2008

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

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 бит = .001 В дает диапазон +/- 32,267 В)

3 голосов
/ 23 ноября 2008

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

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

1 голос
/ 26 ноября 2008

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

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

Учитывая, что этот чип имеет 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, и теперь ваше хост-приложение может просто перенаправить вывод с вашего микро в браузер и wala, браузер готов -

:)

1 голос
/ 23 ноября 2008

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

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

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

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

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

1 голос
/ 22 ноября 2008

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

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

...