795  SPI: Serial Peripheral Interface Protocol

795.1 Learning Objectives

By the end of this section, you will be able to:

  • Understand SPI Architecture: Explain the four-wire structure with MOSI, MISO, SCK, and SS
  • Configure SPI Modes: Select appropriate clock polarity (CPOL) and phase (CPHA)
  • Wire SPI Devices: Connect multiple slaves using chip select lines
  • Compare Protocols: Choose between SPI, I2C, and UART for specific applications
  • Debug SPI Issues: Troubleshoot mode mismatch, chip select problems, and signal integrity
  • Write SPI Code: Program Arduino/ESP32 to communicate with SD cards and displays

795.2 Prerequisites

Before diving into this chapter, you should be familiar with:


795.3 SPI Overview

SPI (Serial Peripheral Interface) is a high-speed, full-duplex synchronous protocol developed by Motorola.

No official standard - implementations vary slightly between manufacturers.

795.3.1 Characteristics

Feature Value
Wires 4+ wires (SCLK, MOSI, MISO, + 1 SS per slave)
Topology Multi-point (star)
Sync/Async Synchronous (SCLK = clock)
Duplex Full-duplex (simultaneous send/receive)
Speed Up to 10+ Mbps (much faster than I2C)
Distance <1 meter (short cables, same PCB)
Devices Unlimited (limited by SS pins available)
Master/Slave Single master, multiple slaves
SPI signal diagram showing four lines: MOSI for master output slave input, MISO for master input slave output, SCK for clock signal, and SS/CS for slave select chip enable
Figure 795.1: SPI signal lines showing MOSI, MISO, SCK, and SS connections

795.4 SPI Signals

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22'}}}%%
graph TB
    M["Master"]
    S1["Slave 1"]
    S2["Slave 2"]

    M -->|"MOSI (Master Out)"| S1
    S1 -->|"MISO (Slave Out)"| M
    M -->|"SCK (Clock)"| S1
    M -->|"SS1 (Chip Select)"| S1

    M -->|"MOSI (Shared)"| S2
    S2 -->|"MISO (Shared)"| M
    M -->|"SCK (Shared)"| S2
    M -->|"SS2 (Dedicated)"| S2

    style M fill:#2C3E50,stroke:#16A085,color:#fff
    style S1 fill:#16A085,stroke:#16A085,color:#fff
    style S2 fill:#16A085,stroke:#16A085,color:#fff

Figure 795.2: SPI Bus Architecture with Multiple Slaves
SPI clock polarity CPOL and phase CPHA timing diagram showing four modes: mode 0 CPOL=0 CPHA=0, mode 1 CPOL=0 CPHA=1, mode 2 CPOL=1 CPHA=0, mode 3 CPOL=1 CPHA=1 with data sampling points
Figure 795.3: SPI clock mechanism and timing showing clock polarity and phase

Signal names (vary by manufacturer):

Function Alternative Names
SCLK SCK, CLK (Serial Clock)
MOSI SDI, DI, SI (Master Out Slave In)
MISO SDO, DO, SO (Master In Slave Out)
SS CS, CE (Slave Select / Chip Select)

SCLK (Serial Clock):

  • Clock signal from master
  • Slaves synchronize to this clock

MOSI (Master Out, Slave In):

  • Data from master to slave
  • Master writes, slaves read

MISO (Master In, Slave Out):

  • Data from slaves to master
  • Slaves write, master reads

SS (Slave Select):

  • Active LOW (usually)
  • Master pulls LOW to select specific slave
  • Separate SS line for each slave

795.5 SPI Modes

SPI has 4 modes based on clock polarity (CPOL) and phase (CPHA):

Mode CPOL CPHA Clock Idle Data Sampled
0 0 0 LOW Rising edge
1 0 1 LOW Falling edge
2 1 0 HIGH Falling edge
3 1 1 HIGH Rising edge

CPOL (Clock Polarity):

  • 0 = Clock idle state is LOW
  • 1 = Clock idle state is HIGH

