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

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

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

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

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

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

Изменить 2. Аппаратное обеспечение и протокол физического уровня.= "http://en.wikipedia.org/wiki/RS-232" rel= "noreferrer" > RS-232 C-серийный стандарт, используемый в ПК, я буду использовать асинхронную связь, Я буду использовать только сигналы RxD, TxD и GND. Я не могу использовать дополнительные провода, потому что микроконтроллер AFAIK их не поддерживает. BTW Я использую AVR чип ATmega128.

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

Протокол передачи данных. Это то, о чем прежде всего беспокоился мой вопрос. Спасибо, что предложили HDLC, PPP и Modbus. Я буду исследовать его.

Ответ 1

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

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

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

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

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

#define TRIGGER_SENSOR 0x01
#define SENSOR_RESPONSE 0x02

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

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

 // 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 не соответствует только reset длине и crc и начинаются с декодирования нового фрейма. Если это совпадение, скопируйте пакет в новый буфер и передайте его в свою функцию обработки команд. Всегда reset длина и crc при получении флага.

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

Так, например, сенсорное устройство может иметь таймер или отвечать на команду для чтения. Затем он отформатировал пакет и отправил его на ПК, и ПК ответит, что он получил пакет. Если нет, то сенсорное устройство может повторно отправить время ожидания.

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

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

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

Ответ 4

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

Ответ 5

Я прочитал этот вопрос несколько месяцев назад, имея точно такую же проблему, и на самом деле не нашел ничего достаточно эффективного для крошечного 8-битного микро с небольшим количеством ОЗУ. Так вдохновленный CAN и LIN, я построил что-то, чтобы выполнить эту работу. Я назвал его MIN (Microcontroller Interconnect Network), и я загрузил его в GitHub здесь:

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

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

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

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

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

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

Ответ 6

Здесь альтернативный протокол:

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) уже могут обрабатывать это с минимальным шумом (просто нужно MAX232 или аналогичные для переключения уровня).

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

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

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

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

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

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

Ответ 7

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

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

Ответ 8

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

C библиотека версия GitHub

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

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

// your device 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();

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

// 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

На стороне рабочего стола есть модуль 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, вы можете использовать интерфейс командной строки

Pytelemetry CLI версия PyPI

Командная строка может быть запущена с помощью

pytlm

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

введите описание изображения здесь

введите описание изображения здесь

Ответ 9

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

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

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

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

Ответ 10

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

Ответ 11

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

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

Ответ 12

SLIP и UDP. Шутки в сторону.

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

Есть хорошая книга и примеры из TCP Lean

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

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