Jump to content
Jump to content
✓ Done
Home / Embedded Systems / I2C vs SPI: Which Serial Bus to Use, and Why
JA
Embedded Systems · Jun 17, 2026 · 9 min read

I2C vs SPI: Which Serial Bus to Use, and Why

I2C vs SPI: Which Serial Bus to Use, and Why

I2C and SPI both connect chips to a microcontroller over a short on-board serial link, and the choice is a tradeoff of pins, speed, and device count. I2C uses two shared wires and addresses each device in software, so adding parts costs no extra pins, but it is slower and half-duplex. SPI uses four wires plus one chip-select line per device, runs full-duplex at far higher clock rates, and has no addressing or acknowledgment.

Reach for I2C when pins are scarce and the peripherals are slow. Think sensors, EEPROMs, and real-time clocks. Reach for SPI when you need throughput to a single device, like a display, an SD card, flash memory, or a fast ADC. The rest of this is the engineering reason behind that one-line answer, including the parts that bite you at bring-up rather than on the datasheet.

What both buses are for

Both I2C and SPI are synchronous serial buses for short, on-board links between a microcontroller and peripheral chips. Synchronous is the word that matters. It means there is a clock line, and that clock keeps both ends in step so a byte sent by the controller arrives the same way it left. The peripherals are the usual cast: sensors, displays, memory. This is the description NXP and Microchip both use, and the third common option breaks that rule.

That third option is UART. Microchip's UART documentation describes it as asynchronous, which means there is no shared clock line at all. Both ends agree on a baud rate ahead of time and trust their own timing. UART is also point to point rather than a bus, so it connects two devices and stops there. That is a different shape of problem. When you are hanging several chips off one microcontroller, you are choosing between I2C and SPI, and you are really choosing along three axes: how many pins you can spare, how fast the data has to move, and how many devices you need to talk to.

I2C: two wires and a software address

Go deeper
AI prompt engineering and model comparison reference cards.
Reference Cards →

I2C uses two wires, and every device on the bus shares them. NXP's UM10204, the I2C-bus specification, names them SDA for data and SCL for clock. Both lines are open-drain, which is the detail people skip. Open-drain means a device can only pull a line low. Nothing on the bus drives it high. So the bus needs pull-up resistors to bring the lines back up to the supply voltage when no one is talking. No pull-ups, no bus. Get that wrong and the whole thing sits dead or behaves like it is haunted.

Because the wires are shared, I2C cannot use a wire to pick a device. It uses an address instead. Per UM10204, each chip carries an address, normally 7-bit, sometimes 10-bit. The controller selects a device by putting that address on the bus, and the matching chip answers. There is no select pin. The protocol is multi-master capable, so more than one controller can sit on the same two wires, and it builds in an acknowledge bit after every byte. The receiver pulls SDA low to say it got the byte. That ACK is a real signal, not a courtesy. It tells the controller whether a device is even present.

I2C is half-duplex. Data moves one direction at a time down that single SDA line, never both at once. And it comes in defined speed grades. UM10204 lists Standard mode at 100 kHz, Fast mode at 400 kHz, Fast mode Plus at 1 MHz, and High-speed mode at 3.4 MHz. There is also a one-directional Ultra Fast mode at 5 MHz, which is a different animal and not what most parts mean when they say I2C. For the vast majority of sensors and clock chips you will wire, you are living at 100 kHz or 400 kHz and perfectly happy there.

Dave's Take: "I2C only needs two pins, so it is simpler" is true at the connector and false at bring-up. You still have to size the pull-ups for the bus capacitance, stay under the speed the wiring can carry, and dodge two parts that ship with the same fixed address. Simpler wiring is not simpler debugging. I have watched a board work fine with one sensor and fall over the moment a second one with the same address went on the same bus.

SPI: four wires and a chip-select per device

SPI takes the opposite bargain. Microchip's SPI documentation gives it four wires: SCK for the clock, MOSI for controller out, MISO for controller in, and a chip-select line, called SS or CS depending on the datasheet you are reading. Notice that data out and data in are separate wires. That is what lets SPI be full-duplex. It can send on MOSI and receive on MISO at the same instant, on the same clock edge. For something like a display push or a flash read, that matters.

There is no addressing scheme in SPI. To talk to a device, the controller pulls that device's chip-select line low, and the device wakes up and listens. That is the whole selection mechanism. It is simple and it is fast, but it has a cost that shows up later: every additional device needs its own chip-select pin coming off the controller. Two devices, two CS pins. Eight devices, eight CS pins, on top of the three shared lines. The pin budget grows with the part count.

SPI also has no built-in acknowledgment. Nothing comes back to confirm a byte landed. The controller clocks data out and assumes it arrived. Clock polarity and phase, written CPOL and CPHA in the documentation, define the four SPI modes, and both ends have to agree on the same mode or the bits land in the wrong place. The payoff for all of this is raw speed. Microchip's documentation puts SPI well above I2C, commonly into the tens of megahertz, where I2C tops out at 3.4 MHz in high-speed mode. When the job is moving a lot of data to one chip, SPI is built for it.