CPHA (Clock Phase):

  • 0 = Data sampled on leading edge (first transition)
  • 1 = Data sampled on trailing edge (second transition)

Most common: Mode 0 and Mode 3

Important: Master and slave must use same mode!


795.6 SPI Data Transfer

Full-duplex simultaneous transfer:

     SS   ____                        ________
              \______________________/

   SCLK   ___   _   _   _   _   _   ___
             \_/ \_/ \_/ \_/ \_/ \_/

   MOSI   ====X===X===X===X===X===X=====
          (Master sends data to slave)

   MISO   ====X===X===X===X===X===X=====
          (Slave sends data to master)

          Bit: 7   6   5   4   3   2   1   0

Process:

  1. Master pulls SS LOW (select slave)
  2. Master generates clock pulses on SCLK
  3. On each clock pulse:
    • Master outputs bit on MOSI
    • Slave outputs bit on MISO
    • Both sides shift data simultaneously
  4. After 8 (or 16) bits, transaction complete
  5. Master pulls SS HIGH (deselect slave)

Data transmitted MSB first (most significant bit first) - can be configured.


795.7 Arduino/ESP32 SPI Example

#include <SPI.h>

// SS (Chip Select) pin
#define SS_PIN 5

void setup() {
  Serial.begin(115200);

  // Initialize SPI
  SPI.begin();

  // Configure SS pin
  pinMode(SS_PIN, OUTPUT);
  digitalWrite(SS_PIN, HIGH);  // Deselect

  Serial.println("SPI Initialized");
}

void loop() {
  // Select slave
  digitalWrite(SS_PIN, LOW);

  // Transfer data (sends 0xAA, receives slave's response)
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  byte response = SPI.transfer(0xAA);
  SPI.endTransaction();

  // Deselect slave
  digitalWrite(SS_PIN, HIGH);

  Serial.print("Sent: 0xAA, Received: 0x");
  Serial.println(response, HEX);

  delay(1000);
}

Wiring (ESP32 default SPI pins):

ESP32 GPIO 18 (SCLK) -> Slave SCLK
ESP32 GPIO 23 (MOSI) -> Slave MOSI
ESP32 GPIO 19 (MISO) -> Slave MISO
ESP32 GPIO 5  (SS)   -> Slave SS/CS
ESP32 GND            -> Slave GND

Common SPI devices:

  • SD card modules
  • TFT/OLED displays
  • NRF24L01 radio modules
  • ADXL345 accelerometer
  • MCP3008 ADC

TipPractical Tips

Choosing the Right SPI Mode:

  1. Check device datasheet - Look for CPOL/CPHA or explicit mode number
  2. Try Mode 0 first - Works with ~80% of SPI devices
  3. Try Mode 3 second - If Mode 0 fails (some displays, Ethernet)
  4. Modes 1 and 2 rare - Only specific industrial/legacy devices

Common Mode Assignments:

  • SD Cards: Mode 0 (CPOL=0, CPHA=0)
  • TFT Displays: Mode 0 or Mode 3
  • ADXL345: Mode 3 (CPOL=1, CPHA=1)
  • NRF24L01: Mode 0
  • W5500 Ethernet: Mode 0

Debugging Mode Issues:

  • Symptom: Garbled data, bits shifted
  • Solution: Try different modes (SPI_MODE0 through SPI_MODE3)
  • Test: Send known byte (0xAA = 10101010), verify response

795.8 Hands-On Lab: SD Card Reader

Objective: Read/write files to SD card via SPI.

#include <SPI.h>
#include <SD.h>

#define SD_CS 5  // Chip Select pin

void setup() {
  Serial.begin(115200);

  if (!SD.begin(SD_CS)) {
    Serial.println("SD card initialization failed!");
    return;
  }
  Serial.println("SD card initialized");

  // Write to file
  File file = SD.open("/test.txt", FILE_WRITE);
  if (file) {
    file.println("Hello from ESP32!");
    file.close();
    Serial.println("File written");
  }

  // Read from file
  file = SD.open("/test.txt");
  if (file) {
    Serial.println("\nFile contents:");
    while (file.available()) {
      Serial.write(file.read());
    }
    file.close();
  }
}

