Использование интерфейса SPI в Arduino – полное руководство


Современные микроконтроллеры используют много различных протоколов для взаимодействия с различными датчиками и периферийными устройствами. Одними из часто используемых протоколов проводной и беспроводной связи являются протоколы последовательной связи (Serial Communication). Последовательная связь – это процесс передачи одного бита за другим с течением времени, последовательно, по каналу связи или шине. Наиболее известными протоколами последовательной связи в настоящее время являются UART, CAN, USB, I2C и SPI.

Внешний вид проекта по взаимодействию между платами Arduino по интерфейсу SPI

В этой статье мы рассмотрим протокол (интерфейс) SPI и как его использовать в плате Arduino. Мы будем использовать протокол SPI для связи между двумя платами Arduino. Одна из плат Arduino будет выступать в качестве ведущей (Master), а другая – в качестве ведомой (Slave). К обоим платам Arduino будут кнопки и светодиоды. Чтобы продемонстрировать возможности связи по протоколу SPI между двумя платами Arduino мы будем управлять светодиодом на ведущей стороне при помощи нажатия кнопки на ведомой стороне и наоборот – все это мы будем осуществлять с помощью протокола последовательной связи SPI.

Что такое SPI

SPI расшифровывается как Serial Peripheral Interface и переводится как последовательный интерфейс (периферийных устройств), а по своей сути он является протоколом последовательной связи. Интерфейс SPI был разработан в компании Motorola в 1970 г. Интерфейс SPI имеет полное дуплексное соединение, что означает что данные передаются и принимаются одновременно. То есть ведущий (master) может передавать данные ведомому (slave), а ведомый одновременно с этим может передавать данные ведущему. SPI является протоколом синхронной последовательной связи, то есть ему для работы необходима синхронизация всех устройств. Ранее использование данного интерфейса на нашем сайте мы рассматривали при подключении графического ЖК дисплея Nokia 5110 к плате Arduino.

Принципы работы интерфейса SPI

Для работы по принципу ведущий/ведомый (master/Slave) протокол SPI использует 4 линии (провода). В этом протоколе ведущий всегда один, а ведомых может быть несколько. В качестве ведущего устройства обычно выступает микроконтроллер, а в качестве ведомых устройств могут выступать микроконтроллеры, датчики, АЦП, ЦАП, ЖК дисплеи и т.д.

На следующем рисунке показан принцип работы протокола SPI с одним ведущим (Master) и одним ведомым (Slave).

Принцип работы протокола SPI с одним ведущим (Master) и одним ведомым (Slave)

SPI интерфейс для своей работы использует 4 линии – MISO, MOSI, SS, and CLK. Их назначение следующее:

  • MISO (Master in Slave Out) – линия ведомого для передачи данных ведущему;
  • MOSI (Master Out Slave In) – линия ведущего для передачи данных ведомому;
  • SCK (Serial Clock) – по этой линии передаются сигналы (импульсы) синхронизации, формируемые ведущим;
  • SS (Slave Select) – ведущий (Master) может использовать эту линию для включения и выключения определенных устройств (ведомых).

На следующем рисунке показан принцип работы протокола SPI с одним ведущим (Master) и несколькими ведомыми (Slave).

Принцип работы протокола SPI с одним ведущим (Master) и несколькими ведомыми (Slave)

Чтобы начать связь (взаимодействие) между ведущим и ведомым нам необходимо установить на контакте ведомого Slave Select (SS) напряжение низкого уровня чтобы он мог взаимодействовать с ведущим. Когда на этом контакте напряжение высокого уровня (high) ведомый игнорирует ведущего. Это позволяет иметь множество ведомых устройств, работающих по протоколу SPI, использующих одни и те же (общие) линии MISO, MOSI и CLK ведущего устройства. Как вы можете видеть из представленного рисунка для 4-х ведомых устройств линии SCLK, MISO, MOSI общие для соединения с ведущим, а линии (контакты) SS каждого ведомого устройства подключены к отдельным контактам SS (SS1, SS2, SS3, SS4) ведущего устройства. При помощи установки на требуемом контакте SS напряжения низкого уровня (LOW) ведущий (master) может взаимодействовать с нужным ему ведомым (slave).

