Deep-dive theory + interactive waveform generator for I²C, SPI, and UART — the three protocols every embedded and VLSI engineer must master.
I²C (Inter-Integrated Circuit) is a synchronous, multi-master, multi-slave, packet-switched serial communication protocol invented by Philips (now NXP) in 1982. It uses only two bidirectional wires — SDA (Serial Data) and SCL (Serial Clock) — pulled to VCC through resistors. Because both lines are open-drain, any device can pull them LOW; they go HIGH only when all devices release the line. This is what enables multi-master operation and clock stretching without bus contention.
Every slave has a unique 7-bit address (112 usable out of 128; some are reserved). The master begins a transaction with a START condition (SDA falls while SCL is HIGH), then sends the 7-bit slave address followed by a R/W̄ bit. The addressed slave responds with an ACK by pulling SDA LOW during the 9th clock. Data then flows byte by byte, each followed by an ACK, until the master issues a STOP condition (SDA rises while SCL is HIGH).
A complete write transaction: START → [ADDR 7b][R/W̄][ACK] → [DATA 8b][ACK] × N → STOP
| Mode | Max Clock | Max Bus Cap | Typical Use |
|---|---|---|---|
| Standard (Sm) | 100 kHz | 400 pF | EEPROMs, basic sensors |
| Fast (Fm) | 400 kHz | 400 pF | RTCs, most modern sensors |
| Fast-Plus (Fm+) | 1 MHz | 550 pF | High-speed sensors, displays |
| High-Speed (Hs) | 3.4 MHz | 100 pF | Memory, camera modules |
| Ultra-Fast (UFm) | 5 MHz | — | Write-only applications |
Sensors (temperature, pressure, IMU), EEPROM (AT24C series), RTC (DS3231), OLED displays (SSD1306), battery management ICs (BQ series), GPIO expanders (PCF8574). I²C is preferred when pin count is critical and bus speed is not the bottleneck.
SPI (Serial Peripheral Interface) is a synchronous, full-duplex serial communication protocol developed by Motorola in the mid-1980s. It uses four wires: SCLK (clock), MOSI (Master Out Slave In), MISO (Master In Slave Out), and CS/SS (Chip Select, active LOW). Unlike I²C, SPI has no addressing mechanism — the master selects a specific slave by asserting its CS pin LOW. Multiple slaves share the same SCLK/MOSI/MISO bus (daisy-chain or parallel CS lines).
SPI is a shift register protocol: internally, master and slave each have an N-bit shift register. On every clock edge, one bit exits the master's register via MOSI and enters the slave, while one bit exits the slave via MISO and enters the master. After N clocks, a complete N-bit word has been exchanged — simultaneously in both directions. There is no ACK; the master must know the protocol of each device to interpret responses.
CPOL (Clock Polarity) sets the idle state of SCLK: 0 = idle LOW, 1 = idle HIGH.
CPHA (Clock Phase) sets which edge is the capture edge: 0 = leading edge, 1 = trailing edge.
Leading edge is the first active transition after CS asserts (rising for CPOL=0, falling for CPOL=1).
| Feature | I²C | SPI |
|---|---|---|
| Wires | 2 (SDA + SCL) | 4 (SCLK, MOSI, MISO, CS) |
| Duplex | Half-duplex | Full-duplex |
| Speed | Up to 5 MHz | Up to 100+ MHz |
| Addressing | 7-bit in packet | CS pin per slave |
| ACK | Yes (hardware) | No |
| Multi-slave | Up to 112 on same bus | One CS pin per slave |
| Typical use | Sensors, EEPROMs, RTCs | Flash, ADC/DAC, SD, displays |
UART (Universal Asynchronous Receiver-Transmitter) is a hardware communication protocol that uses asynchronous serial communication with configurable speed. Unlike I²C and SPI, UART has no clock line — both sender and receiver independently generate their own bit-rate clocks that must be pre-configured to the same baud rate (bits per second). The idle line state is logic HIGH (mark). Transmission begins with a mandatory START bit (logic LOW), which lets the receiver detect the start of a frame and synchronise its sampling clock.
Data bits are transmitted LSB first by convention (bit 0 before bit 7). An optional parity bit follows the data for error detection. One or two STOP bits (logic HIGH) end the frame, giving the receiver time to process before the next frame. Because there is no clock recovery mechanism, baud rates must match within ±2–3% — any mismatch causes the sampling point to drift across the frame.
Example: 8N1 (8 data bits, No parity, 1 stop bit) transmitting 0x41 ('A' = 0b01000001)
Note: 0x41 = 0b01000001. LSB (bit 0 = 1) is sent first → D0=1, then D1..D6=0, D7=0.
| Baud Rate | Bit Period | Typical Use |
|---|---|---|
| 9600 | 104.2 µs | GPS modules, modems, legacy RS-232 |
| 19200 | 52.1 µs | Industrial instruments |
| 38400 | 26.0 µs | Older Bluetooth UART |
| 57600 | 17.4 µs | Some microcontroller debug ports |
| 115200 | 8.68 µs | Standard debug/console (most common) |
| 921600 | 1.08 µs | High-speed UART, FTDI chips |
| 4,000,000 | 250 ns | Maximum for many UARTs |
Debug console (printf over USB-UART), GPS receivers (NMEA sentences), Bluetooth UART (HC-05, HM-10), GSM/LTE modems (AT commands), bootloader flashing, data logging. UART is the universal "wire" for quick embedded communication.
| Feature | I²C | SPI | UART |
|---|---|---|---|
| Type | Synchronous | Synchronous | Asynchronous |
| Wires | 2 | 4 (+1 per slave) | 2 (TX + RX) |
| Duplex | Half | Full | Full |
| Max Speed | 5 MHz | 100+ MHz | ~4 Mbps |
| Addressing | 7-bit (in packet) | CS pin | None |
| Error check | ACK/NACK | None | Parity / Framing |
| Multi-slave | Yes (same bus) | Yes (separate CS) | No (point-to-point) |
| Multi-master | Yes (with arbitration) | No | No |
| Complexity | Medium | Low | Lowest |