Protocols
I2C — Inter-Integrated Circuit
A two-wire, multi-drop, addressed bus. Where SPI trades pins for speed, I2C trades speed for pin count — many devices can share the same two wires because addressing happens in-band.
- What it is
- A two-wire, multi-drop bus where every device shares SDA/SCL and is picked out by an in-band address, not a dedicated pin.
- Mental model
- A party line: everyone hears everything, but only the device whose address was called speaks up.
- Key numbers
- 2 wires (SDA, SCL), 100 kHz–3.4 MHz depending on mode, 7-bit addresses (0x08–0x77 typical).
- Reach for it when
- You're wiring up several low-speed sensors and pin count matters more than raw throughput.
Wires and pull-ups
- SDA
- Serial data — bidirectional, shared by every device on the bus.
- SCL
- Serial clock — driven by the current bus master; can also be held low by a slave (clock stretching).
Both lines are open-drain: every device can only pull them low, never drive them high. That's deliberate, not a limitation — if devices could actively drive the line both ways, two devices disagreeing at the same instant would short their outputs together. Open-drain makes the worst case harmless: multiple devices pulling low at once is still just "low." Since nothing on the bus can drive the line high, something else has to — that's the external pull-up resistor (typically 2.2 kΩ–10 kΩ, board-dependent) tying each line back to the logic-high rail. A device idles by simply releasing the line and letting the resistor win.
Missing or too-weak pull-ups is the most common reason a "correctly wired" I2C bus doesn't work at all — with nothing to source current onto the line, SDA/SCL just sit near 0 V and no device ever sees a valid logic 1.
Anatomy of a transaction
- START — master pulls SDA low while SCL is high.
- Address byte — 7 (or 10) address bits + 1 read/write bit, MSB first.
- ACK/NACK — receiver pulls SDA low for one clock to acknowledge each byte.
- Data byte(s) — 8 bits each, ACKed individually.
- STOP — master releases SDA while SCL is high.
A repeated START is how a master switches from writing a register address to reading its value without releasing the bus — critical for the common "write register pointer, then read" pattern used by most I2C sensors.
Addressing
Most parts use 7-bit addresses (0x08–0x77 usable; some ranges reserved).
Datasheets sometimes list an 8-bit "write address" that already includes
the R/W bit shifted in — a frequent source of off-by-one-bit confusion
when porting code between platforms. A less common
10-bit addressing mode exists for when 7 bits' worth
of address space genuinely isn't enough — it spends part of the first
address byte as an escape sequence (1111 0XX) signaling
"the real address continues in the next byte," which is why a 10-bit
device is invisible to a controller that only knows how to send 7-bit
addresses.
Speed grades
| Mode | Max clock |
|---|---|
| Standard | 100 kHz |
| Fast | 400 kHz |
| Fast Plus | 1 MHz |
| High Speed | 3.4 MHz |
Clock stretching and arbitration
Because SCL is open-drain, a slow slave can hold it low to pause the master mid-byte (clock stretching) — useful for peripherals that need time to prepare data, but it means SCL should always be read back, not assumed. In multi-master systems, arbitration works because a master monitors SDA while transmitting and backs off if it sees a bit it didn't drive — no separate bus-grant mechanism is needed.
Beyond 127 addresses: muxes and expanders
A 7-bit address space, combined with the reality that many sensor families ship with only one or two selectable addresses (often just a single address pin, giving two choices), runs out fast on a board with several identical sensors. Two standard ways around it:
- I2C multiplexer (e.g. the PCA9548) — itself an addressed I2C device that, once configured, connects the controller to one of several independent downstream I2C buses. Each downstream bus can then reuse the same sensor address without collision, since only one is electrically connected at a time.
- I2C GPIO/IO expander (e.g. the PCF8575, MCP23017) — doesn't solve address collisions directly, but turns a single I2C address into many extra GPIO pins, which is often the more direct fix when the actual goal was "I need more pins," not "I need more of this exact sensor."
SMBus: I2C's stricter cousin
SMBus (System Management Bus) is a stricter subset/superset of I2C —
electrically and at the protocol level close enough that most SMBus
devices work on a general I2C bus and vice versa, but SMBus adds
things I2C leaves optional: a fixed timeout that forces a stuck bus to
reset itself, tighter voltage-level and timing specs, and standardized
higher-level commands (like the "read word" / "write word" transaction
formats Linux's i2c-dev exposes as
i2c_smbus_read_word_data() and friends). In practice, most
of what looks like "the I2C API" in Linux userspace tooling is
actually the SMBus subset, because it's specific enough to have
well-defined helper functions where raw I2C intentionally isn't.
- Pros
- Only two wires no matter how many devices are on the bus — adding a tenth sensor costs nothing extra in pins, unlike SPI's one-CS-per-device. Addressing is in-band, so the wiring itself never has to change as devices are added.
- Cons
- Half-duplex and slower than SPI at any given clock rate, a 7-bit address space that runs out fast with several identical sensors (see muxes/expanders above), and a stuck slave can hang the whole bus in a way that needs manual recovery — none of which SPI's point-to-point wiring is exposed to.
- Reach for I2C when
- You're wiring up several low-speed sensors/peripherals and pin count matters more than throughput — the common case on a densely packed board.
- Reach for something else when
- You need real throughput (a display, flash memory, an ADC streaming samples) — SPI's extra pins buy meaningfully higher speed and simpler, more robust framing. Need multiple independent controllers sharing a bus over real distance with guaranteed priority instead of just several peripherals near one controller? That's CAN's job, not I2C's.
Real-world applications
- Environmental sensors — temperature/humidity/pressure sensors (BME280-class parts) and IMUs (MPU6050-class parts) are overwhelmingly I2C, since their data rates are modest and board space is tight.
- EEPROMs — small configuration/calibration-data chips (24LCxx family) on countless boards.
- Display controllers — small OLED panels (SSD1306) are commonly driven over I2C when SPI's extra pins aren't worth it for a slow-updating display.
- Power management ICs — PMICs, fuel gauges, and RTC chips almost always expose I2C as their control interface on phones, wearables, and single-board computers.
- Raspberry Pi / dev-board sensor HATs — the standard way third-party sensor boards attach, since the host exposes one shared I2C bus that many add-on boards can hang off simultaneously.
Gotchas
- No pull-ups (or pull-ups on only one side of a level shifter) → bus stuck low, nothing acks.
- A device that locks up mid-transaction can hold SDA low forever; toggling SCL manually up to 9 times is the standard "unstick the bus" recovery.
- 7-bit vs. 8-bit address confusion — check whether the datasheet's listed address already includes the R/W bit.
- On Linux,
i2c-devplusi2c-tools(i2cdetect,i2cget,i2cset) let you probe a bus from userspace — see Linux → Drivers.