In short: Pick UART for simple point-to-point links, I2C when you need many addressable devices on just two wires, and SPI when raw throughput and full-duplex streaming matter more than pin count.
Every embedded design eventually faces the same crossroads: your microcontroller must talk to a sensor, a display, an EEPROM, or an ADC, and three venerable serial buses compete for the job. UART, I2C, and SPI have each survived forty years because they occupy genuinely different sweet spots. Choosing wrongly costs you pins, PCB area, power, or bandwidth you cannot spare. This guide compares them on the four axes that actually decide a design: speed, pin count, addressing, and duplex.
The one-minute mental model
UART is a peer-to-peer link with no clock wire; both ends must agree on a baud rate in advance. I2C is a shared two-wire bus where a controller addresses many targets by a 7-bit address. SPI is a controller-centric bus that trades extra wires for the highest clock speeds and true simultaneous send/receive. Hold those three sentences and most decisions resolve themselves.
Speed: how fast can each move data?
SPI wins decisively. Because the controller drives a dedicated clock and there is no addressing or acknowledge overhead per byte, SPI routinely runs at 10–50 MHz, and parts like SD cards or TFT displays push 50 MHz+. I2C is clocked but capped by its open-drain bus: 100 kHz standard mode, 400 kHz fast mode, 1 MHz Fast-mode Plus, and 3.4 MHz High-speed mode — though pull-up resistors and bus capacitance usually keep real designs at 400 kHz. UART has no clock to share, so its ceiling is set by how precisely both oscillators match: 115,200 baud is the workhorse, and 921,600 baud or a few Mbaud is achievable with clean clocks.
Rule of thumb: for a 320×240 color display refreshing at 60 fps you need roughly 110 Mbit/s — only SPI (or a parallel bus) survives that. A temperature reading every second needs under 1 kbit/s, where even standard I2C is wildly over-provisioned.
Pin count: the cost that hides on your BOM
This axis flips the ranking. I2C needs exactly two wires (SDA, SCL) no matter how many devices hang off the bus — perfect for pin-starved packages. UART needs two (TX, RX) per link, and crucially those links do not share; three UART peripherals mean six pins and three hardware blocks. SPI is the hungriest: three shared lines (SCLK, MOSI, MISO) plus one chip-select per target, so eight SPI devices cost 3 + 8 = 11 pins.
Addressing: who gets to talk?
I2C bakes addressing into the protocol. The controller broadcasts a 7-bit address (128 slots, minus reserved ones), and only the matching target responds with an ACK. That is why you can chain a sensor at 0x1D, an OLED at 0x3C, and an EEPROM at 0x50 on the same two wires. SPI has no addressing concept at all — selection is physical, via chip-select lines, which is simpler to reason about but does not scale on pins. UART is inherently point-to-point; multi-drop variants like RS-485 add addressing in software or a higher layer.
Duplex: can you send and receive at once?
SPI is the only one that is truly full-duplex: MOSI and MISO are separate wires, so every clock edge shifts a bit out and a bit in simultaneously — ideal for streaming audio codecs or ADCs. UART is full-duplex too, since TX and RX are independent lines, but as a point-to-point link rather than a shared bus. I2C is half-duplex: a single bidirectional SDA line means the controller and target take turns, never overlapping.
Side-by-side
| Trait | UART | I2C | SPI |
|---|---|---|---|
| Wires | 2 (TX, RX) | 2 (SDA, SCL) | 3 + 1 CS per device |
| Typical speed | 115.2 kbaud–few Mbaud | 100 kHz–3.4 MHz | 10–50+ MHz |
| Clock | None (async) | Shared (sync) | Shared (sync) |
| Addressing | Point-to-point | 7-bit (up to ~112 devices) | Physical chip-select |
| Duplex | Full | Half | Full |
| Best for | Consoles, GPS, modems | Sensor arrays, EEPROM, RTC | Displays, flash, ADC/DAC |
Signal integrity note: I2C's open-drain lines demand correctly sized pull-ups — too weak and rise times blur the clock; too strong and you exceed the 3 mA sink limit. When buses misbehave, engineers reach for protocol decoders in a logic analyzer or a full mixed-signal scope rather than guessing.
How the choice plays out in real projects
A battery weather node with a BME280 humidity sensor, an RTC, and a tiny OLED: all three speak I2C, so two wires serve everything and you keep the MCU in a low-pin package. A data-logger writing to NOR flash at megabytes per second: SPI, because only it sustains the throughput and the flash chip already expects it. A board bringing up a Linux SoM that needs a serial console and a GPS module: two independent UARTs, because each is a clean point-to-point stream with no addressing fuss. The same reasoning scales up to chip design — when verification teams model these interfaces in SystemVerilog and run them through tools from Synopsys VCS, Cadence Xcelium, or Siemens Questa, the bus you picked at the board level reappears as a protocol checker in the testbench.
Want the full mental model with waveforms and gotchas? Our SPI protocol explained walkthrough drills into clock polarity and phase (CPOL/CPHA), and the companion I2C addressing and clock stretching piece covers the edge cases that trip up first designs. For a structured path from protocols to full RTL-to-GDSII flows, see our course catalog. If you are weighing a career move into verification or physical design, the industry training at ChipXpert's VLSI programs pairs well with this fundamentals track.
Ready to go from reading datasheets to writing drivers and testbenches? Join the CourseTron Embedded Protocols & VLSI track and build real I2C, SPI, and UART interfaces end-to-end. Explore the curriculum →
Frequently asked questions
Which is fastest, I2C, SPI, or UART?
SPI is the fastest by a wide margin, commonly running 10–50 MHz with no per-byte protocol overhead. I2C tops out at 3.4 MHz (usually run at 400 kHz), and UART is typically 115.2 kbaud, reaching a few Mbaud only with well-matched clocks.
Why does I2C need only two wires for many devices?
I2C uses a shared bus with 7-bit addressing. Every device listens on the same SDA/SCL pair, and only the one whose address the controller sends responds. Adding devices costs no extra pins, just a unique address.
Is UART a bus?
No. Standard UART is a point-to-point link between exactly two devices. Multi-drop networking needs a higher layer such as RS-485 with software addressing; plain UART cannot address multiple nodes.
When should I avoid SPI despite its speed?
Avoid SPI when pins are scarce or you have many slow peripherals. Each target needs its own chip-select line, so eight SPI devices consume eleven pins versus two for I2C — a poor trade when you only read sensors occasionally.