Back
Loading views...SPI
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
- W25Q128 SPI Flash: Read/write firmware storage
- ST7735 LCD: Send pixel data and commands
- MPU-9250 IMU: Read 6-axis motion data at high rate
- MCP3204 ADC: Sample analog signals at 12-bit precision
- 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
- What do CPOL and CPHA mean?
- How many wires does standard SPI use?
- Is SPI full-duplex or half-duplex?
- How do you select a specific slave in a multi-slave SPI system?
- What is the purpose of the dummy byte in SPI reads?
Intermediate
- How would you drive 5 SPI slaves from one MCU?
- Explain the difference between SPI Mode 0 and Mode 3.
- How does QSPI achieve 4x the bandwidth of standard SPI?
- Write an SPI driver that handles both 8-bit and 16-bit transfers.
- What PCB design rules should you follow for 40 MHz SPI?
Advanced
- Implement a complete W25Q128 flash driver with sector erase, page write, and read.
- How would you use DMA to stream audio to an SPI DAC continuously?
- Describe how to implement a SPI bootloader.
- What causes SPI data corruption at high speeds, and how do you fix it?
- How would you implement daisy-chained SPI for 8x LED drivers?
Hands-on Projects
- SPI Flash Logger: Read/write structured data records to W25Q128.
- Graphical LCD Driver: Drive an ST7735 display with DMA SPI at full framerate.
- 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