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

Каков общий протокол для отправки информации из одной системы в другую? Например, предположим, что у нас есть некоторая информация, собранная с микроконтроллера за определенный период времени, которую мы хотим отправить на другой микроконтроллер. Я слышал об интерфейсах SPI и I2C, но мне неясно, когда вы используете один метод вместо другого и как вы его реализуете. Существуют ли другие распространенные методы, помимо SPI и I2C? Одинаков ли процесс реализации для разных микроконтроллеров? Это в основном анализ байтов данных, которые я делаю на принимающем микроконтроллере?

Что конкретно вы хотите сделать?
Просто думаю о том, как заставить разные части системы передавать данные друг другу в небольшой коробке, поэтому можно предположить, что расстояние очень короткое. Причина наличия разных частей в коробке состоит в том, чтобы упростить функции, чтобы каждая часть имела свою собственную функцию (надеюсь, это имеет смысл..)
это не то, что люди обычно называют системой. Это больше то, что я бы определил как подсистемы. Они составляют часть того, что вы могли бы рассматривать как единую систему, выполняющую единый набор задач. Это семантика, но я думаю, что многие из ваших ответов очень широки, потому что у них нет идеального представления о том, что вы ищете в вопросе.
в соответствии с тем, что сказал Кортук, это помогает определить проблему. Один важный вопрос, который следует задать себе, заключается в том, намереваетесь ли вы заменить отдельные подсистемы различными реализациями одной и той же функции, или это одноразовый проект «как есть». Если вы используете реальную шину и предоставляете детали реализации подсистем вашему процессору, то изменение подсистемы требует изменения as/w для вашего контроллера, тогда как если вы используете коммуникационный интерфейс, не имеет значения , как вы реализуете (замену ) подсистема, если она соответствует тому же протоколу сообщений.
Не проще разделить функциональность между несколькими устройствами только по причине разделения задач. Коммуникации и синхронизация более сложны, чем наличие двух процессов в одном микропроцессоре. Теперь, если эти процессы имеют особенно несовместимые профили задержки (один должен обновляться быстро, а другому может потребоваться некоторое время для завершения фрагмента), тогда МОЖЕТ быть веская причина для их разделения. Даже в этом случае более распространенным решением является использование прерываний или поиск способа еще больше разбить более длинную задачу. С тем, что вы описали, я склоняюсь к мысли, что вам следует переосмыслить это.
Полезное сравнение SPI и I2C: electronics.stackexchange.com/questions/29037/…

Ответы (7)

SPI и I2C отчасти похожи в том, что они действительно используются больше для подключения периферийных устройств к контроллеру или процессору, чем для фактической передачи данных между системами. USB — это еще один интерфейс, который люди, кажется, хотят рассматривать как систему связи, которая на самом деле является шиной подключения периферийных устройств.

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

Конечно, эта граница все время становится все более размытой. Такие вещи, как PCI и ISA, несомненно, являются шинами; I2C, SPI, USB, возможно, являются шинами; тогда как RS232, RS485 и Ethernet определенно являются коммуникационными интерфейсами. Но есть такие вещи, как шина CAN и 1553, которые определенно связаны с перемещением данных, но очень сложным способом.

CANbus очень задействован, а ethernet нет? CAN очень просто настроить для простого обмена сообщениями. Это специализированные чипы, и большинство семейств поддерживают их внутри своих микроконтроллеров.
@Kortuk - поскольку что-то вроде 232 имеет своего рода одноранговую симметрию, в то время как 1553 или МОГУТ навязывать отношения ведущий / подчиненный, да. Я не верю, что сказал, что Ethernet прост, просто он не накладывает различий между контроллером шины и устройством шины на конечных точках.
также полное раскрытие - мое мнение о CAN полностью связано с тангенциальным воздействием; это было неиспользуемое дополнительное периферийное устройство в нескольких системах, над которыми я работал, но после сотен просмотров документации вы немного усваиваете неиспользуемые опции просто осмосом. Итак, я работаю, исходя из предположения, что CAN представляет собой архитектуру типа контроллер/управляемое устройство.
Я думаю, что автобус имеет разные значения в разных контекстах. На уровне схемы любой интерфейс с несколькими сигналами можно рассматривать как шину. По мере того, как вы переходите на более высокие уровни с большей абстракцией, шина меняет значение. Чуть выше шина обычно означает, что задействовано или может быть несколько устройств. Например, многоточечная связь RS485 — это, безусловно, шина. Гораздо выше, с точки зрения устройства Linux, RS485 снова становится коммуникационным интерфейсом и понижается в статусе шины... до тех пор, пока вы не добавите поверх него собственный уровень протокола, превратив его обратно в шину. На каждом уровне имеет разное значение.

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

