Перейти к основному содержимому

Протоколы обмена данными

Когда Arduino общается с дисплеем, датчиком или модулем связи, одного провода «данные» недостаточно. Устройства должны одинаково понимать, где начинается сообщение, с какой скоростью идут биты, кто имеет право отвечать и как выбирается нужный адресат. Эти правила образуют протокол обмена.

Сверху вниз показаны функциональные топологии UART, I2C и SPI; оранжевые отрезки обозначают узлы питания подтяжек, а не полную схему питания

Коротко

UART обычно соединяет два устройства перекрёстными линиями TX и RX. I2C объединяет несколько устройств общей парой SDA и SCL с подтягивающими резисторами и адресами. SPI использует общие линии такта и данных, а для выбора каждого периферийного устройства — отдельный CS.

Зачем это нужно

На столе три модуля могут выглядеть похоже: питание, земля и несколько сигнальных контактов. Но неверно выбранный интерфейс не исправить другой библиотекой. UART-модулю нужен согласованный формат последовательных кадров, I2C-датчику — адрес и подтяжки, SPI-памяти — тактовая линия, режим и собственный сигнал выбора.

Знание протоколов помогает:

  • прочитать распиновку и не смешать питание с данными;
  • заранее оценить, сколько контактов Arduino потребуется;
  • соединить несколько датчиков без конфликта адресов;
  • выбрать подходящую скорость и логические уровни;
  • локализовать ошибку между проводкой, транспортом и форматом команды;
  • объяснить, почему код «не видит» физически подключённый модуль.

Главная идея

Протокол — договор между участниками обмена. Он включает несколько уровней:

электрические уровни -> линии и синхронизация -> байты -> команды устройства

Совпадение разъёма не гарантирует совпадение всех уровней. Например, два устройства могут иметь контакты TX и RX, но работать с разным напряжением или скоростью. I2C-дисплей может отвечать по адресу, однако требовать библиотеку для другого контроллера экрана.

UART, I2C и SPI используются рядом на одном мобильном роботе; показаны сигнальные топологии и I2C-подтяжки, но не все цепи питания периферии

Сравнение UART, I2C и SPI

СвойствоUARTI2CSPI
Основные сигналыTX, RXSDA, SCLSCK, COPI, CIPO, CS
Синхронизацияасинхронная, участники заранее задают скоростьтакт передаёт контроллер по SCLтакт передаёт контроллер по SCK
Несколько устройствобычно отдельное соединение или дополнительный протокол поверх UARTобщая шина, выбор по адресуобщие такт/данные и отдельный CS для каждого устройства
Направление данныхотдельная передача и приёмдвунаправленная линия SDAобычно отдельные линии в обе стороны
Дополнительные элементыобщая земля, иногда преобразование уровнейподтяжки SDA и SCL, общая земляотдельные CS, общая земля
Типичный учебный примерGPS или UART-радиомодульнесколько датчиков и дисплейпамять, быстрый АЦП, графический дисплей

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

UART: два независимых направления

UART передаёт биты без отдельной линии такта. Передатчик и приёмник заранее настраивают одинаковую скорость и формат кадра. В простом соединении нужны:

TX устройства A -> RX устройства B
RX устройства A <- TX устройства B
GND устройства A --- GND устройства B

TX соединяют с противоположным RX, а не с одноимённым контактом. Если обмен нужен только в одну сторону, одна сигнальная линия может отсутствовать, но общий провод всё равно нужен.

Параметр UARTПочему должен совпасть
скорость в бодахприёмник определяет границы битов по времени
число битов данныхзадаёт размер полезной части кадра
контроль чётностименяет наличие и смысл проверочного бита
стоповые битыопределяют конец кадра
логические уровнислишком высокое напряжение может повредить вход

