Protocols
SPI — Serial Peripheral Interface
A synchronous, full-duplex, master-driven bus used for short-range, high-speed communication between a microcontroller and peripherals like sensors, flash memory, displays, and ADCs.
- What it is
- A synchronous serial bus where the controller drives the clock and every clock tick shifts one bit out and one bit in, simultaneously.
- Mental model
- A shift register shared between two chips — data moves in both directions on the same clock edge, and wiring (not addressing) picks the device.
- Key numbers
- 4 wires (SCLK, MOSI, MISO, one CS per device), up to tens of MHz, 4 clock modes (0–3).
- Reach for it when
- You need high throughput to a nearby chip and can spare one GPIO pin per device for chip select.
Wires and roles
A standard SPI bus uses four signals, driven by one master (in classic terminology: master/slave; modern datasheets increasingly say controller/peripheral):
- SCLK
- Serial clock — always driven by the controller. Peripherals never generate their own clock.
- MOSI
- Controller Out, Peripheral In (also seen as SDO/SDI on newer datasheets).
- MISO
- Controller In, Peripheral Out.
- CS / SS
- Chip Select — active-low, one line per peripheral, selects which device is listening.
Because clock and chip-select are separate from the data lines, SPI has no addressing scheme on the wire — the wiring itself (which CS line is asserted) determines who you're talking to. That's the key structural difference from I2C, which addresses peripherals in-band over a shared two-wire bus.
Clock polarity and phase (modes)
SPI has four modes, defined by two independent bits: CPOL (clock idle polarity) and CPHA (which clock edge data is sampled on). Getting this wrong is the single most common reason a "correctly wired" SPI device produces garbage.
| Mode | CPOL | CPHA | Clock idle | Data sampled on |
|---|---|---|---|---|
| 0 | 0 | 0 | Low | Rising edge (leading) |
| 1 | 0 | 1 | Low | Falling edge (trailing) |
| 2 | 1 | 0 | High | Falling edge (leading) |
| 3 | 1 | 1 | High | Rising edge (trailing) |
Mode 0 is by far the most common default; check the peripheral's datasheet timing diagram rather than assuming.
How a transfer works
SPI is full-duplex and has no formal "packet" concept — every clock pulse shifts one bit out on MOSI and one bit in on MISO, simultaneously, for as long as CS stays asserted. This means:
- To read N bytes from a peripheral, the controller typically has to clock out N dummy bytes.
- Command framing (register address, read/write bit, byte count) is entirely a software convention defined by each chip's datasheet — SPI itself doesn't define it.
- Deasserting CS usually marks the end of a logical transaction (e.g. flash chips reset their internal address counter on CS high).
Chip select strategies
Because SPI addressing is physical rather than in-band, adding peripherals costs GPIO pins — see GPIO for how those pins are configured as outputs. Two common approaches when you have many peripherals:
- One CS per device — simplest, but doesn't scale past the number of spare pins.
- Daisy-chained (SPI chain) — supported by some devices (e.g. shift registers, some ADCs); shares one CS but requires clocking through the whole chain.
SPI vs. I2C vs. UART
| SPI | I2C | UART | |
|---|---|---|---|
| Wires | 4+ (SCLK, MOSI, MISO, 1×CS per device) | 2 (SDA, SCL) | 2 (TX, RX) |
| Duplex | Full | Half | Full |
| Addressing | Physical (CS line) | In-band (7/10-bit address) | Point-to-point, none needed |
| Typical speed | Up to tens of MHz | 100 kHz–3.4 MHz | Up to ~few Mbps |
| Clock | Shared, controller-driven | Shared, controller-driven | None — both sides agree on baud rate |
See I2C and UART for the full picture.
- Pros
- The fastest of the three at a given clock rate, genuinely full-duplex, and framing is a simple software convention rather than a protocol with fixed overhead — nothing stops a transfer but the wire itself.
- Cons
- Pin count grows with every device (one CS each), unlike I2C's fixed two wires; no built-in addressing, error checking, or acknowledgment — all of that is on you to implement in software if you need it at all; and it's not naturally a multi-controller bus the way CAN is.
- Reach for SPI when
- You need real throughput to a nearby chip — flash memory, a display, a fast ADC — and can spare one GPIO pin per device for chip select.
- Reach for something else when
- Pin budget matters more than speed and you have several low-speed devices — I2C's shared two wires scale better as device count grows. Need several independent nodes sharing a bus over real distance with guaranteed priority, not just several peripherals near one controller? That's CAN.
Variants: 3-wire, dual, and quad SPI
"SPI" in a datasheet doesn't always mean the classic 4-wire form:
- 3-wire SPI
- MOSI and MISO are combined onto a single bidirectional data line (direction switched by the transfer's read/write phase) — trades full-duplex for one fewer pin, common on small sensors where pin count matters more than throughput.
- Dual SPI
- Uses two data lines in parallel during the data phase (command and address are still sent on one line), roughly doubling data-phase throughput — mainly seen on flash memory read commands.
- Quad SPI (QSPI)
- Four data lines in parallel during the data phase — a common way to get much higher effective throughput out of external flash without raising the clock frequency itself (and the EMI/signal-integrity problems that come with it).
These aren't different protocols so much as different physical framings of the same controller/peripheral relationship — the controller and peripheral both have to agree on which variant is in use, usually configured via a specific command sequence the flash chip's datasheet defines.
Clock speed and signal integrity
SPI has no defined maximum clock rate in the specification — the limit in practice is whatever the specific controller, peripheral, and physical wiring can tolerate. A few things that actually set that ceiling:
- Peripheral's maximum SCLK — stated directly in its datasheet; exceeding it produces exactly the kind of "works most of the time, glitches occasionally" failure that's miserable to debug.
- Trace/wire length — longer runs at high clock rates start to behave like transmission lines rather than simple wires; unterminated reflections corrupt data well before the signal looks obviously "bad" on a low-bandwidth probe.
- Rise/fall time vs. clock period — if edges take a meaningful fraction of a clock period to settle, the receiving side can sample before the line has actually reached a valid logic level.
The practical debugging move when a fast SPI link is unreliable: lower the clock rate first and confirm the logic is correct, then raise it back up while watching for where it actually breaks — that tells you whether it's a protocol bug or a signal-integrity one.
Real-world applications
- SD/microSD cards — every SD card supports an SPI fallback mode, which is how most microcontrollers without a dedicated SDIO peripheral read and write them.
- SPI NOR flash — the firmware/bootloader storage chip (e.g. W25Qxx family) on most microcontroller boards is read over SPI, often in quad mode for speed.
- TFT/OLED displays — small display controllers like the ILI9341 or SSD1306 are driven almost exclusively over SPI for the pixel-data throughput.
- ADCs and DACs — precision converter chips (e.g. the MCP3xxx family) commonly expose SPI as their only digital interface.
- Inter-board links — short board-to-board connections (a sensor daughterboard, a radio module like the nRF24L01) frequently use SPI simply because it needs no negotiation — power it up and start clocking.
Gotchas
- Mismatched SPI mode is the #1 cause of "garbage on the first byte then it works" symptoms.
- MISO should usually be tri-stated by deselected peripherals — if it isn't, bus contention corrupts reads from other devices.
- Long wires + fast SCLK = ringing. Slow the clock down before assuming the chip is dead.
- On Linux,
spidevlets you drive SPI from userspace without writing a kernel driver — see Linux → Drivers.