Сдвиг вправо в языке C выполняется оператором >>, за которым следует число, определяющее количество разрядов, на которое производится сдвиг. В результате часть битов будет сдвинута за границу байта. Далее приводится реализация примера из предыдущего раздела на языке C:
byte data = 0b01101001;
byte result = (data & 0b00111000) >> 3;
Представьте, что вы получили два 8-битных байта и должны собрать из них одно 16-битное значение типа int. Для этого можно сдвинуть биты старшего байта в один конец значения int, а затем прибавить второй байт. Этот процесс иллюстрирует рис. 9.3.
Рис. 9.2. Маскирование и сдвиг битов
Рис. 9.3. Объединение двух байтов в значение типа int
Чтобы реализовать это в Arduino C, нужно сначала записать highByte в переменную результата типа int, сдвинуть влево на восемь позиций, а потом прибавить lowByte:
byte highByte = 0x6A;
byte lowByte = 0x0F;
int result = (highByte << 8) + lowByte;
Аппаратная часть SPI
На рис. 9.4 изображена типичная схема подключения к Arduino двух ведомых устройств.
Рис. 9.4. Плата Arduino и два ведомых устройства SPI
Линии тактового сигнала системы (System Clock, SCLK), выход ведущего/вход ведомого (Master Out Slave In, MOSI) и вход ведущего/выход ведомого (Master In Slave Out, MISO) подключаются к контактам на плате Arduino с теми же именами, которые в модели Uno соответствуют контактам D13, D11 и D12. В табл. 9.2 перечислены наиболее распространенные модели плат и соответствие контактов линиям интерфейса SPI.
Таблица 9.2. Контакты интерфейса SPI на плате Arduino
| Модель | SCLK | MOSI | MISO |
|---|---|---|---|
| Uno | 13 (ICSP3) | 11 (ICSP4) | 12 (ICSP1) |
| Leonardo | ICSP3 | ICSP4 | ICSP1 |
| Mega2560 | 52 (ICSP3) | 51 (ICSP4) | 50 (ICSP1) |
| Due | ICSP3 | ICSP4 | ICSP1 |
Линиями выбора ведомого могут быть любые контакты на плате Arduino. Они используются для выбора определенного ведомого устройства непосредственно перед передачей данных и его отключения по завершении обмена данными.
Ни к одной из линий не требуется подключать подтягивающее сопротивление.
Поскольку в некоторых моделях Arduino, в том числе Leonardo, контакты интерфейса SPI имеются только на колодке ICSP, многие платы расширений часто имеют гнезда SPI для подключения к колодке контактов ICSP. На рис. 9.5 изображена колодка ICSP с подписанными контактами.
Рис. 9.5. Контакты ICSP на плате Arduino Uno
Обратите внимание на то, что на плате Arduino Uno имеется вторая колодка ICSP, рядом с кнопкой сброса. Она предназначена для программирования интерфейса USB.
Протокол SPI
Протокол SPI на первый взгляд кажется сложным и запутанным, потому что данные передаются и принимаются обеими сторонами, ведущим и выбранным ведомым, параллельно. Одновременно с передачей ведущим устройством (Arduino) бита по линии MOSI ведомое устройство посылает другой бит по линии MISO плате Arduino.
Обычно Arduino посылает байт данных и затем восемь нулей, одновременно принимая результат от ведомого устройства. Так как частота передачи устанавливается ведущим устройством, убедитесь в том, что она не слишком высока для ведомого устройства.
Библиотека SPI
Библиотека SPI входит в состав Arduino IDE, поэтому вам не придется ничего устанавливать, чтобы воспользоваться ею. Но она поддерживает только сценарии, когда плата Arduino действует в роли ведущего устройства. Кроме того, библиотека поддерживает передачу данных только целыми байтами. Для большинства периферийных устройств этого вполне достаточно, однако некоторые устройства предполагают обмен 12-битными сообщениями, что несколько осложняет обмен из-за необходимости манипуляций с битами, как будет показано в примере в следующем разделе.
Прежде всего, как обычно, необходимо подключить библиотеку SPI:
#include <SPI.h>
Затем инициализировать ее командой SPI.begin в функции запуска передачи: