По ту сторону кода: дружелюбное введение в UART, I2C и SPI для тех, кто боится железа
Возьмите в руки смартфон и ненадолго вскройте его мысленно. Там сидит колония из крошечных чипов, и большинство из них не знает о существовании соседей. Контроллер батареи никогда не слышал о сканере отпечатка, а датчик приближения понятия не имеет, зачем рядом гудит вибромотор.

Чтобы немые незнакомцы превратились в единое целое, кому-то нужно было придумать, как заставить их понимать друг друга. Тут появляются протоколы связи, о которых дальше пойдёт речь. Внутри телефона их много, у камеры и экрана, например, свои скоростные интерфейсы, но мы разберём три самых простых и ходовых, UART, I2C и SPI. Эта статья будет полезна как для новичков, которые хотят погрузиться в тему, так и для тех, кто хочет освежить базовые знания.
Этикет
Несмотря на пример со смартфоном, обращу ваше внимание на то, что устройства общаются повсеместно, и в компьютерах и в ноутбуках и даже в аэрогриле.
Слово «протокол» пугает, хотя суть простая - это набор оговорённых правил. Тут я хочу обратить внимание на формулировки. UART, I2C и SPI называют то интерфейсами, то протоколами, и в обиходе эти слова взаимозаменяемы. Строго говоря, UART - это название самого узла-приёмопередатчика, но способ связи зовут так же, и я буду делать так же.
У многих протоколов есть общий элемент - шина.

Шиной называют набор проводов, к которым подключены все нужные чипы одновременно, будто общий коридор, куда выходят двери сразу нескольких кабинетов. На плате эти провода выглядят как тонкие медные дорожки, и дальше слова «провод» и «линия» будут означать одно и то же.
Когда устройство что-то передаёт, оно меняет напряжение на линии, переключая его между двумя уровнями, низким и высоким, и так получается последовательность нулей и единиц.
У этой последовательности есть ритм, и отбивает его тактовый сигнал, который выдаёт ведущее устройство (об иерархии речь пойдёт ниже). Ведомый на I2C, правда, может ненадолго придержать такт, если не успевает. Синхронные протоколы вроде I2C и SPI прямо выделяют под такт отдельный провод, чтобы обе стороны точно знали, в какой момент можно читать значение на линии данных, не боясь, что оно ещё не успело установиться.

У асинхронного протокола связи под названием UART отдельного тактового провода нет, вместо этого у каждой стороны свои внутренние часы, заранее настроенные на одну и ту же скорость передачи.
Кто в комнате главный
Прежде чем разбирать конкретные протоколы, стоит понять, как устроена иерархия (она есть у I2C и SPI, у UART её нет) между чипами. Представим совещание, где один человек ведёт разговор и по очереди даёт слово каждому из присутствующих, а остальные молчат, пока не услышат обращение к себе.
В телефоне роль ведущего чаще всего берёт на себя главный процессор, и традиционно ведущие устройства называются master. А датчик приближения, гироскоп и прочие выступают в роли ведомых, или slave-устройств, которые просто ждут, когда к ним обратятся (максимум могут подать знак по отдельному проводу прерывания). В новых редакциях документации их называют иначе: в I2C controller и target, в SPI чаще controller и peripheral, но в большинстве даташитов по-прежнему master и slave.
UART, звонок тет-а-тет
Начнём с одного из самых простых и самого древнего в нашей тройке способа договориться. Это протокол под названием UART, что расшифровывается как Universal Asynchronous Receiver-Transmitter, универсальный асинхронный приёмопередатчик. Так называется сам блок внутри чипа, который принимает и передаёт биты, но в обиходе тем же словом зовут и способ связи.
Именно так главный процессор часто общается с модулем Bluetooth, если тот стоит отдельным чипом, а в части телефонов и с приёмником спутниковой навигации, который по привычке называют GPS. Это классический пример разговора один на один, без посторонних на линии.
Фишка UART в том, что он соединяет напрямую только два устройства и шиной в привычном смысле не является. Ведущего и ведомого здесь тоже нет, стороны равноправны, и каждая может заговорить в любой момент.

