Back

SPI

Loading views...

SPI Protocol

Overview

SPI (Serial Peripheral Interface) is a synchronous serial communication protocol developed by Motorola. It uses a master-slave architecture with four wires: clock (SCK), master-out-slave-in (MOSI), master-in-slave-out (MISO), and chip select (CS). It is widely used for high-speed peripherals like flash memory, ADCs, DACs, and display drivers.


1. Theory & Fundamentals

  • Problem solved: Fast, full-duplex synchronous communication between a master and one or more peripherals
  • Physical layer: Single-ended TTL/CMOS, typically 3.3V or 5V
  • Wires: SCK (clock), MOSI, MISO, CS/SS (one per slave)
  • Speed: Up to 80 MHz+ (device-dependent)
  • Full-duplex: Data transmitted and received simultaneously
  • Clock polarity (CPOL): Idle state of clock — 0=LOW, 1=HIGH
  • Clock phase (CPHA): Data sampled on 1st or 2nd clock edge

2. Frame / Packet Structure

CS:   HIGH ───┐                              ┌─── HIGH
              └──────────────────────────────┘
SCK:  (depends on CPOL/CPHA mode)
MOSI: ───── D7 ── D6 ── D5 ── D4 ── D3 ── D2 ── D1 ── D0 ─────
MISO: ───── D7 ── D6 ── D5 ── D4 ── D3 ── D2 ── D1 ── D0 ─────

SPI Modes:

Mode CPOL CPHA Clock Idle Sample Edge
0 0 0 LOW Rising
1 0 1 LOW Falling
2 1 0 HIGH Falling
3 1 1 HIGH Rising

3. Protocol Mechanics

  • Synchronization: Clock provided by master — fully synchronous
  • Data valid: Captured on specific clock edge (CPHA-dependent)
  • No ACK: No built-in acknowledgment mechanism
  • CS active: Typically active LOW; one CS line per slave
  • Daisy-chain: MISO of one slave connects to MOSI of next (rare use)
  • Error detection: None built-in; higher-layer CRC needed

4. Hardware Implementation

  • MCU pins: Dedicated SPI peripheral (MOSI, MISO, SCK, NSS/CS)
  • Multiple slaves: One GPIO per slave for CS control
  • Level shifter: Use TXS0108 or similar for mixed-voltage systems
  • PCB rules: Match trace lengths for high-speed SPI, use ground plane, decouple VCC close to ICs
  • Pull-up on CS: 10kΩ pull-up ensures slave deselected at power-up
  • Common SPI ICs: W25Q128 (flash), MCP3204 (ADC), DAC8552 (DAC), ST7735 (display)

5. Register-Level Programming (STM32)

// Enable SPI1 and GPIO clocks
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN | RCC_APB2ENR_IOPAEN;

// Configure SPI1: Master, SPI Mode 0, 8-bit, MSB first
SPI1->CR1 = SPI_CR1_MSTR      // Master mode
           | SPI_CR1_SSM       // Software slave management
           | SPI_CR1_SSI       // Internal slave select
           | (0x3 << 3)        // Baud = fPCLK/16
           | SPI_CR1_SPE;      // Enable SPI

uint8_t SPI_Transfer(uint8_t data) {
    while (!(SPI1->SR & SPI_SR_TXE));  // Wait TX empty
    SPI1->DR = data;
    while (!(SPI1->SR & SPI_SR_RXNE)); // Wait RX not empty
    return SPI1->DR;
}

6. Driver Development

void SPI_CS_Low(void)  { GPIOA->BSRR = GPIO_BSRR_BR4; }
void SPI_CS_High(void) { GPIOA->BSRR = GPIO_BSRR_BS4; }

void SPI_WriteReg(uint8_t reg, uint8_t val) {
    SPI_CS_Low();
    SPI_Transfer(reg & 0x7F);  // Write bit
    SPI_Transfer(val);
    SPI_CS_High();
}

uint8_t SPI_ReadReg(uint8_t reg) {
    uint8_t val;
    SPI_CS_Low();
    SPI_Transfer(reg | 0x80);  // Read bit
    val = SPI_Transfer(0xFF);  // Dummy byte
    SPI_CS_High();
    return val;
}

7. Debugging & Testing

  • Logic analyzer: Decode SPI with correct CPOL/CPHA mode
  • Common issues:

- Wrong SPI mode → shifted/garbled data

