SPI - Four Wires, One Master, and the Clock That Changes Everything
SPI adds a clock wire to the serial equation and gets dramatically faster as a result. Here's how MOSI, MISO, SCK and CS work together, why clock modes matter, and how to connect multiple devices.
SPI. Four Wires, One Master, and the Clock That Changes Everything
The fundamental problem with UART is that it's asynchronous. Both ends have to independently count time at the same rate and hope they stay in sync. It works, but it sets a ceiling on how fast you can go and how reliably you can do it.
SPI solves this completely. The master provides a clock wire. The slave never has to measure time. it just watches the clock and captures a bit on each edge. This is why SPI running at 40MHz is routine, while UART at 4MHz is pushing it.
The four wires
| Signal | Direction | Role |
|---|---|---|
| SCK | Master β Slave | Clock |
| MOSI | Master β Slave | Data to slave |
| MISO | Slave β Master | Data from slave |
| CS | Master β Slave | Chip select, active LOW |
Rendering diagram...
SCK and MOSI are shared between all slaves. the master broadcasts the clock and data to everyone. But only the one device with its CS pin pulled LOW actually responds. MISO lines do cause a conflict, though: if two slaves are both driving MISO simultaneously, you get bus contention and corrupted data. The CS line prevents this. When a slave's CS is HIGH, its MISO output goes high-impedance.
SPI is full-duplex. Every clock cycle, one bit goes from master to slave (MOSI) and simultaneously one bit comes back (MISO). For read-only operations, the master sends dummy bytes just to generate the clocks. For write-only operations, MISO carries junk you can ignore.
Clock modes. the thing that burns everyone at least once
SPI has two parameters: CPOL (clock idle state) and CPHA (which edge to sample on). This gives four modes:
Mode | CPOL | CPHA | Clock idle | Sample on
-----|------|------|------------|----------
0 | 0 | 0 | LOW | rising edge β most common
1 | 0 | 1 | LOW | falling edge
2 | 1 | 0 | HIGH | falling edge
3 | 1 | 1 | HIGH | rising edge
Mode 0 works for the majority of chips. display drivers, ADCs, flash memory, most sensors. But some chips, particularly certain accelerometers and DACs, require Mode 3. Using the wrong mode means every byte you receive is valid-looking garbage: the bits are all there, just shifted by one edge.
Mode 0: SCK idle LOW, sample on rising edge
SCK β_β_β_β_β_β_β_β_β
β β β β β β β β β sample here
MOSI β[7][6][5][4][3][2][1][0]β
CS LOW βββββββββββββββββββ HIGH
Check the datasheet. It's usually one line in the electrical characteristics table: "SPI Mode 0/3" or "CPOL=0, CPHA=0". If the datasheet is ambiguous, a logic analyser will tell you immediately what mode the device actually uses.
Daisy-chaining. the alternative to multiple CS pins
The usual approach for multiple slaves is one CS pin per device. Simple and direct, but costs a GPIO for every new device.
The alternative is daisy-chaining: MISO of slave 1 connects to MOSI of slave 2, and so on. All devices share one CS. On each clock cycle, each device shifts its register one position. like a long shift register. Popular with LED drivers and some ADC arrays.
Rendering diagram...
Daisy-chain is a pain to debug. if any device in the chain misbehaves, the whole thing breaks. Use independent CS when you can afford the pins.
Practical speed limits
SPI speed is ultimately constrained by three things: the MCU's peripheral limit, the slave's rated SPI clock, and the PCB trace length. For traces under 10cm, 20-40MHz is usually fine. Beyond 15cm, add a small series resistor (22-33Ξ©) at the master output to damp reflections, and drop the clock to whatever the signal still looks clean at on a scope.
SD cards are notoriously finicky above 25MHz in SPI mode. High-speed flash chips are fine at 80MHz. Check the slave's maximum SCK spec before you push the clock up, and if you see occasional CRC failures. especially when the board gets warm. clock speed is where I'd look first.