Сигнальных проводов два: один на передачу (TX), второй на приём (RX), причём TX одного чипа приходит на RX другого. Нужна ещё общая земля, но она требуется всем трём интерфейсам, а внутри одной платы есть и так.
Если приёмник может не успеть разобрать поток, добавляют ещё два провода: RTS и CTS. Своим выходом RTS сторона показывает, что готова принимать, и этот провод приходит на вход CTS собеседника; сняли сигнал - отправитель ждёт. Названия остались от старых модемов, где смысл сигналов был немного другим. Для Bluetooth по самому распространённому варианту обмена, HCI H4, эта пара обязательна. Потеряв хотя бы байт, H4 сбивается и восстанавливается только сбросом. Есть и вариант H5, который сам переспрашивает потерянное и может обойтись без RTS и CTS.
Чтобы разговор состоялся, обе стороны должны быть заранее настроены на одну и ту же скорость передачи, которую называют baud rate. Значение им прописывает разработчик, обычно из привычного ряда вроде 9600 или 115200 бод (в UART один бод равен одному биту в секунду). Если модуль Bluetooth говорит на одной скорости, а процессор слушает на другой, получится мусор.
Передача здесь идёт по одному байту, и каждый из них дополнительно обрамляется стартовым и стоповым битом. Их реальная функция в синхронизации. По фронту стартового приёмник выравнивает свои часы на каждый байт.

Биты данных идут младшим вперёд, за ними может стоять бит чётности для простой проверки, а стоповых битов бывает один или два. Всё это должно совпадать у обеих сторон так же, как скорость; самый ходовой вариант записывают как 8N1.
У этой простоты есть обратная сторона, которая объясняет, зачем вообще понадобились следующие два протокола. На каждого собеседника нужна своя пара проводов и свой приёмопередатчик в процессоре, а чипов в телефоне десятки.
Общий чат I2C
Именно поэтому многие сенсоры внутри телефона обычно висят на общей шине I2C (Inter-Integrated Circuit, буквально «между интегральными схемами»), будто сидят в одном рабочем чате, где в каждый момент пишет кто-то один, а остальные молча читают.
Таких шин в телефоне бывает несколько, но устроены они одинаково. У I2C всего два провода на всех, один для самих данных (SDA) и второй для общего тактового сигнала (SCL), по которому все участники понимают, когда наступил момент читать очередной бит.
Чип не умеет сам поднимать линию к высокому уровню, он может только прижать её к нулю или отпустить. Наверх отпущенную линию возвращает подтягивающий резистор, который стоит между линией и питанием. Если два чипа займут линию одновременно, ни один не тянет её вверх, и короткого замыкания не будет.
Ключевое отличие от UART в адресации. Раз к одной шине подключено сразу несколько чипов, у каждого есть личный адрес, обычно заданный ещё на заводе. Адрес семибитный, так что теоретически на шине помещается чуть больше сотни устройств. На практике число чипов раньше упирается в ёмкость линии: для режимов 100 и 400 кбит/с стандарт разрешает не больше 400 пФ.
Процессор перед началом разговора называет вслух адрес, скажем, контроллера батареи, и откликается подтверждением только он один, а все остальные участники этой же шины игнорируют чужое сообщение.

Можно наткнуться на ситуацию, когда два датчика приезжают с одним и тем же заводским адресом по умолчанию. Спасают либо отдельный вывод на самом чипе, которым можно переключить адрес на соседний, например с 0x68 на 0x69, либо отдельная микросхема-мультиплексор, которая на время прячет одного из тёзок от общей шины, пока процессор говорит с другим.
Шина I2C хорошо подходит компонентам, которым нужно передавать небольшие объёмы данных, но критически важно экономить место на плате. Ею пользуются многие из упомянутых ранее устройств.
Удобство очевидно, ведь вместо отдельной пары проводов на каждый чип хватает одной общей пары сразу на десяток устройств. Платится за это скоростью. Резистор поднимает линию неторопливо, и чем длиннее дорожки и больше на них чипов, тем медленнее.
Поэтому I2C обычно работает на 100 или 400 килобитах в секунду. Стандарт описывает и более быстрые режимы, 1 и 3,4 Мбит/с, но встречаются они реже. В новых мобильных платформах и датчиках уже появляется I3C, более быстрый наследник I2C с теми же двумя проводами.
SPI, или скоростная линия для больших объёмов
Есть в телефоне участники, которым общий чат тесноват. Например, сканер отпечатка: ему нужно отдавать целые изображения, десятки килобайт за раз. Иногда на SPI сажают и контроллер тачскрина, особенно в моделях, которые опрашивают касания сотни раз в секунду, хотя многие тачскрины до сих пор работают по I2C. Serial Peripheral Interface используют, когда нужно как можно быстрее перегнать увесистый кусок данных.