- CS not asserted → slave ignores transaction

- Speed too high → signal degradation

- Floating MISO when CS is high → use pull-up or tristate

  • Loopback test: Connect MOSI to MISO, verify sent = received

8. Real-World Applications

  1. W25Q128 SPI Flash: Read/write firmware storage
  2. ST7735 LCD: Send pixel data and commands
  3. MPU-9250 IMU: Read 6-axis motion data at high rate
  4. MCP3204 ADC: Sample analog signals at 12-bit precision
  5. SD card (SPI mode): FAT filesystem on embedded systems

9. Advanced Topics & Edge Cases

  • QSPI / Dual SPI: 2 or 4 data lines for higher throughput
  • DMA SPI: Zero-CPU bulk transfers to/from flash or display
  • SPI over long cables: Use lower speed, add series resistors
  • Simultaneous slaves: One transaction can address multiple devices with shared SCK/MOSI
  • Bidirectional 3-wire SPI: MOSI/MISO shared on one line (half-duplex)

10. Standards & Variants

Variant Lines Speed Use case
Standard SPI 4 Up to 80MHz General purpose
Dual SPI 3+1 2x faster Flash read
Quad SPI (QSPI) 6 4x faster Fast NOR flash
3-wire SPI 3 Same Display drivers

💡 Practical Examples

Example 1: Read ID from SPI Flash (W25Q128)

SPI_CS_Low();
SPI_Transfer(0x9F); // Read JEDEC ID command
uint8_t mfr = SPI_Transfer(0xFF);
uint8_t type = SPI_Transfer(0xFF);
uint8_t cap = SPI_Transfer(0xFF);
SPI_CS_High();
// mfr=0xEF, type=0x40, cap=0x18 for W25Q128

Example 2: Write to SPI DAC (MCP4921)

void DAC_Write(uint16_t value) {
    uint16_t cmd = 0x3000 | (value & 0x0FFF); // Config bits + 12-bit value
    SPI_CS_Low();
    SPI_Transfer((cmd >> 8) & 0xFF);
    SPI_Transfer(cmd & 0xFF);
    SPI_CS_High();
}

Example 3: DMA SPI TX to display

void LCD_DMA_Send(uint8_t *buf, uint16_t len) {
    DMA1_Channel3->CMAR = (uint32_t)buf;
    DMA1_Channel3->CNDTR = len;
    DMA1_Channel3->CCR |= DMA_CCR_EN;
    SPI1->CR2 |= SPI_CR2_TXDMAEN;
}

🧪 Practice Questions

Beginner

  1. What do CPOL and CPHA mean?
  2. How many wires does standard SPI use?
  3. Is SPI full-duplex or half-duplex?
  4. How do you select a specific slave in a multi-slave SPI system?
  5. What is the purpose of the dummy byte in SPI reads?

Intermediate

  1. How would you drive 5 SPI slaves from one MCU?
  2. Explain the difference between SPI Mode 0 and Mode 3.
  3. How does QSPI achieve 4x the bandwidth of standard SPI?
  4. Write an SPI driver that handles both 8-bit and 16-bit transfers.
  5. What PCB design rules should you follow for 40 MHz SPI?

Advanced

  1. Implement a complete W25Q128 flash driver with sector erase, page write, and read.
  2. How would you use DMA to stream audio to an SPI DAC continuously?
  3. Describe how to implement a SPI bootloader.
  4. What causes SPI data corruption at high speeds, and how do you fix it?
  5. How would you implement daisy-chained SPI for 8x LED drivers?

Hands-on Projects

  1. SPI Flash Logger: Read/write structured data records to W25Q128.
  2. Graphical LCD Driver: Drive an ST7735 display with DMA SPI at full framerate.
  3. SPI ADC Scope: Sample at 1 MSPS with MCP3204 and stream over USB.

Checklist

  • [ ] Explain all 4 SPI modes with timing diagrams
  • [ ] Write bare-metal SPI init and transfer functions
  • [ ] Use CS GPIO correctly for multi-slave systems
  • [ ] Interface with SPI flash, ADC, and display
  • [ ] Implement DMA-based SPI transfer
  • [ ] Debug with logic analyzer using correct SPI mode
  • [ ] Design PCB layout for high-speed SPI
  • [ ] Use QSPI peripheral for NOR flash
  • [ ] Handle SPI errors and timeouts gracefully
  • [ ] Write a complete SPI peripheral driver library