Простой последовательный протокол связи "точка-точка"

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

  •  03-07-2019
  •  | 
  •  

Вопрос

Мне нужен простой протокол связи между двумя устройствами (ПК и микроконтроллером).Компьютер должен отправить некоторые команды и параметры на микроконтроллер.Микропроцессор должен передавать массив байтов (данные с датчика).

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

Есть ли какое-нибудь стандартное решение для этого?(Мне нужна только идея, а не полное решение).

P.S.Любой совет приветствуется. P.P.S Извините за любые грамматические ошибки, я надеюсь, вы понимаете.

Правка 1. Я еще не решил, будет ли это ведущий /ведомый протокол или обе стороны могут инициировать связь.Компьютер должен знать, когда micro выполнила задание и может отправлять данные.Он может непрерывно опрашивать микропроцессор, готовы ли данные, или микропроцессор может отправлять данные, когда задание выполнено.Я не знаю, что лучше и проще.

Правка 2. Аппаратное обеспечение и физический уровень протокол. С тех пор как RS-232Последовательный стандарт C, используемый в ПК, я буду использовать асинхронная связь.Я буду использовать только сигналы RxD, TxD и GND.Я не могу использовать дополнительные провода, потому что микроконтроллер AFAIK их не поддерживает.Кстати, я использую AVR Чип ATmega128.

Поэтому я буду использовать фиксированную скорость передачи данных в бодах, 8 бит данных, 2 стоповых бита без проверки четности (или с?).

Протокол передачи данных.Вот чего в первую очередь касался мой вопрос.Спасибо за предложение ЛПВП, ППС и Модбус протоколы.Я проведу исследование по этому поводу.

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

Решение

Я бы использовал ЛПВП.В прошлом мне с этим везло.Я бы для двухточечного последовательного соединения просто использовал Асинхронное кадрирование и забудьте обо всех других элементах управления, поскольку это, вероятно, было бы излишеством.

В дополнение к использованию HDLC для кадрирования пакета.Я форматирую свой пакет следующим образом.Вот как передаются параметры с использованием стандарта 802.11

U8 cmd;
U8 len;
u8 payload[len];

Общий размер каждого командного пакета равен len +2

Затем вы определяете команды, такие как

#define TRIGGER_SENSOR 0x01
#define SENSOR_RESPONSE 0x02

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

Таким образом, собрав все это вместе, пакет будет выглядеть следующим образом.

 // total packet length minus flags len+4
 U8 sflag;   //0x7e start of packet end of packet flag from HDLC
 U8 cmd;     //tells the other side what to do.
 U8 len;     // payload length
 U8 payload[len];  // could be zero len
 U16 crc;
 U8 eflag;   //end of frame flag

Затем система будет отслеживать последовательный поток на наличие флага 0x7e, и когда он будет там, вы проверите длину, чтобы увидеть, является ли она pklen >= 4 и pklen=len + 4 и является ли crc допустимым.Примечание. не полагайтесь только на crc для небольших пакетов, вы получите много ложных срабатываний, также проверьте длину.Если длина или crc не совпадают, просто сбросьте длину и crc и начните с декодирования нового кадра.Если это совпадение, то скопируйте пакет в новый буфер и передайте его вашей функции обработки команд.Всегда сбрасывайте длину и crc при получении флага.

Для вашей функции обработки команд возьмите cmd и len, а затем используйте переключатель для обработки каждого типа команд.Я также требую, чтобы определенные события отправляли ответ, чтобы система вела себя как удаленный вызов процедуры, управляемый событиями.

Так, например, сенсорное устройство может иметь таймер или реагировать на команду снять показания.Затем он форматировал пакет и отправлял его на компьютер, и КОМПЬЮТЕР отвечал, что он получил пакет.Если нет, то сенсорное устройство может повторно отправить сообщение по истечении времени ожидания.

Кроме того, когда вы выполняете сетевую передачу, вы должны спроектировать ее как сетевой стек, подобный Модель OSI как Форд - Декер очки не забывайте о материал физического уровня.Мой пост с HDLC - это уровень канала передачи данных и тот RPC и обработка команд - это прикладной уровень.

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