Контакты SPI в плате Arduino Uno

На следующем рисунке красным прямоугольником отмечены контакты, которые могут быть использованы в плате Arduino Uno для связи по протоколу SPI.

Контакты SPI в плате Arduino Uno

Линия интерфейса SPI Контакт Arduino Uno
MOSI 11 или ICSP-4
MISO 12 или ICSP-1
SCK 13 или ICSP-3
SS 10

С контактами разобрались, двигаемся дальше.

Использование интерфейса SPI в Arduino

Перед тем как начать обмен данными между двумя платами Arduino по протоколу SPI давайте рассмотрим основные принципы работы с библиотекой SPI (SPI library) в Arduino IDE.

Для того чтобы подключить использование этой библиотеки в программе применяется простая команда #include<SPI.h>. Далее для задействования протокола SPI в плате Arduino необходимо выполнить следующую последовательность шагов:

1. SPI.begin()

Инициализирует шину SPI при помощи установки режимов работы контактов SCK, MOSI и SS на вывод данных, подачи на контакты SCK и MOSI напряжения низкого уровня (low), а на контакт SS – напряжения высокого уровня (high).

2. SPI.setClockDivider(divider)

Используется для установки делителя (коэффициента деления) для сигнала синхронизации SPI по отношению к тактовой частоте микроконтроллера в плате Arduino. Можно использовать делители 2, 4, 8, 16, 32, 64 или 128.

Обозначение делителей:

• SPI_CLOCK_DIV2
• SPI_CLOCK_DIV4
• SPI_CLOCK_DIV8
• SPI_CLOCK_DIV16
• SPI_CLOCK_DIV32
• SPI_CLOCK_DIV64
• SPI_CLOCK_DIV128

3. SPI.attachInterrupt(handler)

Включает режим прерываний в ведомом (slave) устройстве. Прерывание будет возникать каждый раз, когда ведомое устройство будет принимать данные от ведущего (master) устройства.

4. SPI.transfer(val)

Эта функция используется для одновременного приема и передачи данных между ведущим и ведомым.

Необходимые компоненты

  1. Плата Arduino Uno (2 шт.) (купить на AliExpress).
  2. Светодиод (2 шт.) (купить на AliExpress).
  3. Кнопка (2 шт.).
  4. Резистор 10 кОм (2 шт.) (купить на AliExpress).
  5. Резистор 2,2 кОм (2 шт.) (купить на AliExpress).
  6. Макетная плата (2 шт.).
  7. Соединительные провода.

Схема проекта

Схема проекта для последовательной связи между двумя платами Arduino по протоколу SPI представлена на следующем рисунке.

Схема проекта для последовательной связи между двумя платами Arduino по протоколу SPIВнешний вид собранной конструкции проекта на макетных платах представлен на следующем рисунке.

Внешний вид собранной конструкции проекта на макетных платах

Объяснение программы для Arduino

Нам будут необходимы две программы: одна – для ведущей платы Arduino, а другая – для ведомой платы Arduino. Коды обоих программ приведены в конце статьи, здесь же мы кратко рассмотрим их основные фрагменты.

Программа для ведущей (Master) платы Arduino

1. Первым делом в программе нам необходимо подключить библиотеку SPI чтобы получить возможность использования функций этого протокола.

  1. В функции void setup() мы инициализируем последовательную связь со скоростью 115200 бод/с.

Также в этой функции мы зададим режим работы на ввод данных для контакта 2 (к нему подключена кнопка) и режим работы на вывод данных для контакта 7 (к нему подключен светодиод).

Далее мы инициализируем связь по протоколу SPI.

Далее установим делитель для связи по протоколу SPI. Мы будем использовать делитель 8.

Далее подадим на контакт SS напряжение высокого уровня (HIGH) чтобы по умолчанию (в начальный момент времени) у нас не было связи с ведомой arduino.

3. В функции void loop() мы будем считывать состояние кнопки (нажата или нет) подключенной к контакту чтобы передавать соответствующее значение ведомой плате Arduino.

В зависимости от состояния кнопки мы будем записывать в переменную x (ее мы будем передавать ведомой плате Arduino) значение 1 или 0.

