Шины I2C и SPI: OLED-дисплей и датчики

Подключаем умные устройства по двум-четырём проводам вместо десятка.

I2C и SPI — последовательные шины, позволяющие одному микроконтроллеру общаться со множеством устройств (дисплеями, датчиками) по нескольким общим проводам.

Зачем нужны шины

Подключать каждый датчик отдельными проводами накладно: выводов не хватит. Шина решает это: устройства висят на общих линиях, а адресуются по «имени» (адресу). Так на двух проводах I2C можно держать десяток датчиков и дисплей.

I2C: два провода на всех

I2C использует две линии: SDA (данные) и SCL (тактирование). У каждого устройства свой адрес. Схема:

  ESP32                устройства
  GPIO21 (SDA) ----+----+----+
  GPIO22 (SCL) --+-|--+-|--+-|
                 | |  | |  | |
               [OLED][датчик][часы]
  (каждый со своим I2C-адресом)

Сканируем шину

from machine import Pin, I2C

i2c = I2C(0, scl=Pin(22), sda=Pin(21))
devices = i2c.scan()
print("Найдены адреса:", [hex(a) for a in devices])
# например: ['0x3c', '0x76'] — дисплей и датчик

Вывод текста на OLED

from machine import Pin, I2C
import ssd1306

i2c = I2C(0, scl=Pin(22), sda=Pin(21))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)

oled.fill(0)
oled.text("Умный дом", 0, 0)
oled.text("t = 23.5 C", 0, 20)
oled.text("h = 45 %", 0, 35)
oled.show()

I2C против SPI

КритерийI2CSPI
Проводов2 (SDA, SCL)4 (MOSI, MISO, SCK, CS)
СкоростьДо 400 кГц–1 МГцДесятки МГц
АдресацияПо адресу устройстваОтдельной линией CS
Когда удобноМного медленных датчиковБыстрые: дисплеи, SD-карты

Как работает под капотом

В I2C мастер (ESP32) формирует тактовые импульсы на SCL и по SDA передаёт сначала адрес нужного устройства, потом данные. Устройство с этим адресом «откликается», остальные молчат. Линии подтянуты к питанию резисторами, а устройства лишь «притягивают» их к земле — отсюда ограничение по скорости. SPI быстрее: у него отдельные линии на отправку и приём и выделенный провод выбора устройства (CS), поэтому адресация не нужна и поток данных плотнее.

Частые ошибки

  • Перепутать SDA и SCL. Шина не заработает, scan() вернёт пусто.
  • Забыть подтяжку. Многие модули уже имеют резисторы; если нет — добавьте pull-up 4.7 кОм.
  • Не сделать oled.show(). Без него нарисованное не появится на экране — рисунок копится в буфере.

Итог

  • I2C и SPI позволяют общаться со множеством устройств по общим линиям.
  • I2C — 2 провода и адресация; SPI — 4 провода, выше скорость.
  • i2c.scan() показывает адреса подключённых устройств.
  • Для OLED после рисования обязателен show().
Проверьте себя
1. Сколько сигнальных линий использует шина I2C?
AОдну
BДве: SDA и SCL
CЧетыре
DВосемь
2. Чем SPI отличается от I2C?
ASPI медленнее
BSPI быстрее, использует больше проводов и отдельную линию выбора устройства CS
CSPI использует только один провод
DОни идентичны
3. Что произойдёт, если не вызвать oled.show() после рисования?
AДисплей сгорит
BНарисованное останется в буфере и не появится на экране
CТекст появится дважды
DI2C перестанет работать