Протоколы RS232 - сложная штука.Предложение использовать HDLC является хорошим, но это не полное решение.Есть и другие вещи, которые вам нужно решить:

  • Как будет определяться скорость передачи данных между двумя устройствами?Автобуад?Предопределено или задано эксплицитно?
  • Будете ли вы управлять потоком с помощью программного или аппаратного обеспечения или с помощью того и другого?Обратите внимание, что если вы используете аппаратное управление потоком, то вы должен убедитесь, что кабели проложены правильно.
  • Говоря о кабелях, это огромная проблема с RS233.В зависимости от устройства вам может потребоваться использовать прямой сквозной кабель, или перекрестный кабель, или другой вариант.
  • Использование программного механизма управления потоком может быть эффективным, поскольку он позволяет использовать самый простой кабель - всего три проводных (TX, RX и обычный).
  • Вы выбираете 7 или 8-битное слово?
  • Проверка четности HW или программных ошибок.

Я предлагаю вам использовать 8 битов данных, без аппаратной четности, 1 стоповый бит и использовать программное управление потоком.Вам следует использовать autobaud, если ваше оборудование это поддерживает.Если нет, то autobaud чертовски сложно выполнить в программном обеспечении.

Здесь есть несколько хороших ответов, вот несколько полезных советов:

Даже если ваши пакеты не разделены по времени, байт синхронизации является важным способом сокращения количества мест, из которых вам нужно попытаться создать пакет.Вашим устройствам часто приходится иметь дело с кучей ненужных данных (например, окончание передачи пакета при включении или результат аппаратной коллизии).Без байта синхронизации вам придется пытаться создать пакет из каждого полученного вами байта.Байт синхронизации означает, что только 1/255 байт случайного шума может быть первым байтом вашего пакета.Также отлично, когда вы хотите проследить за своим протоколом.

Наличие адреса в ваших пакетах или даже просто небольшого указания master / slave или pc / device полезно, когда вы просматриваете пакеты через инструмент слежки того или иного типа.Вы могли бы сделать это, установив другой байт синхронизации для ПК, чем для УСТРОЙСТВА.Кроме того, это будет означать, что устройство не будет реагировать на свое собственное эхо.

Возможно, вы захотите ознакомиться с исправлением ошибок (например, Хэмминг).Вы упаковываете 8 бит данных в 12-битный защищенный байт.Любой из этих 12 битов может быть перевернут по пути и восстановлены исходные 8 битов.Полезно для хранения данных (используется на компакт-дисках) или там, где устройство не может легко выполнить повторную отправку (спутниковые каналы, односторонняя радиосвязь).

Номера пакетов облегчают жизнь.Отправленный пакет содержит номер, ответы содержат тот же номер и флаг с надписью "response".Это означает, что пакеты, которые так и не пришли (скажем, с повреждением синхронизации), легко обнаруживаются отправителем, и в полнодуплексном режиме с медленным соединением две команды могут быть отправлены до получения первого ответа.Это также упрощает анализ протокола (третья сторона может понять, какие пакеты были получены, не зная базового протокола).

Наличие единого мастера - это потрясающее упрощение.Тем не менее, в полнодуплексной среде это вообще не имеет большого значения.Достаточно сказать, что вы всегда должны это делать, если только вы не пытаетесь сэкономить электроэнергию или не делаете что-то, управляемое событиями на стороне устройства (состояние ввода изменено, образец готов).

Мое предложение - modbus.Это эффективный и простой стандартный протокол для связи с устройствами, имеющими датчики и параметры (например, ПЛК).Вы можете ознакомиться со спецификациями по адресу http://www.modbus.org.Он существует с 1979 года и набирает популярность, у вас не возникнет проблем с поиском примеров и библиотек.

Я прочитал этот вопрос несколько месяцев назад, столкнувшись с точно такой же проблемой, и на самом деле не нашел ничего достаточно эффективного для крошечного 8-битного micro с крошечным объемом оперативной памяти.Так вдохновленный ДЖАНОМ и ЛИН, я создал кое-что для выполнения этой работы.Я назвал это MIN (сеть межсоединений микроконтроллеров) и загрузил его на GitHub здесь:

https://github.com/min-protocol/min

Там есть две реализации:один на встроенном C, один на Python для ПК.Плюс небольшая тестовая программа "hello world", в которой компьютер отправляет команды, а прошивка загорается светодиодом.Я написал в блоге о том, как запустить это на плате Arduino здесь:

https://kentindell.wordpress.com/2015/02/18/micrcontroller-interconnect-network-min-version-1-0/

MIN - это довольно просто.Я исправил представление уровня 0 (8 бит данных, 1 стоповый бит, без четности), но оставил скорость передачи данных открытой.Каждый кадр начинается с трех байтов 0xAA, которые в двоичном формате равны 1010101010, что является хорошей передачей импульсов для автоматического определения скорости передачи данных, если один конец хочет динамически адаптироваться к другому.Фреймы представляют собой 0-15 байт полезной нагрузки с 16-битной контрольной суммой Флетчера, а также управляющим байтом и 8-битным идентификатором (чтобы сообщить приложению, что содержат данные полезной нагрузки).

Протокол использует заполнение символов, так что 0xAA 0xAA 0xAA всегда указывает начало кадра.Это означает, что если устройство выходит из режима сброса, оно всегда синхронизируется с началом следующего кадра (целью разработки MIN никогда не было пропустить неполный или неправильный кадр).Это также означает, что нет необходимости иметь конкретные ограничения по времени между байтами и межкадрами.Полная информация о протоколе приведена в GitHub repo wiki.

Есть место для будущих улучшений с MIN.Я оставил там несколько перехватов для передачи блочных сообщений (зарезервированы 4 бита управляющего байта) и для согласования возможностей более высокого уровня (зарезервирован идентификатор 0xFF), так что есть много возможностей для добавления поддержки часто требуемой функциональности.

Вот альтернативный протокол:

u8  Sync          // A constant value which always marks the start of a packet
u16 Length        // Number of bytes in payload
u8  Data[Length]  // The payload
u16 Crc           // CRC

Используйте RS232 / UART, поскольку ПК (последовательный порт) и процессор (UART) уже могут справиться с этим с минимальными затратами (просто нужен МАКС 232 чип или что-то подобное для изменения уровня).

А используя RS232 / UART, вам не нужно беспокоиться о главном / ведомом, если это не имеет значения.При необходимости доступно управление потоком.

Рекомендуемое программное обеспечение для ПК:либо напишите свой собственный, либо Доклайт для простого мониторинга и управления (ознакомительная версия бесплатна).

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

В любом случае, что бы вы ни делали: пусть все будет просто!

Редактировать: Использовать RS232 с ПК стало еще проще, чем раньше, поскольку теперь вы можете получить преобразователи USB в RS232 / TTL.Один конец подключается к разъему USB вашего компьютера и отображается как обычный последовательный порт;другой выдает сигналы 5 В или 3,3 В, которые могут быть подключены непосредственно к вашему процессору, без необходимости изменения уровня.

Мы использовали TTL-232R-3V3 от чипа FDTI, который идеально подходит для такого рода приложений.

Мое единственное предложение - если вам нужна помехоустойчивость, вы можете использовать полнодуплексный RS-422/485.Вы можете использовать микросхему, подобную это на стороне AVR, затем преобразователь RS-232-> RS-422 на стороне ПК, например здесь 485PTBR.Если вы сможете найти или изготовить экранированный кабель (две скрученные экранированные пары), то у вас будет еще больше защиты.И все это невидимо для микро- и ПК - никаких изменений в программном обеспечении.

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

Вы можете взглянуть на Telemetry и связанная с ним настольная реализация на python Pytelemetry

Основные характеристики

Это - Протокол на основе PubSub, но в отличие от MQTT это двухточечный протокол, нет брокера.

Как и любой протокол pubsub, вы можете опубликовать с одного конца на topic и получите уведомление на другом конце провода по этой теме.

Что касается встроенной части, публикация в теме так же проста, как :

publish("someTopic","someMessage")

Для чисел:

publish_f32("foo",1.23e-4)
publish_u32("bar",56789)

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

