UART, I2C, SPI: чем отличаются и какой выбрать для своего модуля
SPI (30 271), UART (28 569) и I2C (25 038) — три крупнейших чистых ядра спроса в периферии, и все три решают одну задачу — обмен данными между чипами — но настолько разными способами, что путаница между ними съедает больше времени новичков, чем сама распайка.
Главное отличие — сколько устройств на одной линии
UART — соединение строго между двумя устройствами (точка-точка), два провода на приём и передачу (RX/TX), без общей шины. I2C — настоящая шина: до 127 устройств на двух проводах (SDA/SCL), каждое отвечает на свой уникальный адрес. SPI — тоже шина, но без адресации: каждое устройство получает отдельный провод выбора (Chip Select), а данные идут по общим линиям MOSI/MISO/SCK. Отсюда практический вывод: если нужно подключить один датчик — годится любой из трёх; если несколько однотипных датчиков на разных адресах — I2C; если нужна максимальная скорость и не жалко лишних GPIO под Chip Select — SPI.
Скорость и цена скорости
SPI — самый быстрый (десятки МГц, ограничение обычно упирается в длину проводников и наводки, а не в протокол). I2C — медленнее (100 кГц Standard, 400 кГц Fast Mode, 1 МГц Fast Mode Plus), но экономит выводы за счёт общей шины. UART — скорость задаётся конкретным baud rate (9600–115200 бод для большинства модулей, встречаются и выше), и оба устройства обязаны быть настроены на одинаковый baud rate заранее — протокол не согласовывает скорость автоматически, в отличие от USB.
Частые ошибки подключения
**I2C без подтягивающих резисторов** — линии SDA/SCL требуют внешней подтяжки к питанию (обычно 4.7 кОм), потому что выходы I2C — открытый сток (open-drain), сами по себе не держат высокий уровень. Без подтяжки шина либо не работает вообще, либо работает нестабильно на коротких проводах, что маскирует проблему на макетке и всплывает только в готовом корпусе. **SPI: перепутанный режим (Mode 0-3)** — SPI имеет 4 комбинации полярности и фазы тактового сигнала (CPOL/CPHA), устройство и код должны совпадать по режиму, иначе данные читаются со сдвигом на бит и выглядят как случайный мусор — ошибка выглядит как «неисправный модуль», хотя железо исправно. **UART: перепутанные RX/TX** — RX одного устройства подключается к TX другого и наоборот (перекрёстное подключение), прямое соединение RX-RX/TX-TX не работает — классическая ошибка новичков, которую не всегда легко увидеть на схеме модуля. Все три симптома — мусор на SPI при несовпадении режима, тишина на UART при разных baud rate, нестабильная шина I2C без подтяжки — выглядят одинаково без прибора, который покажет, что реально идёт по проводам: разбор такого прибора — в статье Логический анализатор: как выбрать по каналам и частоте дискретизации.
Когда протокола вообще не хватает — I2C как частый затык на длинных линиях
I2C проектировался для коротких дистанций на одной плате (десятки сантиметров) — на проводах длиннее полуметра высокая ёмкость линии искажает фронты сигнала, и шина начинает сбоить непредсказуемо, особенно на Fast Mode. Для вынесенных датчиков на расстоянии metров практичнее либо снизить частоту I2C принудительно, либо перейти на RS-485 (дифференциальная пара, устойчива к наводкам на десятки-сотни метров) — тот случай, когда протокол меняют не из-за скорости, а из-за физической длины линии.