Communication Protocols

Lesson 73: SPI Communication

Learn SPI fundamentals, signal lines, clock modes, and practical master-slave data transfer flow.

Progress indicator

Lesson 73 of 73

Learning Objectives

  • Understand SPI architecture and why it is fast for peripherals.
  • Know MOSI/MISO/SCK/SS line roles in real transfers.
  • Understand mode, clock, and bit-order settings clearly.
  • Read transaction flow from CS low to CS high safely.
  • Avoid common SPI wiring and configuration mistakes.

Concept Explanation

What is SPI

SPI (Serial Peripheral Interface) is a synchronous communication protocol between a controller (master) and peripherals (slaves).

It is commonly used when you need faster transfers than I2C and simple wiring logic.

SPI Communication Basics

Master controls timing with the SPI clock. Data is shifted bit-by-bit on each clock edge. SPI is usually full-duplex: sending and receiving happen together.

Master vs Slave Concept

  • Master starts transaction and sets clock.
  • Slave responds only when its CS/SS is active.
  • One master can control multiple slaves using separate CS pins.

SPI Signal Lines (MOSI, MISO, SCK, SS)

  • MOSI: Master sends data to slave.
  • MISO: Slave sends data back to master.
  • SCK: Master clock signal.
  • SS/CS: Slave-select line (active LOW in most cases).

SPI Data Transfer Process

  1. Master configures SPI transaction settings.
  2. Master pulls target CS LOW.
  3. Master clocks out bits on MOSI while reading bits on MISO.
  4. Master sets CS HIGH to end frame/command.

SPI Clock and Speed

Clock speed is set in SPISettings(clock, bitOrder, mode). Start at safe speed and increase gradually after communication is stable.

SPI Modes Explained

Modes combine clock polarity (CPOL) and phase (CPHA). Common names: SPI_MODE0 to SPI_MODE3. Master and slave mode must match.

When to Use SPI

  • Displays, flash memory, ADC/DAC chips, high-speed sensors.
  • When deterministic timing is important.
  • When short wires and higher data rate are acceptable design choices.

Example Code

This example runs one-byte SPI transfer with explicit transaction and CS control.

#include <SPI.h>

const int CS_PIN = 5;
byte txValue = 0x3A;

void setup() {
  Serial.begin(115200);
  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);

  SPI.begin(); // Initialize SPI bus pins and hardware
}

void loop() {
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));

  digitalWrite(CS_PIN, LOW);               // Select slave
  byte rxValue = SPI.transfer(txValue);    // Full-duplex transfer
  digitalWrite(CS_PIN, HIGH);              // Deselect slave

  SPI.endTransaction();

  Serial.print("TX=0x");
  Serial.print(txValue, HEX);
  Serial.print(", RX=0x");
  Serial.println(rxValue, HEX);

  delay(500);
}

Example Code Explanation

  1. SPI.begin() enables SPI peripheral and default pin mapping.
  2. SPI.beginTransaction(...) applies mode, speed, and bit order.
  3. CS LOW selects the slave before transfer.
  4. SPI.transfer(txValue) sends TX byte and receives RX byte simultaneously.
  5. CS HIGH finalizes current SPI frame.
  6. SPI.endTransaction() releases bus config context safely.
  7. Serial output confirms transmitted and received values.

What Happens Inside

  1. Master writes outgoing byte into SPI shift register.
  2. Clock pulses move bits out/in one edge at a time.
  3. Slave shift register responds with return bits over MISO.
  4. Master assembles received bits into final RX byte.
  5. CS deactivation ends command frame for selected slave.

Common Mistakes with SPI

  • Wrong SPI mode (CPOL/CPHA mismatch) causing garbage data.
  • CS not handled correctly (left LOW too long or toggled incorrectly).
  • Clock too fast for slave or wiring quality.
  • MOSI/MISO swapped in wiring.

Best Practices for SPI

  • Always use transaction APIs for shared SPI bus safety.
  • Set each slave CS HIGH by default; activate one slave at a time.
  • Start slow clock (e.g., 1 MHz), then tune upward after validation.
  • Use Serial logging and logic analyzer when debugging unstable transfers.

Try it now

Open the simulator workspace and step through SPI transaction and chip-select flow.

Run in Simulator