Common Bus Protocols#

Three serial protocols dominate low-to-medium-speed digital communication between ICs on a PCB: SPI, I2C, and UART. Each makes different tradeoffs between pin count, speed, complexity, and flexibility. This page covers the hardware and timing aspects — the electrical signals, the clocking, and the timing diagrams — not the software drivers or register-level programming.

SPI (Serial Peripheral Interface)#

A synchronous, full-duplex, master-slave serial bus. Developed by Motorola in the 1980s, SPI is the standard for high-speed communication between a controller and peripherals (ADCs, DACs, flash memory, displays, sensors).

Signals:

  • SCLK — Serial clock, generated by the master
  • MOSI — Master Out, Slave In (data from master to slave)
  • MISO — Master In, Slave Out (data from slave to master)
  • CS (or SS) — Chip Select, active LOW, one per slave

Operation:

  1. Master asserts CS (LOW) to select the target slave
  2. Master generates SCLK and shifts data out on MOSI
  3. Simultaneously, the selected slave shifts data out on MISO
  4. After the transfer, master deasserts CS (HIGH)

SPI is fundamentally a pair of shift registers connected in a ring — the master’s shift register and the slave’s shift register exchange data bit-by-bit on each clock edge.

Clock modes (CPOL and CPHA):

  • CPOL — Clock polarity. 0 = idle LOW, 1 = idle HIGH
  • CPHA — Clock phase. 0 = data sampled on leading edge, 1 = data sampled on trailing edge
  • Four combinations (Mode 0-3) define when data is valid relative to the clock. Both master and slave must agree on the mode

Timing considerations:

  • Clock frequency: typically 1-50 MHz, some devices support 100+ MHz
  • No protocol-level overhead — every clock cycle transfers one bit in each direction. Throughput equals clock frequency (for single-bit mode)
  • Setup and hold timing on MOSI/MISO relative to SCLK must be met. At high frequencies, the propagation delay from master SCLK output to slave SCLK input (and back for MISO) limits the maximum frequency
  • No acknowledgment mechanism — the master has no way to know if the slave received the data correctly (unless the protocol layer adds one)

Multi-slave topologies:

  • Independent CS lines — Most common. Each slave has its own CS. Only one is selected at a time. Pin count grows with slave count
  • Daisy chain — MISO of one slave connects to MOSI of the next. Data shifts through all slaves in series. Requires all slaves to support daisy-chaining

Hardware features:

  • Quad SPI (QSPI) uses 4 data lines instead of 1, quadrupling throughput. Common for flash memory
  • Dual SPI uses 2 data lines. Both are extensions of the basic SPI concept, trading pin count for speed

I2C (Inter-Integrated Circuit)#

A synchronous, half-duplex, multi-master serial bus. Developed by Philips (now NXP). I2C uses just two wires for communication, making it ideal for connecting many low-speed peripherals (sensors, EEPROMs, RTCs, I/O expanders) with minimal pin count.

Signals:

  • SCL — Serial clock
  • SDA — Serial data

Both lines are open-drain with external pull-up resistors. Any device can pull the line LOW; the pull-up pulls it HIGH when released. This wired-AND topology enables multi-master capability and clock stretching.

Operation:

  1. Master generates a START condition (SDA goes LOW while SCL is HIGH)
  2. Master sends a 7-bit slave address plus a read/write bit
  3. The addressed slave responds with an ACK (pulls SDA LOW during the 9th clock cycle)
  4. Data bytes transfer, each followed by ACK/NACK
  5. Master generates a STOP condition (SDA goes HIGH while SCL is HIGH)

Addressing:

  • 7-bit addressing: up to 128 devices (minus reserved addresses), giving about 112 usable addresses
  • 10-bit addressing: for systems needing more addresses (rarely used)
  • Each device has a fixed or partially configurable address. Address conflicts are a common integration problem — two sensors from different manufacturers with the same address cannot share a bus without an I2C multiplexer

Speed modes:

  • Standard mode: 100 kHz
  • Fast mode: 400 kHz
  • Fast mode plus: 1 MHz
  • High-speed mode: 3.4 MHz

Timing considerations:

  • Rise time depends on pull-up resistor value and bus capacitance. The I2C specification limits bus capacitance to 400 pF (standard mode). More capacitance requires stronger pull-ups (lower resistance) but increases power consumption
  • Pull-up resistor sizing: too large = slow rise time (may violate timing), too small = excessive LOW-state current and inability of weak devices to pull the bus LOW
  • Clock stretching: a slave can hold SCL LOW to pause the master while it processes data. The master must detect this and wait. Not all masters support clock stretching properly

Electrical characteristics:

  • Open-drain signaling means signal integrity is generally good — no bus contention, no drive fights
  • But the asymmetric rise/fall (slow rise, fast fall) limits speed. At higher I2C speeds, the pull-up resistor value becomes critical
  • Level shifting is natural: a MOSFET-based level shifter works bidirectionally on open-drain lines

UART (Universal Asynchronous Receiver-Transmitter)#

