I2C vs SPI: How to Choose the Right Bus for Your Sensor or Peripheral

You’re staring at two versions of the same sensor on Digi-Key. One says I2C, the other says SPI. They cost the same. The datasheets are 40 pages each. You need to pick one, order it, and route a PCB by Friday.
Most engineers make this choice based on whatever they used last time. That works until it doesn’t: until your I2C bus locks up under noise, or you run out of pins because every SPI device needs its own chip-select line, or your IMU can’t keep up because you picked the slow interface.
This article gives you a 5-question decision framework you can reuse on every project. It won’t teach you the protocols from scratch; both are synchronous, serial, short-range, and master-initiated. The differences are what matter.
I2C vs SPI at a Glance
I2C uses 2 wires: SDA (data) and SCL (clock). The signals are open-drain, meaning bus lines float high through pull-up resistors and devices pull them low to talk. Every device has a 7-bit address, so you can hang many devices on the same 2 wires. Built-in ACK/NACK bytes tell you if a device received your data. Typical speeds: 100 kHz (standard), 400 kHz (fast), 1 MHz (fast-mode plus).
SPI uses 4 wires: MOSI (data out), MISO (data in), SCLK (clock), and CS (chip-select). Signals are push-pull, so the driver actively shoves the line high or low. There’s no addressing; instead, you pull a device’s CS pin low to select it. Full-duplex (send and receive at the same time). No built-in acknowledgment. Speeds commonly range from 1 MHz to 50+ MHz, with some devices hitting 80 MHz.
| Feature | I2C | SPI |
|---|---|---|
| Wires | 2 (SDA, SCL) | 4+ (MOSI, MISO, SCLK, CS) |
| Max Typical Speed | 400 kHz – 1 MHz | 1 MHz – 50+ MHz |
| Duplex | Half-duplex | Full-duplex |
| Addressing | 7-bit/10-bit address | Chip-select line per device |
| Multi-device | Yes (shared bus) | Yes (extra CS pin each) |
| Acknowledgment | Built-in ACK/NACK | None (fire and forget) |
| Signal Type | Open-drain (needs pullups) | Push-pull |
| Complexity | Protocol is complex | Protocol is simple |
| Pin Cost (5 devices) | 2 pins | 8 pins (3 shared + 5 CS) |
| Best For | Many slow, small sensors | Fast data, displays, memory |
The 5-Question Framework
These 5 questions, asked in order, will resolve about 90% of real bus-selection decisions.
Q1: How many pins can you spare?
On a small MCU (an ATtiny85 with 8 pins, or a constrained module layout), every GPIO is precious. I2C needs just 2 pins regardless of how many devices you connect. SPI needs 3 shared lines plus 1 CS pin per device.
Connecting 5 sensors? I2C costs you 2 pins. SPI costs you 8. Lean I2C.
Q2: How fast do you need data?
If you need sustained throughput above 1 MHz, SPI is your bus. A TDK ICM-42688-P IMU running at 32 kHz output data rate, an SD card logging data, an SPI flash chip, an SPI-driven display: I2C physically can’t keep up.
Reading a temperature sensor once a second, or polling humidity every 5 minutes? 400 kHz I2C is more than enough. Above 1 MHz: lean SPI. Below: I2C handles it fine.
Q3: How noisy is your environment?
SPI’s push-pull drivers actively force the line high and low, which makes them more resistant to electrical noise and more forgiving of longer traces.
I2C relies on passive pull-up resistors to bring the line high. That’s fine on a clean, short PCB. But add electrical noise or run traces past about 30 cm, and that weak pull-up edge gets corrupted. You’ll see random NAKs or bus hangs. Noisy board or long traces: lean SPI.
Q4: How many devices share the bus?
I2C shines with a cluster of low-speed sensors (temperature, humidity, EEPROM, OLED display, light sensor) all on 2 wires. Addressing handles the rest.
But I2C addresses are limited, and sometimes two identical sensors share the same fixed address. Need 2 BME280s? You’re stuck with 0x76 and 0x77. Need a third? You’ll add an I2C multiplexer, or switch to SPI where each device just gets its own CS line. Many low-speed devices: lean I2C. But watch for address collisions.
Q5: Does your hardware already dictate the choice?
Sometimes the decision is already made for you. Your IMU only offers SPI. Your OLED only has I2C pads broken out. Your MCU has 3 SPI peripherals but only 1 I2C. Or your BLE module reserves certain pins.
Check the sensor datasheet and your MCU peripheral map before agonizing over theory. Let the hardware have the last word.
Here’s the framework as a decision tree:
START
│
┌────────────┴────────────┐
│ Q1: Pins very limited? │
└────────────┬────────────┘
YES / \ NO
↓ ↓
Lean I2C ┌──────────────────────┐
│ Q2: Need > 1 MHz │
│ throughput? │
└──────────┬───────────┘
YES / \ NO
↓ ↓
Lean SPI ┌───────────────────┐
│ Q3: Noisy or long │
│ traces? │
└────────┬──────────┘
YES / \ NO
↓ ↓
Lean SPI ┌──────────────────┐
│ Q4: Many (5+) │
│ devices? │
└───────┬──────────┘
YES / \ NO
↓ ↓
Lean I2C ┌──────────────────┐
│ Q5: Does HW/part│
│ dictate choice? │
└───────┬──────────┘
YES / \ NO
↓ ↓
Use what's Default:
available I2C for
simplicityReal Scenarios You’ll Recognize
Scenario A: Weather station with BME280 + OLED + light sensor
Battery-powered weather logger. BME280 for temperature, humidity, and pressure. SSD1306 OLED for display. VEML7700 light sensor.
All 3 run fine at 400 kHz. You only read them every few seconds. Pin count matters because you want a small, cheap MCU. I2C is the obvious call. Two wires, 3 devices, done.
VCC
│
[Rp] [Rp] Rp = Pull-up resistors (4.7kΩ typical)
│ │
SDA ────┼──────┼──── SDA SCL ────┼──────┼──── SCL
│ │ │ │
┌──┴──┐ ┌┴───┐ ┌───┴──┐ ┌─┴──┐
│ MCU │ │BME │ │ OLED │ │VEML│
└─────┘ └─────┘ └──────┘ └────┘
(Master) (0x76) (0x3C) (0x10)Scenario B: Drone flight controller with IMU + barometer + flash
Your IMU (ICM-42688-P) needs to output data at 8 kHz. Your flash chip streams telemetry logs. The barometer is lower priority but might as well share the fast bus.
SPI across the board. Shared SCLK, MOSI, MISO lines. Separate CS for each device. The IMU runs at 24 MHz SPI clock, the flash at 20 MHz. You’d never hit those numbers on I2C.
Scenario C: Mixed bus, the pragmatic choice
You can use both on the same board. It’s common and often smartest. Slow config sensors (temperature, humidity, EEPROM) on I2C. High-speed data path (flash, display, ADC) on SPI.
Don’t feel forced to pick one bus for everything. Optimize each path on its own.
5 Beginner Mistakes That’ll Cost You a Weekend
Forgetting I2C pull-up resistors. Or using the wrong value. Too high (47kΩ) and the edges are sluggish. Too low (1kΩ) and the devices can’t pull the line down. Start with 4.7kΩ. Symptoms of missing pull-ups: bus hangs, SDA stuck low, garbage reads.
I2C address collisions. You bought 3 identical sensors with no configurable address pin. They all answer to 0x68. Fix: use an I2C mux (TCA9548A), pick sensors with selectable addresses, or move to SPI.
Wrong SPI mode (CPOL/CPHA). SPI has 4 modes (0 through 3) depending on clock polarity and phase. Use the wrong one and your data looks like random noise. Always check the timing diagram in your sensor’s datasheet. Mode 0 (CPOL=0, CPHA=0) is the most common default.
Assuming I2C works over long cables. It doesn’t. I2C was designed for inter-chip communication on a single board. Past about 30 cm, capacitance kills your signal edges. Use a bus extender (P82B715) or switch to a differential protocol like RS-485.
Ignoring clock stretching. Some I2C sensors hold the clock line low while processing. Some MCU I2C peripherals, notably older STM32 parts, handle this poorly or not at all. The result: subtle, intermittent bus hangs that are miserable to debug. Check your MCU errata sheet.
When Neither I2C nor SPI Is Right
Long distances (meters, not centimeters): look at UART/RS-485.
Automotive or industrial with many nodes: CAN bus.
Raw camera or display data at high speed: parallel interfaces or MIPI.
Extreme pin constraints with very low data rates: 1-Wire (but it’s painfully slow).
These are edge cases. For the vast majority of sensor and peripheral connections on a single PCB, the choice comes down to I2C or SPI.
Pick a Bus and Ship the Board
Pin-starved? I2C. Need speed above 1 MHz? SPI. Noisy or long traces? SPI. Lots of slow sensors? I2C. Hardware dictates? Follow it.
When nothing pushes you strongly either way, start with I2C. It’s simpler to wire, simpler to debug with a logic analyzer (you can see addresses and ACKs), and simpler to prototype. If you hit speed or reliability walls, migrate to SPI. Most dual-interface sensors make that switch painless.
If you’re building a BLE-connected sensor node and want to understand how the firmware side fits together, including which peripherals your BLE stack will claim, the Hubble device SDK introduction is a good place to see how on-board bus choices interact with wireless constraints before you commit to a layout.
Hubble Network connects your sensors from silicon to cloud over Bluetooth — no gateways, no complex infrastructure. See how it works →