void loop() {}

795.9 Knowledge Check: SPI Signal Integrity

Scenario: Your data logger uses an SPI flash memory (Winbond W25Q128) rated for 133 MHz clock. Tests at 80 MHz work reliably (98% success rate), but at 133 MHz you see 40% corruption. A logic analyzer reveals clock signal overshoot (+5.8V on 3.3V logic) and ringing (+/-0.8V oscillations lasting 12 ns).

Think about:

  1. Why do PCB traces behave differently at 133 MHz vs 10 MHz?
  2. What physical phenomena cause the overshoot and ringing?

Key Insight: At high frequencies, transmission line effects dominate PCB design. A 10 cm trace at 133 MHz becomes an antenna:

  • Signal wavelength: lambda = c/f = (3x10^8 m/s) / (133x10^6 Hz) = 2.26 meters
  • Critical length: lambda/10 = 22.6 cm (your trace is 10 cm -> significant effects)
  • Fast edge time: ~2 ns (10%-90% rise) creates harmonics up to 500 MHz

Root causes:

  • Impedance mismatch: 50 ohm PCB trace -> 10 ohm chip pin creates reflection coefficient Gamma = (10-50)/(10+50) = -0.67 (67% negative reflection)
  • Reflected wave: Bounces back toward source, interfering with forward signal (ringing)
  • Overshoot: Reflected wave adds to forward wave (constructive interference)

Solutions:

  1. Series termination: 22-33 ohm resistor at source dampens reflections
  2. Shorter traces: Reduce to <5 cm (<lambda/40 at 133 MHz)
  3. Controlled impedance: Design 50 ohm traces (width/height ratio)
  4. Ground plane: Continuous plane under signal reduces loop inductance

Verify Your Understanding:

  • Why does this matter more at 133 MHz than 10 MHz? Because lambda/10 at 10 MHz = 3 meters (trace is insignificant). At 133 MHz, lambda/10 = 22 cm (trace is significant fraction).
  • Calculate required series resistor: Source impedance (5 ohm) + resistor (27 ohm) = 32 ohm approximately equal to 50 ohm trace impedance (minimizes reflections).

795.10 Protocol Comparison for IoT

795.10.1 When to Use Each Protocol

Protocol Best For Avoid When
RS-232 GPS modules, serial debugging, industrial legacy systems Multiple devices on same bus, high speed needed
I2C Multiple low-speed sensors (temp, humidity, pressure), displays, EEPROMs High-speed data transfer (video, audio), long cables
SPI High-speed sensors, SD cards, displays, radio modules Pin count is limited, long-distance communication

795.10.2 Detailed Comparison

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#2C3E50', 'primaryTextColor': '#fff', 'primaryBorderColor': '#16A085', 'lineColor': '#16A085', 'secondaryColor': '#E67E22'}}}%%
graph TD
    Start["Choose Protocol"]

    Start --> Q1{"How many<br/>devices?"}
    Q1 -->|"2 only"| UART["UART/RS-232<br/>2 wires<br/>115 kbps<br/>Point-to-point"]
    Q1 -->|"3+"| Q2{"Speed<br/>requirement?"}

    Q2 -->|"< 400 kbps"| I2C["I2C<br/>2 wires<br/>400 kbps<br/>Up to 112 devices<br/>Addressable"]
    Q2 -->|"> 1 Mbps"| SPI["SPI<br/>4+ wires<br/>10+ Mbps<br/>Full-duplex<br/>Fast"]

    style Start fill:#2C3E50,stroke:#16A085,color:#fff
    style Q1 fill:#7F8C8D,stroke:#16A085,color:#fff
    style Q2 fill:#7F8C8D,stroke:#16A085,color:#fff
    style UART fill:#E67E22,stroke:#16A085,color:#fff
    style I2C fill:#16A085,stroke:#16A085,color:#fff
    style SPI fill:#2C3E50,stroke:#16A085,color:#fff