Самый нижний уровень — это физический уровень , который фактически перемещает биты.

  • SPI и I²C предназначены для коротких расстояний внутри устройства, где не так много шума, который может нарушить передачу.

  • Для не слишком быстрой связи на расстояния до нескольких десятков метров хорошим выбором будет последовательная связь через RS-232.

  • Если есть больше шума или больше расстояния, используются дифференциальные сигналы, например, в RS-485. Для более быстрой передачи данных есть Ethernet, который становится все более популярным.

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

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

Можно использовать простой последовательный UART (одна линия Tx и одна линия Rx без дискретных часов) и его можно легко адаптировать для пересечения различных потенциалов (даже первичной и вторичной цепей) с помощью оптронов или магнитных изоляторов .

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

Например, PMBus — это протокол связи с источником питания, который использует I2C в качестве физического носителя.

Как отметил @Jon, одна из проблем при выборе коммуникационного интерфейса заключается в том, всегда ли один объект будет нести ответственность за инициирование связи или за это могут нести ответственность несколько объектов. Связанный с этим вопрос заключается в том, всегда ли один объект будет готов к получению незапрашиваемых сообщений. SPI часто используется в приложениях, где одна сторона всегда будет готова к приему данных. Что-то вроде сдвигового регистра 74HC595, например, никогда не бывает «занято». Хотя SPI хорош для связи между микроконтроллером и оборудованием, которым должен управлять микроконтроллер, на самом деле он не подходит для связи между двумя микроконтроллерами. Когда два процессора с аппаратным обеспечением I2C используют его для связи, программному обеспечению может потребоваться столько времени (в очень широких пределах), чтобы справиться с тем, что происходит, без потери данных. Если бы процессору требовалось 100 микросекунд для обработки каждого входящего байта, это серьезно ограничило бы пропускную способность, но отправитель замедлился бы достаточно, чтобы получатель не отставал. Единственный способ, который обычно может произойти с SPI, - это наличие отдельного провода для квитирования.

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

  1. Его скорость несколько ограничена; SPI может работать намного быстрее, и даже UART иногда может работать немного быстрее
  2. (2) Хотя очень удобно, что для I2C требуется только два провода, оба провода должны быть способны к двунаправленной связи с открытым коллектором. Это затрудняет отправку I2C через повторители.

Лично я хотел бы, чтобы поставщики контроллеров поддерживали трехпроводной вариант SPI, который включает квитирование. Однако я не знаю ни одного контроллера, который делает это.

Забавно, что вы должны упомянуть об этом ... Мне нужно превратить интерфейс SPI в недвунаправленный интерфейс, подобный I2C (первый байт - это адрес), чтобы позволить гораздо большему количеству устройств участвовать в шине, чем у меня есть выбор микросхемы для . Это работает, если все ваши ведомые устройства являются FPGA. :) Я тоже хотел, чтобы между этими двумя основными синхронными стандартами было что-то среднее.
О, я думаю, мне следует пояснить, что выходные сигналы на ведомых устройствах не устанавливаются до тех пор, пока не будет получен его адресный байт, и они остаются включенными до тех пор, пока не будет отменен выбор одного чипа ... так что это, очевидно, немного отличается от обычного SPI + высокий уровень протокол. Однако он полностью совместим со стандартным SPI с точки зрения главного устройства. (как микропроцессор)
@даррон: Круто. Интересно, что должно произойти, чтобы промышленность начала использовать трехпроводную коммуникационную шину открытого стандарта, в которой провода активно перемещаются вверх и вниз? Я предполагаю, что есть небольшой конфликт между отказом от пассивных подтягиваний и разрешением любому устройству сигнализировать о прерывании, хотя это можно исправить, добавив контакт прерывания, который может быть подключен к ведущему устройству или не подключен к ведомым устройствам (моя текущая реализация протокол имеет только одно ведомое устройство, поэтому он может использовать провод возврата данных для асинхронного сигнала, когда он хочет быть обслуженным).
@darron: чтобы не использовать контакт выбора микросхемы, мастер сигнализирует о начале команды, отправляя два нарастающих фронта по проводу данных, когда тактовый сигнал низкий; ведомые устройства могут указывать, был ли их последний байт данных действительным, выводя значение состояния, когда и часы, и данные находятся на низком уровне (в режиме ожидания); в противном случае они указывают, что им нужно внимание, когда часы низкие, а данные высокие. Если бы я проектировал ведущее оборудование для этого протокола, я бы добавил возможность отправлять 8-тактовые импульсы, когда провод данных зеркально отражает часы, а в ведомом оборудовании включить асинхронный подсчет количества нарастающих фронтов во время...
@darron: ... байт данных. Если пять или больше, байт будет проигнорирован (ведомое устройство предположит, что ведущее устройство заинтересовано в получении байта данных, но на самом деле ничего не хочет сказать). Однако это было бы не так важно, как если бы ведомое устройство сообщало о статусе последнего байта, когда часы были низкими (что, если бы ведомое устройство было процессором, позволило бы ведущему узнать, что ведомое устройство не было готово). и упустил последнюю «возможность сделки».

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

