3.22. SPI у коді

machine.SPI обгортає апаратний SPI-контролер; лінії CS — це звичайні виходи Pin, якими керує скрипт. Створіть екземпляр SPI з ідентифікатором шини, бажаною тактовою частотою та (якщо потрібно) режимом:

from machine import SPI, Pin

spi = SPI(0, baudrate=1_000_000, polarity=0, phase=0)
cs = Pin("P3", Pin.OUT, value=1)         # CS idle high

id вибирає, який апаратний блок SPI використовувати; доступні номери та виводи SCK/MOSI/MISO, до яких вони відображаються, залежать від плати (див. Плати OpenMV). baudrate — це частота SCK у герцах — фактична частота, яку досягає апаратне забезпечення, може бути дещо нижчою через поділ тактового сигналу, що буде показано у виведеному значенні об’єкта SPI.

Вивід CS створюється з value=1, щоб він залишався знятим у стані спокою. Кожна транзакція стверджує CS (переводить його в низький рівень), передає байти, і знімає CS (переводить його в високий рівень).

3.22.1. Читання, запис, обмін

Три методи покривають типові випадки:

cs.value(0)
spi.write(b"\x10\x20\x30")              # send 3 bytes, ignore what comes back
cs.value(1)

cs.value(0)
data = spi.read(4)                      # read 4 bytes; sends 0x00 while reading
cs.value(1)

rx = bytearray(2)
cs.value(0)
spi.write_readinto(b"\x9F\x00", rx)     # send 0x9F, 0x00; receive 2 bytes
cs.value(1)

write() — це швидкий шлях лише для запису; контролер надсилає байти і відкидає все, що периферійний пристрій надіслав назад по MISO. read() — дзеркальна операція: він генерує N імпульсів SCK, надсилаючи фіксований байт-заповнювач (0 за замовчуванням) по MOSI, і зберігає байти MISO. write_readinto() — повнодуплексна форма: вона надсилає байти з одного буфера і зберігає одночасно отримані байти MISO в інший. Багато периферійних пристроїв використовують цю схему — «надіслати командний байт, потім прочитати відповідь у наступній передачі» — тому дві операції природно вкладаються в один виклик write_readinto.

Більшість периферійних пристроїв вимагають, щоб лінія CS залишалася знятою протягом усієї транзакції (від командних байтів до байтів відповіді), тому тримайте дужки cs.value(0) / cs.value(1) навколо всієї послідовності, а не навколо кожного виклику методу.

3.22.2. Типове зчитування датчика

Багато SPI-датчиків організують свій стан у вигляді набору внутрішніх регістрів і дотримуються однакової форми обміну: надіслати адресу регістра (з прапором читання/запису у старшому біті), потім прочитати або записати байти регістра. Зчитування регістра 0x0F на такому пристрої:

rx = bytearray(2)
cs.value(0)
spi.write_readinto(b"\x8F\x00", rx)     # 0x80 = "read" flag, then reg 0x0F
cs.value(1)
register_value = rx[1]

Перший байт MISO є сміттям (пристрій ще отримував команду в цей момент); другий байт MISO містить вміст регістра. Точний формат командного байта — який біт є прапором читання/запису, чи автоматично збільшується адреса при багатобайтовому зчитуванні — описано в таблиці даних пристрою.

3.22.3. Бітовий банг

Вищезазначений екземпляр SPI використовує апаратний блок SPI: спеціалізований периферійний пристрій всередині MCU з власним регістром зсуву та генератором тактового сигналу, який апаратно формує сигнали SCK / MOSI / MISO. Програмне забезпечення лише передає байт; біти переміщуються по проводу без подальшої участі CPU, залишаючи CPU вільним для виконання іншої роботи паралельно.

Альтернативою є бітовий банг: програмне забезпечення перебирає кожен біт і безпосередньо перемикає виводи GPIO для формування тієї ж форми хвилі. Апаратний периферійний пристрій при цьому не використовується — CPU переводить SCK у низький рівень, встановлює MOSI, переводить SCK у високий рівень, зчитує MISO і так далі для кожного біта кожного байта. Це повністю завантажує CPU на час усієї транзакції і працює повільніше, ніж апаратний блок, але працює на будь-якому виводі і не потребує вільного апаратного блоку.

machine.SoftSPI — це реалізація того самого SPI API на основі бітового бангу:

from machine import SoftSPI, Pin

spi = SoftSPI(baudrate=500_000, polarity=0, phase=0,
              sck=Pin("P2"), mosi=Pin("P0"), miso=Pin("P1"))

Використовуйте його, коли пристрій потрібно підключити до виводів, не підключених до апаратного блоку SPI, або коли всі апаратні блоки вже зайняті. 500 kHz — комфортний верхній поріг для більшості камер; CPU зайнятий протягом усієї транзакції.