Все статьиПрограммирование

Как работает SPI (Serial Peripheral Interface)? Полное руководство для Arduino и электроники

БА
Бексултан Айтен
CTO, Alashed
30 июля 2025 г.
9 мин чтения
Как работает SPI (Serial Peripheral Interface)? Полное руководство для Arduino и электроники

SPI (Serial Peripheral Interface) — высокоскоростной синхронный протокол передачи данных для микроконтроллеров, датчиков, SD-карт и дисплеев. Разбираем принцип работы, режимы, примеры кода для Arduino.

Пример подключения устройства (дисплей) по SPI
Пример подключения устройства (дисплей) по SPI

SPI (Serial Peripheral Interface) — это высокоскоростной синхронный протокол передачи данных, широко используемый в микроконтроллерах, датчиках, SD-картах и дисплеях. В отличие от UART, SPI работает с тактовым сигналом, что обеспечивает быстрый и надёжный обмен данными.

В этой статье мы разберём:

  • Что такое SPI и где он применяется?
  • Принцип работы SPI (устройство, режимы передачи)
  • Основные линии SPI: MOSI, MISO, SCK, SS
  • SPI в Arduino: аппаратная и программная реализация
  • Примеры кода для работы с SPI
  • Сравнение SPI с I2C и UART
  • Частые проблемы и их решение

1. Что такое SPI и зачем он нужен?

SPI — это синхронный последовательный интерфейс, разработанный для быстрого обмена данными между микросхемами. Он используется в:

  • Датчиках (акселерометры, гироскопы, термометры)
  • Памяти (EEPROM, Flash, SD-карты)
  • Дисплеях (OLED, TFT, LED-драйверы)
  • Беспроводных модулях (Wi-Fi, Bluetooth, NRF24L01)

Ключевые особенности SPI:

  • Высокая скорость (до десятков МГц)
  • Полный дуплекс (одновременная передача и приём)
  • Простая аппаратная реализация
  • Гибкость (поддержка множества ведомых устройств)

Главный недостаток: Требует больше линий, чем I2C или UART. Обычно требуется 7-8 проводов для подключения SPI устройств, из них 2-3 питание.

2. Как работает SPI? Основы синхронной передачи

SPI использует 4 основные линии:

ЛинияНазначение
SCKТактовый сигнал (синхронизация)
MOSIДанные от мастера к ведомому (Master Out Slave In)
MISOДанные от ведомого к мастеру (Master In Slave Out)
SS/CSВыбор ведомого устройства (Slave Select/Chip Select)
Пример соединения двух микроконтроллеров по SPI.
Пример соединения двух микроконтроллеров по SPI.

Принцип работы:

1. Мастер (например, Arduino) генерирует тактовый сигнал SCK.

2. Данные передаются по MOSI и принимаются по MISO одновременно (полный дуплекс).

3. SS (Slave Select) переводится в LOW, чтобы активировать нужное устройство.

Режимы SPI (CPOL и CPHA)

SPI поддерживает 4 режима передачи, определяемые фазами тактового сигнала:

РежимCPOL (Polarity)CPHA (Phase)Описание
000Такт начинается с LOW, данные читаются по фронту
101Такт начинается с LOW, данные читаются по срезу
210Такт начинается с HIGH, данные читаются по фронту
311Такт начинается с HIGH, данные читаются по срезу

Важно: Устройства должны использовать одинаковый режим SPI!

3. SPI в Arduino: аппаратная и программная реализация

Аппаратный SPI (Hardware SPI)

В Arduino Uno (ATmega328P) аппаратный SPI выведен на контакты:

  • SCK13
  • MOSI11
  • MISO12
  • SS (CS, chip select) → 10 (но можно выбрать любой цифровой пин)

Пример чтения/записи в EEPROM (25LC512):