Arduino Serial скрывает формирование кадров, но не угадывает настройки второго устройства. Значение Serial.begin(9600) должно соответствовать настройке партнёра. Термин «UART» также не означает классические уровни интерфейса RS-232: у RS-232 другие электрические уровни, и его нельзя подключать напрямую к GPIO без преобразователя.

I2C: общая адресная шина

В I2C контроллер формирует такт SCL, а данные передаются по SDA. Обе линии обычно имеют выходы с открытым стоком: участники могут тянуть линию вниз, а высокий уровень создают подтягивающие резисторы.

Несколько устройств подключают параллельно:

SDA контроллера --- SDA всех устройств
SCL контроллера --- SCL всех устройств
GND контроллера --- GND всех устройств

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

Адрес пишут в контексте

Документация может приводить 7-битный адрес либо байт адреса с уже добавленным битом чтения/записи. Arduino Wire обычно принимает 7-битное значение. Формат нужно проверить в datasheet, а не исправлять случайным сдвигом до появления ответа.

Номиналы подтяжек зависят от напряжения, ёмкости, скорости и уже установленных резисторов на модулях. Если каждый breakout добавляет свою пару, итоговое параллельное сопротивление может стать слишком малым. Линии нельзя подтягивать к напряжению, небезопасному для входов контроллера или периферии.

SPI: скорость и отдельный выбор устройства

В типичном четырёхпроводном SPI контроллер использует:

  • SCK — тактовый сигнал;
  • COPI — данные от контроллера к периферии; в старых datasheet часто используется название MOSI;
  • CIPO — данные от периферии к контроллеру; старое распространённое название — MISO;
  • CS или SS — выбор конкретного устройства.

SCK, COPI и CIPO можно разделить между несколькими устройствами, но каждому обычно выделяют отдельный CS. Неактивное устройство должно освободить линию CIPO. Если два CS активны одновременно, ответы могут конфликтовать. При чтении старой документации сопоставляйте COPI с MOSI, а CIPO — с MISO.

Настройка SPIЧто случится при ошибке
частота SCKустройство пропускает биты или не отвечает
порядок битовбайты интерпретируются зеркально по разрядам
режим CPOL/CPHAданные считываются на неверном фронте такта
активный уровень CSпериферия не выбирается либо остаётся выбранной

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

Инициализация интерфейсов в Arduino

Этот скетч показывает только запуск трёх аппаратных API и периодическую отправку диагностического байта в USB/Serial. Он не делает подключённые устройства взаимозаменяемыми.

#include <Wire.h>
#include <SPI.h>

unsigned long lastReport = 0;

void setup() {
Serial.begin(115200);
Wire.begin();
SPI.begin();
}

void loop() {
const unsigned long now = millis();
if (now - lastReport >= 1000) {
lastReport = now;
Serial.println("controller running");
}
}

Wire.begin() настраивает плату как I2C-контроллер в обычном учебном сценарии. SPI.begin() запускает аппаратный SPI-блок. Для реального устройства затем нужны его адрес, регистры, команды и параметры из документации.

Точные аппаратные пины интерфейсов зависят от платы. На некоторых Arduino они продублированы на отдельном разъёме, на других назначаются периферийной матрицей. Проверяйте pinout выбранной платы.

Как выбрать протокол для узла робота

Начинают не с любимой библиотеки, а с документации периферии. Если модуль поддерживает несколько интерфейсов, оценивают:

  1. требуемую скорость и объём данных;
  2. число свободных пинов;
  3. количество устройств на шине;
  4. длину проводов и уровень помех;
  5. доступность аппаратного блока на плате;
  6. поддержку библиотекой и необходимость разделять ресурс.
Узел роботаРазумный кандидатЧто проверить
конфигурационный радиомодульUARTуровни, скорость, формат команд
набор медленных датчиков на одной платеI2Cадреса, подтяжки, ёмкость шины
быстрый дисплей или память рядом с контроллеромSPIрежим, максимальный SCK, отдельный CS
связь между удалёнными платамине выбирать автоматически ни одиндопустимую длину и помехоустойчивый физический уровень

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

