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.

Quick reference
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.

SPI modes
ModeCPOLCPHAClock idleData sampled on
000LowRising edge (leading)
101LowFalling edge (trailing)
210HighFalling edge (leading)
311HighRising 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:

SPI mode 0 timing: CS frames the transaction while SCLK, MOSI and MISO all run inside it, sampled on the rising edge CS SCLK MOSI MISO
CS (amber) frames the whole transaction; SCLK (blue) is controller-driven throughout; MOSI (teal) and MISO (violet) both shift one bit per clock edge, simultaneously — mode 0 shown, sampled on the rising edge.

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:

SPI vs. I2C vs. UART

SPII2CUART
Wires4+ (SCLK, MOSI, MISO, 1×CS per device)2 (SDA, SCL)2 (TX, RX)
DuplexFullHalfFull
AddressingPhysical (CS line)In-band (7/10-bit address)Point-to-point, none needed
Typical speedUp to tens of MHz100 kHz–3.4 MHzUp to ~few Mbps
ClockShared, controller-drivenShared, controller-drivenNone — both sides agree on baud rate

See I2C and UART for the full picture.

Why SPI, and when
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:

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

Gotchas

Field notes

→ Code examples for SPI