Некоторые вопросы по этому приложению:

  1. Будет ли в этом проекте больше 2-х микроконтроллеров?
  2. Каковы ваши требования к скорости и пропускной способности? Как быстро туда поступает необходимая информация и как часто вы отправляете/получаете данные?

Если вы ответили НЕТ на вопрос 1:

Если в этом проекте всего 2 микроконтроллера, то однозначно можно использовать UART между ними. Если им обоим необходимо инициировать связь, используйте управление потоком, в противном случае отправка данных в одном направлении должна быть тривиальной. По большей части это должно быть «достаточно быстро», учитывая, что вы выбираете одну из более высоких скоростей передачи данных. I2C и SPI обычно хороши только для архитектуры master/slave.

Если вы ответили ДА (более 2 контроллеров) на вопрос 1:

  • Если в вашем проекте более 2 микроконтроллеров, какой из них инициирует связь? Будет ли это только один главный контроллер (т.е. архитектура ведущий-ведомый)? Или любая из подсистем сможет говорить в любое время?
  • Есть ли необходимость в том, чтобы какая-либо из подсистем общалась друг с другом? например: для устройств A, B и C: A может отправлять на B и C, а B может отправлять как на A, так и на C и т. д.

Так что теперь вам нужно что-то более масштабируемое, где вы можете сбрасывать адресуемые устройства на общую шину. Ответы на эти дополнительные вопросы помогут вам выбрать между I2C и SPI (ведущий-ведомый) или чем-то вроде CAN (многоглавный).

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

В произвольном порядке самые популярные экземпляры физического уровня для 2 ЦП в одном блоке выглядят следующим образом:

  • гирляндный SPI (например, используемый JTAG)
  • SPI выбора провода на ведомом устройстве
  • «RS-232 уровня TTL», также известный как «асинхронная последовательная связь пуск-стоп» (прямое подключение вывода UART TX одного ЦП к выводу UART RX другого ЦП)
  • I2C
  • 8-битные данные + строб (например, параллельный порт порта принтера IEEE 1284)
  • общая память (только один ЦП одновременно управляет шиной адреса/данных/управления)

Эти экземпляры физического уровня (а также другие экземпляры физического уровня для 2 ЦП в отдельных блоках) обычно предоставляют поток байтов программному обеспечению, реализующему более высокие уровни системы связи.

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

Протокол для отправки информации от одного процессора к другому почти всегда включает интерпретацию потока байтов как серии пакетов:

  1. преамбула
  2. заголовок
  3. (возможно, экранированные) сериализованные данные
  4. трейлер

Некоторым людям нравится создавать совершенно новые, настраиваемые, несовместимые протоколы путем смешивания и сопоставления (2) одного из многих видов структуры заголовка с (3a) одним из многих видов сериализации данных с (3b) одним из многих видов экранирование этих сериализованных данных с помощью (4) одного из многих видов трейлера.

Некоторые из самых простых протоколов для инкапсуляции данных в пакет включают в себя:

Чуть более сложные протоколы для инкапсуляции данных в пакет включают:

Существует длинный список протоколов на

Вам может понравиться чтение «Фольклор по дизайну протоколов» Радии Перлман, в котором описывается, как дизайн протокола может пойти не так.

Нет единого «общего» протокола. Выбор может (например) зависеть от:

  • расстояние
  • требуемая пропускная способность
  • наличие специальной периферии
  • уровень шума
  • потребность в оптической изоляции
  • критичность (допустимая частота отказов)
  • доступная мощность процессора на обоих концах
  • доступные контакты ввода/вывода на обоих концах

Во многих случаях вы должны отличать физический уровень (уровни сигналов) от уровня канала передачи данных (+/- способ кодирования данных) (проверьте модель OSI, нижние 2 ..4 уровня). Возможные физические слои, например:

  • простые 5В или 3.3В или даже 1.8В ТТЛ
  • любой из вышеперечисленных, но с открытым коллектором вместо двухтактного
  • сбалансированная сигнализация напряжения lov (часто используется с FPGA)
  • сбалансированное высокое напряжение (RS485, RS432)
  • несимметричный более высокое напряжение (RS232)
  • сбалансированный, связанный с трафиком (различные версии Ethernet, аудио PDIF)
  • оптический (оптический ethernet, toslink)

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

Существует множество способов кодирования данных и синхронизации на линии. RS232 традиционно использует NRZ, есть кодировка Machester, а также различные форматы, используемые на жестких дисках с любопытными именами, строка 2.7 RLL.

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