Главная chevron_right Уроки chevron_right Связь chevron_right Arduino и Serial Peripheral Interface (SPI)

Arduino и Serial Peripheral Interface (SPI)

Serial Peripheral Interface (SPI) — синхронный протокол последовательной передачи данных для быстрого обмена между микроконтроллером и периферийными устройствами на коротких расстояниях.

Статья обновлена 18.11.2021 автором Karl Söderby.

Понятия «контроллер» и «периферия» заменили устаревшие термины «master» и «slave». Arduino больше не использует старую терминологию. Таблица соответствий ниже:

Master/Slave (OLD)Controller/Peripheral (NEW)
Master In Slave Out (MISO)Controller In, Peripheral Out (CIPO)
Master Out Slave In (MOSI)Controller Out Peripheral In (COPI)
Slave Select pin (SS)Chip Select Pin (CS)

---

Библиотека SPI

Библиотека SPI входит в состав каждого ядра Arduino — устанавливать её отдельно не нужно. Подробное описание всех функций SPI доступно по ссылкам:

Serial Peripheral Interface (SPI)

При работе по протоколу SPI всегда есть одно устройство-контроллер (как правило, микроконтроллер), которое управляет периферийными устройствами. Все устройства на шине разделяют три общие линии:

  • CIPO (Controller In Peripheral Out) — линия, по которой периферия отправляет данные контроллеру.
  • COPI (Controller Out Peripheral In) — линия, по которой контроллер отправляет данные периферии.
  • SCK (Serial Clock) — тактовый сигнал, синхронизирующий передачу данных; формируется контроллером.

Помимо общих линий, у каждого устройства есть своя:

  • CS (Chip Select) — линия выбора устройства. Когда CS переведён в LOW, устройство активно и общается с контроллером. Когда CS в HIGH — устройство игнорирует шину. Благодаря этому несколько SPI-устройств могут совместно использовать линии CIPO, COPI и SCK.

Что нужно знать перед работой с новым SPI-устройством

Прежде чем писать код для нового SPI-устройства, уточните несколько параметров из даташита:

  • Максимальная тактовая частота. Задаётся первым параметром SPISettings. Например, если чип рассчитан на 15 MHz, передайте 15000000. Arduino автоматически выберет наибольшую допустимую скорость, не превышающую указанное значение, при работе с SPISettings.
  • Порядок битов: MSB или LSB? Задаётся вторым параметром SPISettings: MSBFIRST или LSBFIRST. Большинство SPI-чипов используют MSB first.
  • Полярность и фаза тактового сигнала. Определяют, в каком состоянии находится тактовая линия в режиме ожидания (высокий или низкий уровень) и по какому фронту происходит выборка данных. Задаются третьим параметром SPISettings.
  • Внимательно читайте даташит. Стандарт SPI достаточно гибкий, и каждый производитель реализует его немного по-своему. Не пренебрегайте документацией.

Режимы передачи SPI

Всего существует четыре режима. Они определяют комбинацию полярности тактового сигнала (CPOL) и фазы (CPHA):

ModeClock Polarity (CPOL)Clock Phase (CPHA)Output EdgeData Capture
SPI_MODE000FallingRising
SPI_MODE101RisingFalling
SPI_MODE210RisingFalling
SPI_MODE311FallingRising

Как использовать SPI в коде

Определив параметры SPI, вызовите SPI.beginTransaction(), чтобы начать работу с портом SPI. Порт SPI будет настроен согласно вашим параметрам. Самый простой и надёжный способ — вызывать SPISettings непосредственно внутри SPI.beginTransaction():

SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0));

Если другие библиотеки обращаются к SPI из обработчиков прерываний, они не смогут получить доступ к SPI до тех пор, пока вы не вызовете SPI.endTransaction(). Настройки SPI применяются в начале транзакции, а SPI.endTransaction() их не сбрасывает. Если beginTransaction не будет вызван повторно — настройки сохранятся. Старайтесь сократить время между вызовами до SPI.endTransaction(): это повысит совместимость вашего кода с другими библиотеками, использующими SPI.

При работе с большинством SPI-устройств алгоритм такой: после SPI.beginTransaction() переведите пин Chip Select в LOW, вызовите SPI.transfer() нужное количество раз для передачи данных, затем переведите CS в HIGH и вызовите SPI.endTransaction().

Типичные ошибки

  • Неверный режим SPI. Если данные принимаются некорректно, первым делом проверьте CPOL и CPHA в даташите — это самая частая причина проблем.
  • Слишком высокая частота. Некоторые компоненты и длинные провода не справляются с высокими скоростями. Попробуйте снизить частоту в SPISettings.
  • Забытый CS. Если не перевести CS в LOW перед транзакцией, устройство просто не отреагирует на данные.
  • Конфликт библиотек. Если несколько библиотек используют SPI, убедитесь, что каждая корректно вызывает SPI.beginTransaction() и SPI.endTransaction() — иначе возможны непредсказуемые сбои.

Подробнее о SPI читайте здесь: Wikipedia's page on SPI.

Учебные примеры