SPI

SPI используют там, где нужно быстро передавать много данных на небольшом расстоянии: дисплеи, SD-карты, flash-память, радиомодули, быстрые датчики. Контроллер задаёт такт, выбирает устройство и передаёт байты.
В классическом SPI есть SCK для такта, MOSI для данных от контроллера к модулю, MISO для данных от модуля к контроллеру и CS для выбора конкретного устройства. Общий GND обязателен. Если устройств несколько, каждому обычно нужен свой CS.

Зачем это нужно
Роботу может понадобиться быстро обновлять экран, читать память или получать данные от IMU. I2C часто удобнее для простых датчиков, но SPI лучше подходит для больших блоков данных и высокой частоты обмена на коротких проводах.
SPI сам по себе не говорит, что означает команда. Один дисплей ждёт поток пикселей, память ждёт команду и адрес, а датчик ждёт номер регистра. Поэтому после подключения линий всегда читают документацию конкретного модуля.
Главная идея
Контроллер активирует CS нужного устройства и начинает выдавать импульсы SCK. На каждом такте один бит уходит по MOSI, а другой может возвращаться по MISO.
Если контроллер хочет прочитать данные, он всё равно должен продолжать передавать такты. Часто для этого по MOSI отправляют фиктивные байты-заполнители.
Провода и сигналы
| Линия | Направление | Зачем нужна |
|---|---|---|
SCK | контроллер → устройство | тактовые импульсы |
MOSI | контроллер → устройство | команды, адреса, передаваемые данные |
MISO | устройство → контроллер | ответ, статус, читаемые данные |
CS или SS | контроллер → устройство | выбор устройства для текущей транзакции |
GND | общий провод | общий ноль |
VCC | питание модуля | напряжение зависит от модуля |
В новых текстах вместо MOSI/MISO иногда пишут COPI/CIPO, но в Arduino-библиотеках и на большинстве модулей чаще встречаются старые обозначения. Для работы важно не название, а направление сигнала.
Где находятся пины
| Плата | SPI-пины | Комментарий |
|---|---|---|
| Arduino Uno | D13/SCK, D11/MOSI, D12/MISO, D10/SS | линии также есть на разъёме ICSP |
| Arduino Nano | D13/SCK, D11/MOSI, D12/MISO, D10/SS | расположение другое, номера похожи на Uno |
| Arduino Mega | D52/SCK, D51/MOSI, D50/MISO, D53/SS | не совпадает с Uno |
| ESP32 DevKit | часто VSPI: GPIO18/SCK, GPIO23/MOSI, GPIO19/MISO, GPIO5/SS | Arduino-ESP32 позволяет задавать другие пины |
| ESP8266 | обычно аппаратный SPI занят flash-памятью; для внешних модулей используют доступные SPI-пины платы | зависит от конкретной платы |
Пин CS можно выбрать почти любым свободным цифровым выводом, если библиотека модуля это поддерживает. Но аппаратный SS на некоторых микроконтроллерах влияет на режим SPI, поэтому его поведение проверяют отдельно.
Подключение устройства к Arduino Uno: TFT-дисплей

| Контакт TFT-модуля | Arduino Uno | Зачем |
|---|---|---|
SCK | D13 | такт SPI |
DIN, SDA или MOSI | D11/MOSI | данные к дисплею |
SDO или MISO, если есть | D12/MISO | чтение ответа от дисплея |
CS | D10 | выбор дисплея |
GND | GND | общий ноль |
VCC | по документации модуля | часто дисплей требует 3,3 В логики |
У многих TFT-дисплеев есть дополнительные выводы DC или A0 и RST. Они не являются базовыми линиями SPI, но нужны конкретному дисплею: DC различает команду и данные, RST сбрасывает контроллер дисплея.
Несколько устройств на одной SPI-шине

SCK, MOSI и MISO можно сделать общими для нескольких устройств, но CS обычно отдельный для каждого:
| Линия | Дисплей | Память | IMU |
|---|---|---|---|
SCK | общий | общий | общий |
MOSI | общий | общий | общий |
MISO | общий, если используется | общий | общий |
CS | свой пин | свой пин | свой пин |
Перед транзакцией контроллер активирует только один CS. Невыбранные устройства должны отпускать линию MISO. Если модуль этого не делает, несколько устройств начнут одновременно управлять одним проводом.
Пример с несколькими Arduino