// Add an indexing meaning to the topic
publish("foo:1",45) // foo with index = 1
publish("foo:2",56) // foo with index = 2

// Add a grouping meaning to the topic
publish("bar/foo",67) // foo is under group 'bar'

// Combine
publish("bar/foo:45",54)

Это хорошо, если вам нужно отправлять массивы, сложные структуры данных и т.д.

Кроме того, шаблон PubSub великолепен из-за своей гибкости.Вы можете создавать приложения master / slave, от устройства к устройству и т.д.

Библиотека C GitHub version

Библиотеку C очень просто добавить на любое новое устройство, если у вас на нем есть приличная библиотека UART.

Вам просто нужно создать экземпляр структуры данных, называемой TM_transport (определяется Telemetry), и назначьте 4 указателя на функции read readable write writeable.

// your device's uart library function signatures (usually you already have them)
int32_t read(void * buf, uint32_t sizeToRead);
int32_t readable();
int32_t write(void * buf, uint32_t sizeToWrite);
int32_t writeable();

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

// At the beginning of main function, this is the ONLY code you have to add to support a new device with telemetry
TM_transport transport;
transport.read = read;
transport.write = write;
transport.readable = readable;
transport.writeable = writeable;

// Init telemetry with the transport structure
init_telemetry(&transport);  

// and you're good to start publishing
publish_i32("foobar",...

Библиотека Python PyPI version

На стороне рабочего стола есть pytelemetry модуль, реализующий протокол.

Если вы знаете python, следующий код подключается к последовательному порту, публикуется один раз в теме foo, печатает все полученные темы в течение 3 секунд, затем завершает работу.

import runner
import pytelemetry.pytelemetry as tm
import pytelemetry.transports.serialtransport as transports
import time

transport = transports.SerialTransport()
telemetry = tm.pytelemetry(transport)
app = runner.Runner(transport,telemetry)

def printer(topic, data):
    print(topic," : ", data)

options = dict()
options['port'] = "COM20"
options['baudrate'] = 9600

app.connect(options)

telemetry.subscribe(None, printer)
telemetry.publish('bar',1354,'int32')
time.sleep(3)

app.terminate()

Если вы не знаете python, вы можете использовать интерфейс командной строки

Пителеметрия CLI PyPI version

Командную строку можно запустить с помощью

pytlm

Тогда вы сможете connect, ls(список) полученные темы, print полученные данные по теме, pub(опубликовать) по теме или открыть plot по теме для отображения полученных данных в режиме реального времени

enter image description here

enter image description here

Что касается проверки четности (как это уже несколько раз упоминалось здесь):

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

Используйте что-то легкое, например CRC16, с таблицей подстановки - ее можно вычислять по мере получения каждого байта и, по сути, это просто XOR.Предложение Стива Мельникоффа отлично подходит для небольших микропроцессоров.

Я бы также предложил передавать данные, читаемые человеком, а не необработанные двоичные файлы (если производительность не является вашим главным приоритетом).Это сделает отладку файлов журналов намного приятнее.

Вы не указываете точно, как ведет себя микроконтроллер, но будет ли все, передаваемое с микро, прямым ответом на команду с ПК?Если да, то, похоже, вы можете использовать какой-либо протокол master / slave (обычно это самое простое решение).Если обе стороны могут инициировать связь, вам нужен более общий протокол канального уровня передачи данных. ЛПВП это классический протокол для этого.Хотя полный протокол, вероятно, является излишеством для ваших нужд, вы могли бы, например, по крайней мере, использовать тот же формат фрейма.Вы также могли бы взглянуть на ППС чтобы посмотреть, есть ли там какие-нибудь полезные детали.

возможно, этот вопрос может быть совершенно глупым, но кто-нибудь рассматривал возможность использования одного из Модем X/Y/Z протоколы?

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

SLIP и UDP.Серьезно.

На нем говорят все ПК и подобные устройства.

Есть хорошая книга и примеры из TCP Бережливый

Джереми Бентам тайком сфотографировался с работающим TCP / IP.AVR так же хорош , как и PIC, верно ?

Я бы порекомендовал вместо этого UDP, это чертовски просто.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top