Serial Peripheral Interface (SPI) is a synchronous serial communication protocol commonly used in microcontrollers and embedded systems. On Arduino boards, SPI enables fast, efficient communication with various external peripherals such as sensors, memories and wireless communication modules. This protocol is appreciated for its simplicity, speed and flexibility.
The SPI link is synchronous, which means that transmission requires the clock given before transmission.
It’s a full-duplex link, which means that you can listen to what you’re transmitting while sending bits.
It’s not an exclusive link: the circuits communicate according to a master-slave scheme, where the master takes care of all communication. Several slaves can coexist on the same bus, in which case selection of the recipient is made via a dedicated line between master and slave called chip select, as shown in the diagram below:
SPI has lines labeled “MOSI”: Master Output Slave Input, generated by the master, lines labeled “MISO”: Master Input Slave Output, generated by the slave, and a clock line (SCK: SPI Serial Clock).
These three lines are connected to their respective lines on one or more slaves. Slaves are identified by their CS (Chip Select) line signal.
On Arduino boards, the pins dedicated to SPI vary according to the board model. For example, on an Arduino Uno, the SPI pins are :
Arduino simplifies the use of SPI with its SPI.h library. Here’s a basic example of how to use this library to communicate with an SPI device:
#include <SPI.h>
void setup() {
// Initialize SPI communication
SPI.begin();
// Configure SS pin as output
pinMode(10, OUTPUT);
}
void loop() {
// Activate slave by setting SS to LOW
digitalWrite(10, LOW);
// Send data byte to SPI device
byte dataSent = 0x42;
byte dataReceived = SPI.transfer(dataSent);
// Disable slave by setting SS to HIGH
digitalWrite(10, HIGH);
// Wait before retransmitting
delay(1000);
}
The following program sends byte 42 via the SPI wires.
If you want to read the values on the SPI of the Arduino board :
#include <SPI.h>
// Set the SS (Slave Select) pin
const int slaveSelectPin = 10;
void setup() {
// Initialize serial communication to display results
Serial.begin(9600);
// Set SS pin as output
pinMode(slaveSelectPin, OUTPUT);
// Initialize SPI communication
SPI.begin();
// Optional: Set SPI parameters
SPI.setClockDivider(SPI_CLOCK_DIV16); // Divide clock by 16 (1 MHz for a 16 MHz clock)
SPI.setDataMode(SPI_MODE0); // SPI mode 0
SPI.setBitOrder(MSBFIRST); // Bit order: MSB first
}
void loop() {
// Activate slave by setting SS to LOW
digitalWrite(slaveSelectPin, LOW);
// Send a read request to the SPI device
byte requestByte = 0x00; // Example of request (may vary depending on device)
byte receivedValue = SPI.transfer(requestByte);
// Disable slave by setting SS to HIGH
digitalWrite(slaveSelectPin, HIGH);
// Display received value in serial monitor
Serial.print("Value received: ”);
Serial.println(receivedValue);
// Wait before reading again
delay(1000);
}
If you’d like to know more about the communications buses available on Arduino, we’ve written courses on UART and I2C.
If you’d like to apply what you’ve seen in this course, you can read our course on RFID, which uses the SPI link to operate.