Две Arduino Uno можно соединить так, чтобы одна была контроллером SPI, а другая отвечала как периферия.
| Arduino-контроллер | Arduino-периферия |
|---|---|
D13/SCK | D13/SCK |
D11/MOSI | D11/MOSI |
D12/MISO | D12/MISO |
D10/SS | D10/SS |
GND | GND |
Здесь линии не «перекрещивают» по названию, как в UART. Современные обозначения COPI и CIPO прямо показывают направление: от контроллера к периферии и обратно. В старой документации им обычно соответствуют названия MOSI и MISO. Роль платы определяет направление.
Минимальная идея для платы-контроллера:
#include <SPI.h>
const byte DEVICE_SELECT = 10;
void setup() {
SPI.begin();
pinMode(DEVICE_SELECT, OUTPUT);
digitalWrite(DEVICE_SELECT, HIGH);
}
void loop() {
digitalWrite(DEVICE_SELECT, LOW);
byte answer = SPI.transfer(0x55);
digitalWrite(DEVICE_SELECT, HIGH);
delay(1000);
}
Скетч платы-периферии сложнее, потому что нужно правильно обслуживать аппаратный SPI и момент выбора SS. Для первого знакомства достаточно собрать схему, увидеть такт SCK и байт 0x55 на логическом анализаторе.
Режимы SPI
У SPI есть четыре режима, которые задают положение такта относительно данных:
| Режим | CPOL | CPHA | Что меняется |
|---|---|---|---|
MODE0 | 0 | 0 | такт в покое низкий, выборка на первом фронте |
MODE1 | 0 | 1 | такт в покое низкий, выборка на втором фронте |
MODE2 | 1 | 0 | такт в покое высокий, выборка на первом фронте |
MODE3 | 1 | 1 | такт в покое высокий, выборка на втором фронте |
Если режим выбран неверно, байты могут выглядеть почти правильными, но быть сдвинутыми. Режим, максимальную частоту и порядок битов берут из datasheet устройства.
Частые ошибки
| Ошибка | Что произойдёт |
|---|---|
забыли GND | уровни не имеют общего отсчёта |
перепутали MOSI и MISO | устройство не получает команду или контроллер не видит ответ |
не управляют CS | модуль не понимает границы команды |
выбрали неверный CPOL/CPHA | байты читаются со сдвигом |
| подали 5 В на 3,3-вольтовый модуль | можно повредить входы |
| сделали длинные провода на высокой частоте | появляются искажения и ошибки |
Что запомнить про SPI
- SPI использует отдельный такт
SCK. MOSIидёт от контроллера к устройству,MISO— обратно.- Каждому устройству обычно нужен свой
CS. - Для чтения контроллер всё равно должен выдавать такт.
- Режим SPI и частоту выбирают по datasheet конкретного модуля.
Практика
- Найдите на Arduino Uno пины
D13,D11,D12,D10. - Нарисуйте подключение TFT-дисплея и подпишите все провода.
- Добавьте на схему второй SPI-модуль и отдельный
CS. - Снимите логическим анализатором
SCK,MOSI,MISOиCS.
Проверьте себя
- Чем SPI отличается от UART по тактированию?
- Почему у нескольких SPI-устройств обычно разные
CS? - В каких направлениях передают данные
COPIиCIPOи как эти линии называются в старых обозначениях? - Почему чтение по SPI требует передачи байтов-заполнителей?
Сначала ответьте без подсказки. Ответ можно считать полным, если вы:
- формулируете основную мысль своими словами;
- называете важные условия, ограничения или меры безопасности;
- для схемы, кода или расчёта показываете ход решения и ожидаемый результат.
Если один из пунктов объяснить не получается, найдите соответствующую главу статьи, перечитайте её и повторите ответ.
Словарь статьи
- SPI — синхронный интерфейс с общей линией такта и отдельным выбором периферии.
- SCK — тактовый сигнал от контроллера.
- COPI — данные от контроллера к периферийному устройству; старое обозначение —
MOSI. - CIPO — данные от периферийного устройства к контроллеру; старое обозначение —
MISO. - CS/SS — сигнал выбора конкретного периферийного устройства.
- CPOL/CPHA — параметры уровня покоя такта и фронта выборки данных.
Связанные темы
- UART — асинхронная связь без отдельного такта.
- I2C — адресная шина с двумя сигнальными линиями.
- 1-Wire — одна линия данных и ROM-коды.
- Сравнение протоколов — как выбирать интерфейс.
- Отладка обмена — как проверять режим, уровни и сигналы.
Источники
- Arduino Docs. Arduino Uno Rev3.
- Arduino Docs. Introduction to SPI.
- Espressif. Arduino-ESP32 SPI API.
- Microchip. Serial Peripheral Interface peripheral.
- Texas Instruments. Common SPI Communication Issues.