P3 · Interfacing & Communication · Lesson 4 of 5

I²C — Two-Wire Addressed Bus

~14 min

Slide 1

Two wires, many devices, each with an address

I²C (Inter-Integrated Circuit, said "eye-squared-see" or "I-two-C") is the wire-saver. It performs a clever trick: connect many devices using just two wires — no matter how many devices you add. It does this with addresses instead of SPI's per-device select pins.

Two wires, shared by everyone

An entire I²C bus is just two lines, shared by every device on it:

  • SDA — Serial Data (the data line).
  • SCL — Serial Clock (the clock line — so I²C is synchronous, like SPI).

Every device — the controller and all the peripherals — connects to these same two wires. Adding a tenth device adds zero new wires. Compare that to SPI, where each new device needs another CS pin, and you see I²C's whole appeal: it scales by wires you don't add.

              ┌──────── SDA ────────┬──────────┬──────────┐
Microcontroller                     │          │          │
              └──────── SCL ────────┴──────────┴──────────┘
                              Device 1   Device 2   Device 3
                              (addr 0x48)(addr 0x68)(addr 0x3C)
                          (only two shared wires, any number of devices)

The problem this creates — and the solution: addresses

If everyone shares the same two wires, how does the controller talk to just one device without the others answering? SPI used a physical CS pin per device. I²C uses a software address instead.

Every I²C device has a unique address — a small number, often written in hex (e.g., 0x48, 0x68, 0x3C). The address is usually fixed by the chip's manufacturer (sometimes partly configurable with a pin or two). To start a conversation, the controller broadcasts the address of the device it wants on the shared bus. Every device hears it, but only the one whose address matches responds — the rest stay quiet.

It's exactly like calling someone's name across a crowded room: everyone hears the name, but only the right person answers. The "name" is the I²C address.

Why addressing beats per-device pins

This addressing scheme is what lets I²C connect many devices on two wires:

  • No CS pins — the controller selects by name (address), not by wire.
  • Constant wiring — two wires whether you have 2 devices or 12.
  • Pin-efficient — perfect for small, pin-limited microcontrollers with lots of little peripherals.

The price is that I²C is more complex internally (addresses, acknowledgements, a defined start/stop sequence) and slower than SPI. But for "many slow devices, few pins," it's unbeatable.

There's one physical requirement that makes the shared bus work safely — pull-up resistors — and that's the next slide, tying directly back to L1.

Quick check

I²C connects many devices using just two wires because each device has:

Slide 2

Pull-up resistors: why I²C needs them

There's one physical detail every I²C bus needs, and it trips up beginners constantly: pull-up resistors on SDA and SCL. The reason ties straight back to the pull-up/pull-down resistors you met in L1 — here's why I²C can't live without them.

The problem: many devices, one shared wire

On an I²C bus, many devices connect to the same two wires. That raises a danger: what if two devices try to drive the line at once — one pushing it HIGH, another pulling it LOW? In an ordinary "push-pull" output, that's a near-short: a direct fight between a device sourcing current and one sinking it, potentially damaging both.

I²C avoids this with a design called open-drain.

Open-drain: devices can only pull LOW

On an I²C bus, every device's output is open-drain, which means a device can do only one active thing: pull the line LOW (connect it to ground). No device is allowed to actively drive the line HIGH.

So how does the line ever get HIGH? That's the job of the pull-up resistors.

The pull-ups return the line HIGH

Each line (SDA and SCL) has a pull-up resistor connecting it to the supply voltage (e.g., 3.3V). This resistor gently holds the line HIGH whenever no device is pulling it LOW — exactly the pull-up behaviour from L1:

  • No device pulling → the pull-up wins → line sits HIGH (idle "1").
  • Any device pulls LOW → it overpowers the gentle pull-up → line goes LOW ("0").

Because devices can only pull low and the resistor only pulls high, two devices can never short-circuit each other. If several pull low at once, the line just goes low — no conflict, no damage. This open-drain-plus-pull-up scheme is precisely what makes a shared multi-device wire safe. It's the physical foundation of the whole I²C bus.

The practical consequence

This is why an I²C bus always needs pull-up resistors — typically a few kΩ on each of SDA and SCL. Forget them, and the lines have no way to reach HIGH: they float, and the bus simply doesn't work (or works erratically). Two very common real-world situations:

  • Breakout/sensor modules often include their own pull-ups on board, so a single module "just works." But put several modules on one bus and you may have too many pull-ups in parallel — something to be aware of.
  • Bare chips on a custom board usually need you to add the pull-ups yourself. Many a dead I²C bus has been revived by adding the two missing resistors.

The L1 connection

This is a satisfying payoff from earlier in the ladder: the humble pull-up resistor (L1) isn't a textbook curiosity — it's the component that makes the most popular sensor bus in the world physically possible. When you add pull-ups to an I²C bus, you're applying L1 directly.

The final I²C slide weighs its trade-off — wires saved versus speed given up — and sets up the protocol-choice decision in Lesson 5.

Quick check

I²C's SDA and SCL lines need pull-up resistors (L1) because the bus is:

Slide 3

I²C's trade-off: wires for speed

I²C's character is the mirror image of SPI's: it spends speed to buy wires. Two wires for any number of devices is a powerful deal — as long as you don't need to go fast. Here's when that trade is right.

What I²C is great at

  • Many devices, minimal pins. This is I²C's superpower. A pin-limited microcontroller can host a temperature sensor, a real-time clock, an accelerometer, a small OLED display, and more — all on the same two wires. Adding devices costs addresses, not pins.
  • Small, slow peripherals. Most little sensor and module chips — environmental sensors, RTCs, EEPROMs, IMUs, small displays — speak I²C precisely because they're slow enough not to need SPI's speed and benefit from the wire economy.
  • Tidy wiring. Two wires snaking past every device is far simpler to route than SPI's clock+two-data+a-CS-each.

What I²C is poor at

  • Speed. I²C is slower than SPI — fine for sensor readings and small displays, but not for streaming bulk data or driving a fast graphical screen. When throughput matters, SPI wins.
  • Complexity. Addresses, acknowledgement bits, and a defined start/stop sequence make I²C more involved than SPI's "just clock the bits." (Libraries hide most of this, but it's there.)
  • Address clashes. Two devices with the same fixed address can't share a bus without help. Occasionally you must check datasheets to avoid a collision (some chips let you change a bit or two of the address).
  • The pull-ups. A real, easy-to-forget requirement (last slide).

The three side by side (preview of Lesson 5)

UARTSPII²C
Wires24 (+CS each)2 (any # devices)
SpeedLow–modHighestModerate
Devices2 onlyMany (pin each)Many (address each)
Spends…(simplest)pins → speedspeed → wires
Sweet spotsimple 2-device linkfew fast peripheralsmany slow peripherals

Summary of I²C

  • Synchronous, two wires: SDA (data) + SCL (clock).
  • Many devices by unique address, not by select pin.
  • Open-drain bus → needs pull-up resistors (the L1 payoff).
  • Trade-off: slower and more complex than SPI, but unbeatable for many slow devices on few pins.

You now have all three workhorses. The instinct you're building — which column does this job belong in? — is exactly what the final lesson sharpens into a clear decision, alongside the analog (ADC/DAC) path for sensors that don't speak any digital protocol at all.