An asynchronous, full-duplex, point-to-point serial interface. No clock line — both sides must agree on the baud rate in advance.

Signals:

  • TX — Transmit data (output)
  • RX — Receive data (input)
  • Optional: RTS/CTS (flow control), DTR/DSR (modem control)

Frame format:

  • 1 start bit (LOW)
  • 5-9 data bits (usually 8)
  • Optional parity bit (even, odd, or none)
  • 1-2 stop bits (HIGH)

The most common configuration: 8N1 (8 data bits, no parity, 1 stop bit) = 10 bit-times per byte.

Operation:

  1. The line idles HIGH
  2. The transmitter pulls the line LOW for one bit-time (start bit)
  3. Data bits follow, LSB first, each held for one bit-time
  4. Optional parity bit
  5. Stop bit(s) — line returns HIGH for 1-2 bit-times
  6. Line idles HIGH until the next byte

Baud rate and timing:

  • Common baud rates: 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
  • The receiver uses the start bit’s falling edge to synchronize, then samples each subsequent bit at the center of the bit-time
  • Both transmitter and receiver must agree on the baud rate to within about ±2-3%. If the clocks drift further apart, the receiver samples at the wrong time and data is corrupted
  • At 115200 baud: one bit is ~8.7 us, one byte is ~87 us, maximum throughput is ~11.5 KB/s

Voltage levels:

  • UART is a protocol, not a voltage standard. The electrical interface varies:
    • TTL/CMOS UART — 0 V / 3.3 V or 0 V / 5 V. Directly from the microcontroller or FPGA
    • RS-232 — ±3 to ±15 V (typically ±12 V). Inverted logic (positive = logic 0). Needs a level shifter (MAX232 or similar) to connect to CMOS logic
    • RS-422 / RS-485 — Differential signaling for noise immunity and long distances. RS-485 supports multi-drop (multiple devices on one pair)

Flow control:

  • None — The transmitter sends at will. The receiver must keep up. Data is lost if the receiver’s buffer overflows
  • Hardware (RTS/CTS) — The receiver deasserts CTS when its buffer is nearly full, signaling the transmitter to pause. Reliable but requires extra wires
  • Software (XON/XOFF) — Special characters in the data stream signal pause and resume. No extra wires, but the control characters cannot appear in the data (problematic for binary data)

Comparing the Three#

FeatureSPII2CUART
Wires4+ (SCLK, MOSI, MISO, CS per slave)2 (SCL, SDA)2 (TX, RX)
ClockingSynchronous (master provides clock)Synchronous (master provides clock)Asynchronous (baud rate agreement)
DuplexFullHalfFull
Speed1-100+ MHz100 kHz - 3.4 MHz9600 baud - 1+ Mbaud
Multi-deviceOne CS per slaveAddressing (112+ devices on 2 wires)Point-to-point
OverheadNone (raw bits)Address + ACK per transferStart/stop bits per byte
ComplexityLowMediumLow

Tips#

  • Always verify SPI clock mode (CPOL/CPHA) against the specific device datasheet — there is no universal default
  • Size I2C pull-up resistors based on bus capacitance and speed mode — calculate or use NXP’s guidelines
  • Verify UART baud rates on both ends before debugging protocol issues — rate mismatch is the most common problem
  • Plan for I2C address conflicts during system integration — check all device addresses before committing to a bus topology

Caveats#

  • SPI has no standard — Unlike I2C (which has a detailed specification from NXP), SPI was never formally standardized. Different manufacturers implement variations: different word sizes, different CS behavior, different byte ordering. Always check the specific device’s datasheet
  • I2C pull-up resistors are not optional — Without pull-ups, the bus stays at whatever voltage the parasitic capacitance holds. The signals will be sluggish, unreliable, or completely nonfunctional. Size the pull-ups for the bus capacitance and speed mode
  • UART baud rate mismatch produces garbage — If the transmitter and receiver are at different baud rates, the received data is corrupted. There is no handshake or negotiation — both sides must be configured correctly before communication begins
  • I2C address conflicts are a system integration problem — Two devices with the same address on the same bus cannot coexist. Solutions include I2C multiplexers (TCA9548A), alternate addresses (some devices have address pins), or separate buses
  • Long SPI traces at high speed need signal integrity attention — At 50 MHz, a 10 cm SPI trace is a significant fraction of a wavelength. Impedance matching and termination may be needed
  • RS-232 voltage levels will damage CMOS inputs — Connecting an RS-232 signal (±12 V) directly to a 3.3 V CMOS UART input will destroy the chip. Always use a level translator (MAX3232 or equivalent)

In Practice#

  • I2C signals with slow rise times and rounded edges indicate pull-up resistors are too large for the bus capacitance
  • SPI data that appears shifted or inverted suggests clock polarity or phase mismatch — verify CPOL/CPHA settings
  • UART output that displays as gibberish on a terminal almost always indicates baud rate mismatch
  • I2C transactions that NAK unexpectedly may be caused by address conflicts or missing pull-ups