Figure 795.4: Wired Protocol Selection Decision Flowchart

795.10.3 Practical Trade-offs

I2C Advantages:

  • Only 2 wires (minimal pins)
  • Easy to add devices (just connect to bus)
  • Addressable (up to 112 devices)
  • Bidirectional on same wire

I2C Disadvantages:

  • Slower than SPI
  • Pull-up resistors required
  • Address conflicts possible
  • Limited cable length

SPI Advantages:

  • Very fast (10+ Mbps)
  • Full-duplex (simultaneous send/receive)
  • Simple, no addressing
  • No pull-up resistors needed

SPI Disadvantages:

  • More wires (4+ pins)
  • Separate SS for each slave (pin intensive)
  • No multi-master capability
  • No flow control
TipProtocol Selection Guide

Choose UART when:

  • Point-to-point communication (2 devices)
  • Serial debugging or console needed
  • GPS module, Bluetooth HC-05/HC-06
  • Cable lengths up to 15 meters

Choose I2C when:

  • Multiple devices (2-112 on same bus)
  • Limited pins (only 2 wires available: SDA, SCL)
  • Low-to-medium speed OK (< 400 kHz)
  • Sensors, displays, EEPROMs, RTCs

Choose SPI when:

  • High speed required (1-10+ Mbps)
  • Enough pins available (4+ wires)
  • SD cards, TFT displays, fast sensors
  • Full-duplex needed (simultaneous TX/RX)

Real-World Examples:

  • Weather station: I2C (BME280, OLED display on same bus)
  • Data logger: SPI (SD card for fast writes)
  • GPS tracker: UART (GPS module + serial debug)
  • Robot: Mixed (I2C for sensors, SPI for displays, UART for debug)

795.11 Quiz: SPI and Protocol Comparison

Question 1: An SPI SD card interface uses 4 wires: MOSI, MISO, SCK, CS. You connect two SD cards by sharing MOSI/MISO/SCK but using separate CS lines (CS1, CS2). What happens if both CS1 and CS2 are LOW simultaneously while the master transmits?

Explanation: SPI has no collision detection or arbitration - it’s a full-duplex point-to-point protocol extended to multi-drop via CS. When multiple CS lines are LOW, multiple slaves drive MISO simultaneously. If they output different logic levels (one drives HIGH, other drives LOW), electrical conflict occurs potentially damaging the outputs. Even if they happen to output the same bits, it’s undefined behavior. Critical rule: Only ONE CS can be LOW at a time. Master must use GPIO pins to sequentially select devices: set CS1 LOW (talk to SD1), set CS1 HIGH, set CS2 LOW (talk to SD2). This sequential access is a key limitation vs I2C’s multi-drop addressing.

Question 2: A Modbus RTU network has 1 master and 15 slaves on RS-485. Each slave must respond within 50 ms to a master query. If each Modbus transaction (query + response) takes 15 ms at 19.2 kbps, what is the maximum update rate for all slaves?

Explanation: Modbus RTU master-slave polling: (1) Sequential polling: Modbus is half-duplex master-slave - master queries each slave sequentially (Slave 1, then Slave 2, etc.). Slaves don’t transmit unless queried. Can’t poll in parallel. (2) Cycle time calculation: Polling all 15 slaves requires 15 transactions: Cycle time = 15 slaves x 15 ms/transaction = 225 ms to query all devices once. (3) Update rate: 1000 ms / 225 ms/cycle = 4.44 Hz - each slave receives fresh data 4.44 times per second. (4) Comparison to requirement: 50 ms response timeout is per-transaction (master waits up to 50 ms for slave response), not cycle time. 15 ms actual transaction time is well within 50 ms timeout.

Question 3: Why do industrial networks use 24V DC instead of 5V TTL or 3.3V CMOS for I/O signaling, despite higher voltage requiring more expensive components?

