UART — Universal Asynchronous Receiver/Transmitter

TX line
Start bit
Data bits
Parity bit
Stop bit

How UART Works

UART is an asynchronous serial protocol — no shared clock. Both sides agree on a baud rate in advance. An idle line is held HIGH (logic 1). Each frame begins with a start bit (LOW), followed by 7–9 data bits (LSB first), optional parity bit, and one or two stop bits (HIGH).


Bit period = 1 / baud_rate
 
Frame time = (1 + data_bits + parity + stop) × bit_period

Parity: Even parity — total number of 1 bits (including parity) is even. Odd parity — total is odd. Detects single-bit errors only.

SPI — Serial Peripheral Interface

CS (chip select)
SCK (clock)
MOSI (master→slave)
MISO (slave→master)

How SPI Works

SPI is a synchronous, full-duplex protocol using 4 lines: SCK (clock), MOSI (master out), MISO (master in), CS/SS (chip select, active LOW). Data is sampled on one clock edge and shifted on the other — determined by the mode (CPOL/CPHA).


CPOL=0: clock idles LOW   CPOL=1: clock idles HIGH

CPHA=0: sample on leading edge   CPHA=1: sample on trailing edge

SPI is faster than I²C and UART (up to hundreds of MHz) but requires more wires. Multiple slaves share SCK/MOSI/MISO; each slave has its own CS line.

I²C — Inter-Integrated Circuit

SDA (data)
SCL (clock)
Start/Stop conditions
ACK/NACK

How I²C Works

I²C uses two open-drain lines (with pull-up resistors): SDA (data) and SCL (clock). The master generates the clock and initiates transactions. Up to 128 (7-bit) or 1024 (10-bit) devices share the same bus.


Start condition: SDA falls while SCL is HIGH. Stop condition: SDA rises while SCL is HIGH. Data is valid when SCL is HIGH (changed when SCL is LOW). After each byte, the receiver pulls SDA LOW during the 9th clock pulse to send ACK; if it stays HIGH, that is NACK.


Frame: START | 7-bit addr | R/W | ACK | 8-bit data | ACK | STOP

Protocol Comparison

FeatureUARTSPII²C
Synchronous?No (async)YesYes
Wires2 (TX, RX)4+ (SCK, MOSI, MISO, CS×n)2 (SDA, SCL)
Max devices2 (point-to-point)Unlimited (one CS each)128 (7-bit) / 1024 (10-bit)
Full duplex?YesYes (simultaneous)No (half-duplex)
Typical speedup to ~1 Mbpsup to ~100 MHz100 kHz – 3.4 MHz
AddressingNone (dedicated wire)None (CS pin per device)7-bit or 10-bit address
Error detectionOptional parity bitNone built-inACK/NACK only
Hardware complexitySimpleModerateModerate (pull-ups needed)
Typical useDebug consoles, GPS, Bluetooth, RS-232Flash, SD cards, ADCs, displaysSensors (temp, IMU), EEPROMs, RTCs
Pull-up resistors?NoNoRequired (on SDA & SCL)
Clock stretchingN/AN/ASupported by slave
Long-distance?RS-232 up to 15m; RS-485 up to 1.2kmShort (high-speed, board-level)Short (board-level, <1m typical)

When to Use Which

UART: Simple two-device communication, debug output, connecting to legacy serial equipment (GPS modules, RS-232). No clock signal, so both sides must agree on baud rate. Easy to implement in software ("bit-bang").


SPI: Fast data transfer to a single peripheral (SD card, external flash, high-speed DAC/ADC). Needs more pins for multiple devices but supports very high clock rates. Best for applications where speed matters more than pin count.


I²C: Multiple sensors on a single bus with minimal wiring. Ideal for slow peripherals (temperature sensors, IMUs, EEPROMs) where you need many devices but speed is not critical. Requires careful pull-up resistor selection based on bus capacitance.