Уровни напряжения

Надпись 3.3 V или 5 V рядом с питанием не всегда сообщает допустимый уровень сигнального входа. Плата-модуль может иметь стабилизатор на VCC, но не иметь преобразователя на RX, SDA или SCK.

Перед соединением найдите в документации:

  • напряжение питания модуля;
  • абсолютный максимум сигнальных входов;
  • пороги высокого и низкого уровней;
  • наличие и направление level shifter;
  • напряжение, к которому подключены I2C-подтяжки.

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

Диагностика по уровням

Ошибку удобнее искать слоями:

СлойПроверка
питаниеправильное напряжение, полярность, общий GND, потребление
проводкасоответствие TX/RX, SDA/SCL, SCK/COPI/CIPO/CS и старым обозначениям в datasheet
электрические уровнисовместимость GPIO и подтяжек
транспортскорость UART, адрес I2C, режим и частота SPI
команда устройстваправильный регистр, формат пакета, паузы
программавыбранная библиотека, версия, обработка ошибки

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

Что запомнить о протоколах

  • Протокол задаёт правила, а распиновка и электрические уровни задают физическую возможность обмена.
  • UART соединяют TX с противоположным RX и согласуют формат кадра.
  • I2C использует общие SDA/SCL, адреса и подтяжки; совпавшие адреса создают конфликт.
  • SPI разделяет такт и линии данных, но обычно требует отдельный CS для каждого устройства.
  • У всех соединённых логических устройств должна быть корректная общая точка отсчёта.
  • Настройки берут из документации конкретного модуля и платы.

Практика

Задание 1. Распознай интерфейс

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

Задание 2. Схема трёх шин

Нарисуйте UART-соединение двух плат, I2C-шину с двумя датчиками и SPI-шину с двумя периферийными устройствами. Отметьте направления, общий провод, подтяжки и отдельные CS.

Задание 3. Выбор для робота

Роботу нужны радиомодуль, два одинаковых датчика и быстрая память. Предложите интерфейс для каждого узла. Укажите, какие сведения ещё нужно узнать, прежде чем схема станет готовой.

Задание 4. План диагностики

Составьте последовательность проверок для I2C-модуля, который не отвечает после подключения. Начните с действий без изменения кода и закончите анализом транзакций.

Проверьте себя

  1. Какие правила кроме проводов входят в понятие протокола?
  2. Почему в UART соединяют TX и RX перекрёстно?
  3. Для чего I2C нужны подтягивающие резисторы?
  4. Как выбирается устройство на общей I2C-шине?
  5. Зачем каждому SPI-устройству отдельный CS?
  6. Какие параметры SPI должны соответствовать datasheet?
  7. Почему маркировка питания модуля не гарантирует допустимый уровень входов?
  8. В каком порядке искать ошибку обмена?
Ориентиры для самопроверки

Сначала ответьте без подсказки. Ответ можно считать полным, если вы:

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

Если один из пунктов объяснить не получается, найдите соответствующую главу статьи, перечитайте её и повторите ответ.

Словарь статьи

  • Протокол — согласованный набор правил обмена данными.
  • UART — асинхронный последовательный интерфейс с отдельными передачей и приёмом.
  • I2C — синхронная адресная шина на линиях SDA и SCL.
  • SPI — синхронный интерфейс с тактом, линиями данных и выбором периферии.
  • Бод — число символьных состояний сигнала в секунду; в обычном UART часто соответствует битам в секунду.
  • Адрес — число, выбирающее устройство на общей шине.
  • Подтяжка — резистор, формирующий неактивный высокий уровень линии.
  • Chip Select — сигнал выбора конкретного SPI-устройства.
  • Логический уровень — диапазон напряжения, распознаваемый как LOW или HIGH.
  • Транзакция — законченная последовательность обмена по правилам интерфейса.

Связанные темы

Источники