The decision axes: pins, speed, device count

Here is the side by side. The pin math is the part that decides most real designs. I2C stays at two wires no matter how many devices you add, right up until bus capacitance or address collisions become the limit. SPI grows by one chip-select pin for every device. On a microcontroller with a tight pin count, that single fact often makes the call before speed ever enters the conversation.

Feature I2C SPI
Wires 2 (SDA, SCL) 4 or more (SCK, MOSI, MISO, plus a CS per device)
How devices are selected Software address (7-bit, sometimes 10-bit) A chip-select line pulled low
Duplex Half-duplex Full-duplex
Typical speed Up to 3.4 MHz (high-speed mode) Tens of MHz
Acknowledgment Yes, an ACK bit after each byte None
Adding a device Free, same two wires One more chip-select pin

Read that table as a set of tradeoffs, not a scoreboard. I2C trades speed for pin efficiency and gives you an ACK bit so the bus can tell you when a device is missing. SPI trades pins and error feedback for throughput and full-duplex transfers. Neither one is better. They are tuned for different jobs, and the right answer falls out of what you are wiring.

When each one wins

The honest sorting is by speed and pin pressure, and the typical fits line up cleanly. Put your many low-speed peripherals on I2C, especially when pins are scarce. Sensors belong there. So do real-time clocks, EEPROMs, and the small configuration chips that hold a few bytes of settings and rarely get touched. None of those need to move much data, and they are happy sharing two wires.

Put your high-throughput single devices on SPI. A display that needs a full framebuffer pushed to it. An SD card. Flash memory you are reading at speed. A fast ADC sampling hard. These want bandwidth, and they usually want it to one part at a time, so the chip-select cost stays low and the full-duplex speed pays off. The pattern is consistent enough that you can almost read a parts list and predict the bus before you check a single datasheet.

Dave's Take: "SPI is faster, so use SPI" skips the cost. SPI has no acknowledgment and no addressing, so on a noisy board a dropped bit shows up as corrupted data, not an error flag. Nothing tells you it happened. Full-duplex speed buys you nothing if you spend a week chasing chip-select timing or staring at a frame that looks almost right. Faster on paper is not the same as faster to ship.

The gotchas nobody mentions

I2C's open-drain wiring hides three traps. The first is pull-up sizing. Those resistors are not a formality you copy from a reference design and forget. They fight bus capacitance, and if they are too weak for the capacitance on your traces, the lines rise too slowly and your edges smear, which limits the speed the wiring can actually carry no matter what mode you asked for. The second is that same bus capacitance climbing as you add devices and trace length, quietly pushing you back down toward Standard mode. The third is address collisions. Plenty of I2C parts ship with a fixed address, and two of the same part on one bus means a fight the protocol cannot referee. Some chips give you a couple of address-select pins to dodge this. Many do not. Check before you commit the layout.

SPI's traps are different. The first is chip-select sprawl. Every device is another CS pin, and on a busy microcontroller those run out, which is when people start improvising with decoders and shift registers to save the speed they wanted. The second is the missing acknowledgment. With no ACK, the bus has no idea whether a transfer worked, so corruption travels as data rather than as an error, and you find it downstream when something acts wrong. The fix is usually a checksum or a known-value read-back you build yourself, because the protocol will not.

Both buses live or die by the chip running them. The number of hardware I2C and SPI ports you get is a property of your microcontroller, and it varies a lot from part to part. Some give you several of each. Some give you one I2C peripheral and make you bit-bang anything more. If you are weighing parts, the count of usable I2C and SPI peripherals across the common chips is worth a look in our breakdown of the STM32, ESP32, and RP2040, because that number, more than any spec on the bus itself, decides how much you can hang off one board.

How to choose

Start with pins, not speed. Count what the package gives you and what your peripherals demand. If you are pin-constrained and your devices are slow, I2C is the answer, and your effort goes into pull-up sizing and address planning. If you have a single device that needs to move real data, SPI is the answer, and your effort goes into getting the mode right and adding your own error checking. Most boards end up running both, with the slow sensor crowd on I2C and the one bandwidth-hungry part on its own SPI bus.

The mistake is letting a spec-sheet number make the call. SPI's tens-of-megahertz headline does nothing for an EEPROM that updates twice a day. I2C's two-wire economy does nothing for a display starved for bandwidth. Match the bus to the job and the work that follows gets shorter. That is the whole game.

Related: What Is a Microcontroller | STM32 vs ESP32 vs RP2040

JA
Founder, TruSentry Security | Technology Editor, EG3 · EG3

Founder of TruSentry Security. Installs the cameras, reads the datasheets, and writes about what the spec sheet got wrong.