У SPI аналогия смещается от общего чата к пульту, на котором у начальника есть отдельная кнопка вызова для каждого нужного сотрудника. У процессора есть общий провод для тактового сигнала и две общие линии для самих данных, одна от процессора к чипам и одна обратно, так что говорить и слушать можно одновременно.
Но вдобавок к каждому участнику, например к сканеру отпечатка, тянется собственный провод выбора устройства, его обычно подписывают CS или SS. Процессор активирует провод нужного чипа, и отвечает только он, остальные молчат. Активный уровень у этого провода, как правило, низкий, а невыбранные чипы отключают свой выход от общей линии, чтобы не мешать.
Единого официального стандарта у SPI, в отличие от I2C, никогда не было, поэтому в даташитах одни и те же провода называют по-разному: где-то MOSI (master output slave input) и MISO, где-то SDO и SDI, а где-то DIN и DOUT. Подвох в том, что MOSI соединяют с MOSI, а SDO одного чипа идёт на SDI другого, если оба имени даны от лица самого чипа. В новых документах встречаются и другие варианты, например PICO и POCI.
Ещё у SPI есть четыре режима (в документации их задают параметрами CPOL и CPHA). CPOL (Clock Polarity) определяет исходное состояние линии тактирования (ноль там в покое или единица). А CPHA (Clock Phase) определяет, на каком фронте такта читать бит, на первом или на втором. Нарастающий это фронт или спадающий, зависит уже от CPOL, и вместе два параметра дают те самые четыре режима.
SPI на фоне I2C спокойно берёт десятки мегабит. Главная причина в том, что выходы чипов сами тянут линию и вверх, и вниз, не дожидаясь резистора. Вдобавок здесь нет ни адресов, ни подтверждений, так что на служебные биты ничего не тратится.
Платить за скорость приходится проводами, их нужно три общих и ещё по одному на каждый чип, против двух на всех у I2C. Поэтому SPI ставят там, где нужно быстро гонять большие объёмы данных.
Когда крышка закрывается
Самое время мысленно закрыть крышку телефона, которую мы открыли в самом начале, и подвести итог.

Каждому немому чёрному квадратику инженер подбирает либо личный звонок, либо место в общем чате, либо скоростную линию, смотря что именно чипу нужно сказать процессору и как быстро.
UART | I2C | SPI | |
|---|---|---|---|
Сигнальных проводов | 2 (4 с управлением потоком) | 2 | 3 общих и по одному на чип |
Устройств | 2 | десятки, у каждого адрес | сколько хватит выводов процессора |
Тактовый провод | нет | есть | есть |
Кто начинает разговор | любая сторона | ведущий | ведущий |
Ходовая скорость | 9600–115200 бит/с, бывает до нескольких Мбит/с | 100 или 400 кбит/с, (реже 1 и 3,4 Мбит/c) | десятки Мбит/с |
В телефоне | Bluetooth, отладочная консоль | датчик приближения, контроллер батареи | сканер отпечатка, защищённый чип |
Ни один из этих трёх способов передачи данных не лучше и не хуже другого сам по себе, у каждого своя цена в проводах и сложности разводки платы. Когда в следующий раз телефон гасит экран у уха или спокойно докладывает о заряде батареи, вспомните, что за этим спокойствием стоит десяток крошечных договорённостей.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.