In short: UART, SPI, I2C, and CAN each trade off wiring cost, speed, device count, and robustness — UART for simple point-to-point links, SPI for fast on-board peripherals, I2C for many slow sensors on two wires, and CAN for noisy, safety-critical multi-node buses like a car.
Every embedded system eventually has to move a byte from one chip to another. The question is never "which protocol is best" in the abstract, but "which trade-offs match this link." A pressure sensor talking to a microcontroller, a flash chip feeding a bootloader, and 40 electronic control units sharing a car's wiring harness are three completely different engineering problems. This guide walks through the four workhorse serial protocols — UART, SPI, I2C, and CAN — and the concrete reasons you reach for each.
Why serial, and why these four
Parallel buses move a whole word per clock, but they cost one pin per bit plus skew-matched routing. As clock rates climbed, serializing the data onto one or two wires — and spending transistors on the SerDes instead of PCB real estate — won almost everywhere. The four protocols below are the ones you will meet on virtually every microcontroller datasheet, from an 8-bit Microchip PIC to a multi-core NXP i.MX. They differ along three axes that drive every design decision: wires, speed, and addressing (how a master picks which device it is talking to).
UART: the simplest link
UART (Universal Asynchronous Receiver/Transmitter) is asynchronous — there is no shared clock line. Both ends simply agree on a baud rate beforehand (9600, 115200, up to a few Mbit/s on modern parts) and a frame format, classically 8 data bits, no parity, 1 stop bit ("8N1"). The transmitter idles high, drops a start bit, shifts out the byte LSB-first, then raises a stop bit. The receiver oversamples (typically 16x) to find the bit centers.
UART is strictly point-to-point: one TX, one RX per direction. It has no addressing, so you cannot put three devices on one UART and expect them to sort themselves out. Its appeal is ubiquity and debuggability — a logic analyzer or even a USB-serial dongle decodes it trivially, which is why bootloaders, GPS modules, and debug consoles still default to it.
Gotcha: because there is no clock, a 2–3% baud mismatch between a cheap RC oscillator and the peer accumulates across the 10-bit frame and corrupts the stop bit. Always use a crystal or trimmed internal oscillator for links above 115200 baud.
SPI: speed at the cost of pins
SPI (Serial Peripheral Interface) is synchronous and full-duplex. The master drives a clock (SCLK) and a Master-Out-Slave-In line (MOSI); the slave replies on MISO on the same clock edges. There is no device address on the wire at all — the master selects a slave by pulling its dedicated Chip Select (CS/SS) line low. That is the defining trade-off: SPI is blisteringly fast (tens of MHz; 50–100 MHz on QSPI flash) because there is no protocol overhead, but every extra slave costs another GPIO pin for its CS.
SPI is the right choice for high-throughput on-board peripherals: SD cards, TFT displays, ADCs sampling at megahertz, and especially NOR flash that a system boots from. If you want the deeper comparison of when a fast four-wire bus beats a tidy two-wire one, see our companion piece on I2C vs SPI.
I2C: many devices on two wires
I2C (Inter-Integrated Circuit) solves SPI's pin-explosion problem by giving every device a 7-bit address and sharing exactly two open-drain lines: SDA (data) and SCL (clock), each pulled up by a resistor. A transaction begins with a START condition, the master shifts out the 7-bit address plus a read/write bit, the addressed slave pulls SDA low to ACK, and data flows byte-by-byte with an ACK after each. Standard mode is 100 kHz, Fast mode 400 kHz, and Fast-mode Plus reaches 1 MHz.
The addressing is both the strength and the limit. You can hang a temperature sensor at 0x48, an RTC at 0x68, and a barometer at 0x76 on the same two wires — but if two parts share a fixed address (common with cheap sensor modules), you need an address-select pin, an I2C mux, or a second bus. The open-drain lines also cap speed: the pull-up resistor and total bus capacitance form an RC time constant, so a heavily loaded bus must either slow down or use stronger pull-ups.
CAN: the robust multi-master bus
CAN (Controller Area Network) was built by Bosch for automobiles, where a dozen meters of harness run beside spark plugs and alternators. Its two defining choices are differential signaling — CAN_H and CAN_L swing in opposite directions, so electromagnetic noise cancels out in the twisted pair — and message-based addressing. CAN frames carry an 11-bit (or 29-bit extended) identifier that names the message, not the node. Any ECU can transmit; receivers use hardware acceptance filters to decide what to keep.
The elegant part is arbitration. When two nodes start transmitting at once, each identifier bit is a dominant 0 or recessive 1. A node that sends recessive but reads dominant on the bus knows a higher-priority message is present and silently backs off — collision resolved with zero retransmission and zero lost time. Classic CAN runs to 1 Mbit/s; CAN FD extends the data phase to 5–8 Mbit/s with up to 64-byte payloads.
Numbers that matter: a classic CAN bus needs a 120 Ω termination resistor at each physical end of the trunk. Miss one and reflections corrupt frames; add a third and you overload the drivers. This is the single most common lab mistake students make wiring their first bus.
Choosing: a side-by-side
| Protocol | Wires | Typical speed | Addressing | Best for |
|---|---|---|---|---|
| UART | 2 (TX/RX) | ≤ a few Mbit/s | none (1:1) | Debug console, GPS, modems |
| SPI | 3 + 1 CS/slave | 10–100 MHz | CS pin per slave | Flash, displays, fast ADCs |
| I2C | 2 (SDA/SCL) | 0.1–1 MHz | 7-bit on-wire | Many slow sensors on-board |
| CAN | 2 differential | 1 Mbit/s (8 FD) | message ID | Noisy multi-node, automotive |
In practice a single board uses several at once: SPI to the flash, I2C to the sensor cluster, UART to the debug header, and CAN to the outside world. In VLSI verification coursework, these same protocols become the first serious SystemVerilog UVM agents you will write — a UART driver is a rite of passage before you tackle AXI. Teams building silicon lean on Synopsys VCS, Cadence Xcelium, or Siemens Questa to simulate these bus interfaces long before tape-out; our hands-on labs mirror that exact toolchain. Explore the full track on the CourseTron courses page, or dive deeper into on-board timing in our guide to debugging I2C bus errors.
If your goal is industry placement rather than theory, the structured programs at ChipXpert's VLSI training pair this protocol knowledge with real EDA flows and interview preparation.
Ready to build a UART and I2C driver from scratch on real hardware? Join the CourseTron Embedded Systems track and ship a working multi-protocol firmware project. Start learning →
Frequently asked questions
Is SPI always faster than I2C?
For raw throughput, yes — SPI's push-pull lines and absence of per-byte ACK overhead let it run 10–100x faster than I2C. But "faster" ignores pin cost: ten SPI slaves need ten chip-select pins, whereas ten I2C devices share two wires. Pick SPI for bandwidth, I2C for density.
Why does CAN use two wires instead of one?
CAN uses a differential pair so that external noise couples equally onto both lines and cancels when the receiver subtracts them. In a car's electrically hostile environment this common-mode rejection is what keeps a 1 Mbit/s bus reliable over several meters of unshielded harness.
Can I connect two devices with UART and a third later?
Not on the same UART. UART is inherently point-to-point with no addressing. To add devices you either use a separate UART per peer, add an RS-485 transceiver layer with a software addressing scheme, or switch to an addressable bus like I2C or CAN.
What is clock stretching in I2C?
A slow slave can hold SCL low after an ACK to tell the master "wait, I'm not ready." The master must sense the line is still low and pause its clock. Not every master supports it in hardware, which is a frequent source of hangs with sensors like certain SHT or BME parts.