Explanation: 24V industrial standard driven by noise immunity: (1) Voltage margins: TTL (5V): High = 2.0-5V, Low = 0-0.8V -> +/-0.8V noise margin (16%). If 1V noise spike occurs on 0V signal -> false HIGH. 24V logic: High = 15-30V, Low = 0-5V -> +/-5V noise margin (20%). 5V noise spike on 0V signal -> still LOW. Industrial plants have +/-10V transients from motor starters, VFDs, relay coils; 24V survives, 5V doesn’t. (2) Cable resistance: 100m CAT5e cable: 9 ohm resistance. 5V sensor with 100mA draw: voltage drop = 0.9V (18% of 5V, fails). 24V sensor: 0.9V drop -> 23.1V (4% drop, OK).

Question 4: An industrial plant has 200 sensors on a Modbus RS-485 network (1200m total cable length, 100 kbps). Intermittent communication errors occur. Troubleshooting reveals the bus has termination at one end only. What is the impact, and how should it be fixed?

Explanation: Transmission line theory applies to RS-485 at 100 kbps over 1200m: (1) Cable as transmission line: At 100 kbps, bit duration = 10 us. Signal propagation velocity in twisted pair ~200 m/us. Propagation delay for 1200m = 6 us (60% of bit duration). When signal arrives at cable end, reflections occur if impedance mismatched. (2) Unterminated end: Cable characteristic impedance Z0 = 120 ohm (RS-485 twisted pair). Unterminated end = open circuit (Z = infinity). Reflection coefficient Gamma = (Z - Z0) / (Z + Z0) ~ +1 (full reflection). Symptoms: Intermittent errors (CRC failures), worse at high baud rates. (3) Fix: Dual termination - add 120 ohm resistor at far end. Now both ends match Z0 = 120 ohm, signal absorbed (Gamma = 0), no reflections.

Question 5: A CAN Bus network in a factory connects 30 devices (sensors, actuators, PLCs) at 500 kbps over 80m. One faulty sensor continuously transmits error frames, corrupting the bus. What happens, and how does CAN Bus self-heal?

Explanation: CAN Bus fault confinement (self-healing mechanism): (1) Error detection: Every CAN message has CRC-15, stuff bits, ACK slot. When error detected, node transmits error frame. (2) Error counters: Each node maintains: Transmit Error Counter (TEC) and Receive Error Counter (REC). (3) Error states: Error-active (TEC/REC < 128): Normal operation. Error-passive (128-255): Can receive, but transmits recessive error frames. Bus-off (TEC >= 256): Node automatically disconnects from bus. (4) Faulty sensor scenario: Sensor TEC increments rapidly. After ~16 failed transmissions (128/8), enters error-passive. After 32 more failures (256/8), enters bus-off (disconnects). Bus self-heals: Other 29 devices continue operating normally. CAN has no bus master - it’s multi-master, peer-to-peer.


795.12 Summary

This chapter covered SPI (Serial Peripheral Interface) protocol and protocol comparison:

  • Four-wire interface (SCLK, MOSI, MISO, SS) enables high-speed full-duplex communication
  • SPI modes (0-3) define clock polarity and phase - must match between master and slave
  • Chip select (SS/CS) lines enable multi-slave configurations with separate select per device
  • Speed advantage: 10+ Mbps vs I2C’s 400 kbps, ideal for SD cards, displays, and fast sensors
  • Trade-off: More pins (4+ wires) vs I2C’s 2 wires, no multi-master, no addressing
  • Protocol selection: UART for point-to-point, I2C for multi-device low-speed, SPI for high-speed

795.13 What’s Next

Having mastered wired protocols, explore complementary topics:

  • Wireless Communication: Wi-Fi, Bluetooth, Zigbee, and LoRaWAN for cable-free IoT connectivity
  • Industrial Networking: Deep dive into Modbus RTU/TCP, CANopen, EtherCAT, and PROFINET
  • Network Protocols: TCP/IP, MQTT, CoAP, and HTTP for application-layer communication
  • Sensor Interfacing: Practical projects connecting temperature, humidity, accelerometer, and display modules
  • Protocol Analyzers: Using logic analyzers and bus sniffers to debug communication issues
  • Wired Communication Overview: Return to the overview page