Перед передачей информации нам необходимо установить на контакте slave select (выбор ведомого) напряжение низкого уровня (LOW) чтобы начать передачу от ведущего к ведомому.

Далее нам необходимо выполнить еще один важный шаг. При помощи следующей команды мы будем передавать значение кнопки сохраненное в переменной Mastersend ведомой arduino, а также одновременно с этим принимать значение от ведомой arduino и сохранять его в переменной Mastereceive.

После этого на основе значения Mastereceive мы будем включать или выключать светодиод подключенный к ведущей плате Arduino.

Примечание: мы будем использовать функцию serial.println() для просмотра результатов работы программы в окне монитора последовательной связи Arduino IDE. Более подробно все эти процессы можно посмотреть на видео, приведенном в конце статьи.

Программа для ведомой (Slave) платы Arduino

1. Первым делом в программе нам необходимо подключить библиотеку SPI чтобы получить возможность использования функций этого протокола.

2. В функции void setup() мы инициализируем последовательную связь со скоростью 115200 бод/с.

Также в этой функции мы зададим режим работы на ввод данных для контакта 2 (к нему подключена кнопка) и режим работы на вывод данных для контакта 7 (к нему подключен светодиод).

Важным моментом для ведомой платы Arduino является команда:

Эта команда устанавливает на контакте MISO режим вывода данных – это необходимо для передачи данных ведущей плате Arduino.

Далее переводим интерфейс SPI на этой плате в ведомый режим (Slave Mode) при помощи регистра управления SPI (SPI Control Register).

Затем включаем прерывание для связи по протоколу SPI. Если будут приниматься данные от ведущего (master) будет вызываться процедура обработки прерывания (Interrupt Routine) и принятое значение будет извлекаться из регистра SPDR (SPI data Register).

Значение от ведущего будет извлекаться из регистра SPDR и сохраняться в переменной Slavereceived. Это будет выполняться в следующей процедуре обработки прерывания:

3. Далее в функции void loop() мы будем включать или выключать светодиод, подключенный к ведомой плате Arduino, в зависимости от значения в переменной Slavereceived.

Далее мы считываем состояние кнопки подключенной к ведомой плате Arduino и сохраняем ее значение в переменной Slavesend. Чтобы передать ее значение ведущей плате Arduino мы записываем значение Slavesend в регистр SPDR.

Примечание: мы будем использовать функцию serial.println() для просмотра результатов работы программы в окне монитора последовательной связи Arduino IDE. Более подробно все эти процессы можно посмотреть на видео, приведенном в конце статьи.

Тестирование работы проекта

На следующем рисунке показано тестирование работы проекта. Когда мы нажимаем на кнопку, подключенную к ведущей плате Arduino, зажигается белый светодиод, подключенный к ведомой плате Arduino.

Зажигается белый светодиод, подключенный к ведомой плате Arduino

А когда мы нажимаем на кнопку, подключенную к ведомой плате Arduino, зажигается красный светодиод, подключенный к ведущей плате Arduino.

Зажигается красный светодиод, подключенный к ведущей плате Arduino

Исходный код программы (скетча)

Код программы для ведущей (Master) платы Arduino

Код программы для ведомой (Slave) платы Arduino

Видео, демонстрирующее работу схемы

(Проголосуй первым!)
Загрузка...
15 831 просмотров

Комментарии

Использование интерфейса SPI в Arduino – полное руководство — 6 комментариев

  1. Зачем используется модификатор volatile, ведь в Ардуино нет многопоточности?

    • Нет, но она может быть искусственно смоделирована в ней, например, с помощью FreeRTOS. Конкретно для чего здесь она использована, не задавался таким вопросом, но если посмотреть буржуинские сайты - то там делают именно так. В общем, данный элемент я списал с иностранного сайта

  2. (1)
    > Что такое SPI
    > ... SPI является проколом синхронной последовательной связи...
    исправьте опечатку

    (2)
    > 3. SPI.attachInterrupt(handler)
    > Эта функция вызывается когда ведомое (slave) устройство принимает данные от ведущего (master) устройства.
    а разве она не прерывание включает?

    • Да, спасибо за внимательность. Отмеченные вами опечатки поправил. SPI.attachInterrupt - да, она включает режим обнаружения прерываний в ведомом устройстве

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *