ELECTRONICS

Библиотека SPI

встроена в средуArduino, встроенаверсия ядро AVR 1.8.8

Быстрая четырёхпроводная шина для карт памяти, дисплеев, радиомодулей и RFID. Обычно работает внутри других библиотек.

SPI — три общих провода (MOSI, MISO, SCK) плюс по одному проводу выбора CS на каждое устройство. На UNO это выводы 11, 12 и 13; CS — любой. Обмен идёт мегабитами в секунду, поэтому на SPI сидят всё, что передаёт много данных: дисплеи, SD-карты, nRF24L01, RC522.

Напрямую SPI трогают редко — библиотеки модулей делают это сами. Знать нужно раскладку выводов, чтобы правильно подключить, и то, что вывод 13 при этом занят под тактовый сигнал вместе со встроенным светодиодом.

Установка и подключение

Ставить ничего не нужно: библиотека входит в среду Arduino и доступна сразу после установки. Достаточно строки подключения в начале скетча.

#include <SPI.h>

Создание объекта — обычно до setup():

SPI.begin();                                          // в setup(): выводы 11, 12, 13 переходят под шину
pinMode(CS_PIN, OUTPUT); digitalWrite(CS_PIN, HIGH);   // CS своего устройства — вручную

Методы

Только то, что нужно в обычном скетче. Сигнатуры сверены с версией ядро AVR 1.8.8.

begin()
Включить шину. Настраивает MOSI, SCK и вывод SS как выходы.
beginTransaction(SPISettings(hz, order, mode))
Начать обмен с настройками: частота, порядок бит (MSBFIRST), режим 0–3. Так разные устройства на одной шине не мешают друг другу.
transfer(uint8_t data)
Отправить байт и одновременно получить байт в ответ.
transfer16(uint16_t data)
То же с двумя байтами.
transfer(void* buf, size_t count)
Обменять буфер целиком; ответ ложится на место отправленного.
endTransaction()
Закончить обмен, отпустить шину.
end()
Выключить шину, вернуть выводы.
usingInterrupt(uint8_t n)
Сообщить, что обмен идёт и из прерывания — библиотека будет их блокировать на время транзакции.

Пример

#include <SPI.h>

const int CS = 10;

void setup() {
  Serial.begin(9600);
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);           // устройство не выбрано
  SPI.begin();
}

void loop() {
  // прочитать регистр 0x00 у типичного чипа: адрес с битом чтения, потом пустой байт
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  digitalWrite(CS, LOW);
  SPI.transfer(0x00 | 0x80);        // у многих чипов старший бит — признак чтения
  byte value = SPI.transfer(0x00);  // отправляем пустышку, получаем ответ
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
  Serial.println(value, HEX);
  delay(1000);
}

Схема «опустить CS — обменяться — поднять CS» одинакова для любого устройства; отличаются только адреса регистров и режим.

На чём попадаются

Два модуля на одной шине не работают вместе

У каждого свой CS, и в простое он должен быть HIGH. Библиотеки, которые не поднимают CS после обмена, мешают соседям.

На Mega ничего не работает

Там шина на 50, 51, 52, а не на 11, 12, 13. Библиотеки берут правильные выводы сами, но провода надо переставить.

Вывод 10 нужно держать выходом

На AVR вывод SS (10 на UNO), настроенный входом и притянутый к земле, переводит плату в режим ведомого, и шина замолкает.

Модуль на 3,3 В сгорел от UNO

MOSI и SCK с UNO выдают 5 В. nRF24L01 и SD-карты требуют делителей или преобразователя уровней.

Где используется на сайте

Что дальше