```cpp

#include <SPI.h>

void setup() {

SPI.begin(); // Инициализация SPI

pinMode(10, OUTPUT); // SS (Slave Select)

digitalWrite(10, HIGH); // Деактивировать EEPROM

}

void writeEEPROM(uint16_t addr, uint8_t data) {

digitalWrite(10, LOW); // Активировать EEPROM

SPI.transfer(0x06); // Команда "Write Enable"

digitalWrite(10, HIGH);

digitalWrite(10, LOW);

SPI.transfer(0x02); // Команда записи

SPI.transfer(addr >> 8); // Старший байт адреса

SPI.transfer(addr & 0xFF); // Младший байт адреса

SPI.transfer(data); // Данные

digitalWrite(10, HIGH);

}

uint8_t readEEPROM(uint16_t addr) {

digitalWrite(10, LOW);

SPI.transfer(0x03); // Команда чтения

SPI.transfer(addr >> 8);

SPI.transfer(addr & 0xFF);

uint8_t data = SPI.transfer(0x00); // Чтение данных

digitalWrite(10, HIGH);

return data;

}

void loop() {

writeEEPROM(0x0001, 0xAB); // Запись байта 0xAB по адресу 0x0001

uint8_t value = readEEPROM(0x0001); // Чтение

delay(1000);

}

`

Программный SPI (Bit Banging)

Если аппаратного SPI недостаточно (например, нужно несколько шин), можно реализовать SPI вручную:

```cpp

#define SCK_PIN 13

#define MOSI_PIN 11

#define MISO_PIN 12

#define SS_PIN 10

void setup() {

pinMode(SCK_PIN, OUTPUT);

pinMode(MOSI_PIN, OUTPUT);

pinMode(MISO_PIN, INPUT);

pinMode(SS_PIN, OUTPUT);

digitalWrite(SS_PIN, HIGH);

}

uint8_t softSPITransfer(uint8_t data) {

uint8_t received = 0;

for (int i = 0; i < 8; i++) {

digitalWrite(MOSI_PIN, (data & 0x80) ? HIGH : LOW);

digitalWrite(SCK_PIN, HIGH);

received <<= 1;

if (digitalRead(MISO_PIN)) received |= 1;

digitalWrite(SCK_PIN, LOW);

data <<= 1;

}

return received;

}

`

4. Сравнение SPI с I2C и UART

ПараметрSPII2CUART
СкоростьДо 50 МГцДо 3.4 МГцДо 1 МГц
Линии4 (SCK, MOSI, MISO, SS)2 (SDA, SCL)2 (TX, RX)
Тип передачиПолный дуплексПолудуплексПолудуплекс
СинхронизацияТактовый сигнал (SCK)Тактовый сигнал (SCL)Асинхронный
Подключение устройствДо 10+ (с отдельными SS)До 128 (по адресам)1:1 (без преобразователей)

Когда выбирать SPI?

  • Нужна высокая скорость (SD-карты, дисплеи).
  • Не критично количество проводов.
  • Не требуется поддержка множества устройств на одной шине.

5. Частые проблемы и их решение

1. Устройство не отвечает

Проверьте:

  • Правильно ли подключены MOSI/MISO (не перепутаны местами).
  • Верный ли режим SPI (CPOL/CPHA) выбран в коде.
  • Активирован ли SS (Chip Select).

2. Помехи и искажённые данные

Решения:

  • Уменьшите скорость SPI (например, с SPI_CLOCK_DIV2 на SPI_CLOCK_DIV8).
  • Используйте экранированные провода и подтягивающие резисторы.

3. Конфликт нескольких устройств на одной шине

Каждое ведомое устройство должно иметь отдельный SS-сигнал!

Заключение

SPI — мощный интерфейс для высокоскоростной передачи данных между микросхемами. Он идеален для работы с памятью, датчиками и дисплеями в Arduino-проектах.

Главные выводы:

  • SPI использует 4 линии (SCK, MOSI, MISO, SS).
  • Поддерживает полный дуплекс и скорость до десятков МГц.
  • В Arduino есть аппаратная поддержка SPI, но можно реализовать и программно.

Теперь вы знаете, как работает SPI, и сможете применять его в своих устройствах!

P.S. Попробуйте подключить SPI-модуль (например, RFID RC522 или SD-карту) к Arduino — это отличный способ закрепить знания.

Попробуйте Alashed бесплатно

Подключите школу к пилоту. Генерируйте КМЖ за 2 минуты, ведите CodeStudio уроки, заказывайте оборудование — всё в одном месте.

Попробовать бесплатноДемо