What Is I2C (Inter-Integrated Circuit)?
Last updated 7 July 2026 · 4 min read
Direct Answer
I2C (Inter-Integrated Circuit) is a two-wire synchronous serial bus — SDA for data and SCL for clock — that allows a controller to address multiple peripheral devices over the same pair of lines using a 7-bit or 10-bit device address, instead of needing a dedicated chip-select per device like SPI.
Detailed Explanation
I2C uses just two signal lines shared by every device on the bus:
- SDA (Serial Data): carries both directions of data, time-multiplexed.
- SCL (Serial Clock): generated by whichever device is currently acting as controller (in standard mode, a fixed primary controller).
Every transaction starts with a START condition, followed by a 7-bit (or extended 10-bit) address plus a read/write bit, then one or more data bytes, each acknowledged by the receiver, ending with a STOP condition. Because the address is transmitted on the bus itself, any number of peripherals can share the same two wires; there's no per-device chip-select like SPI requires.
Standard speed grades are 100 kHz (Standard Mode), 400 kHz (Fast Mode), 1 MHz (Fast Mode Plus), and 3.4 MHz (High Speed Mode), though most general-purpose sensors and EEPROMs only support up to Fast Mode.
Practical Examples
A common board might have an I2C temperature sensor, an I2C EEPROM, an I2C-controlled GPIO expander, and an external RTC IC all wired to the same two SDA/SCL pins on the microcontroller, each with a distinct fixed or configurable address. The firmware addresses each one individually over the shared bus rather than needing a separate pair of wires per device.
This is exactly why I2C is popular for sensor-heavy designs: adding another I2C peripheral often costs zero additional GPIO pins, as long as its address doesn't collide with something already on the bus.
Design Considerations
- Pull-up resistor sizing: typical values are 2.2 kΩ–4.7 kΩ, but the correct value depends on bus capacitance (trace length, number of devices) and target speed. Too weak a pull-up limits rise time at high speed; too strong increases power draw and ringing.
- Address collisions: check every device's address space before committing to a bus layout, especially with fixed-address sensors from the same vendor family. Where only two devices need to communicate point-to-point, UART is a simpler alternative with no addressing or pull-up requirements, though it cannot serve a shared bus.
- Bus capacitance limits: the I2C spec caps total bus capacitance (400 pF for standard/fast mode), which limits practical trace length and device count without a bus buffer.
- Clock stretching support: some peripherals pause SCL to indicate they need more time; confirm your microcontroller's I2C peripheral (and any bit-banged implementation) actually supports this, or transfers can corrupt silently. See how I2C clock stretching works and how to debug a timeout for the mechanism, which devices commonly use it, and how to tell a legitimate long stretch apart from a genuinely stuck bus.
- Multi-master designs: I2C's "multi-master capable" label refers to a specific wired-AND bus-arbitration mechanism that lets two controllers safely start a transaction at the same moment without corrupting either one. See how I2C multi-master bus arbitration works for the mechanism and when a genuinely multi-controller bus is the right design choice.
- Outgrowing I2C's speed or per-device interrupt lines: I3C is I2C's MIPI-defined successor, backward-compatible on the same SDA/SCL pins, adding dynamic addressing, In-Band Interrupts, and substantially higher throughput. Worth evaluating for a new sensor-heavy design where I2C's fixed addressing or lack of a built-in interrupt mechanism is becoming a real constraint.
- Bus recovery from a stuck slave: a device interrupted mid-transaction (hot-unplugged, or browning out) while holding SDA low wedges the entire bus for every device on it, not just the affected one. Build in the I2C bus-clear recovery sequence from NXP's specification rather than relying on a full power cycle to clear it. On STM32 specifically, this same fault can leave the peripheral's own BUSY flag stuck set even after the bus-clear sequence. See STM32 I2C configuration and BUSY-flag lockup recovery for the additional peripheral-level reset this requires.
- Choosing between I2C, SPI, and UART: for a structured comparison of when each protocol is the better choice, see SPI vs I2C vs UART: which to use.
- I2C on Raspberry Pi: for enabling I2C via device tree overlay, sizing pull-ups for a CM4 carrier board, and using i2cdetect, see Raspberry Pi GPIO Interfacing.
- Mixing 3.3 V and 5 V devices on the same bus: because I2C is open-drain and bidirectional, a simple resistor divider or unidirectional buffer cannot shift it. See how do you shift logic levels between 3.3V and 5V? for why I2C specifically needs an open-drain-aware bidirectional buffer (PCA9306/TCA9516-class, or a discrete MOSFET shifter).
- Commercial peripheral integration: integrating multiple I2C peripherals into a production device involves driver development, bus diagnostics, and error recovery. Zeus Design's embedded firmware team handles this kind of hardware-software integration for commercial products.
Common Mistakes
- Omitting pull-up resistors entirely because the bus "seems to work" on the bench with parasitic capacitance, then failing intermittently in production.
- Two peripherals sharing a fixed address with no multiplexer or alternate-address strategy planned for.
- Ignoring NACK responses from the bus and assuming a write succeeded. See what a real NACK-on-every-address failure looks like in practice for how to diagnose it systematically.
- Running at 400 kHz with pull-up resistors and trace lengths only validated at 100 kHz.
Frequently Asked Questions
- Why does I2C need pull-up resistors?
- I2C uses open-drain outputs on both SDA and SCL, meaning devices can only pull the line low, never drive it high. External pull-up resistors are required to return the lines to a high (idle) state, and this is also what allows multiple devices to share the bus safely.
- Can two I2C devices share the same address?
- Not on the same bus segment. If two peripherals have a fixed, identical address, you need an I2C multiplexer/switch, a level-translating bus splitter, or to choose a peripheral variant with an alternate address (many sensors expose an address-select pin for exactly this reason).
References
Related Questions
What Is SPI (Serial Peripheral Interface)?
SPI is a synchronous full-duplex serial bus for connecting microcontrollers to peripherals at high speed. Learn how SCLK, MOSI, MISO, and CS work.
What Is UART (Universal Asynchronous Receiver-Transmitter)?
UART sends serial data asynchronously over TX and RX with no shared clock. Learn how framing, baud rate, RS-232 voltage levels, and common UART pitfalls work.
SPI vs I2C vs UART: Which Protocol Should You Use?
SPI suits high-speed transfers, I2C minimises pins for multi-device buses, and UART suits point-to-point links. Learn which to choose for your embedded design.
What Is a Microcontroller (MCU)?
A microcontroller (MCU) combines a CPU, flash, RAM, and peripherals on one chip. Learn how MCUs work and how they differ from microprocessors and FPGAs.
What Is PCB Routing, and How Do You Route a Board Well?
PCB routing draws the copper traces implementing a schematic's netlist, balancing trace width, spacing, layer use, and impedance requirements.
How to Interface Sensors and Peripherals with Raspberry Pi GPIO
Interface sensors and peripherals with Raspberry Pi GPIO: 3.3 V limits, level shifting, I2C/SPI/UART device tree configuration, lgpio API, and i2cdetect.
Related Forum Discussions
I2C bus completely dead after unplugging a sensor live — SDA stuck low, no NACK, nothing
We've got a shared I2C bus with four sensors on it (temperature, humidity, an IMU, and a current sense IC), all on the same bus off one MCU.
I2C bus scan finding nothing — NACK on every address despite pull-ups
Working through my first proper I2C project, hooking up a BME280 temp/humidity sensor to an ESP32 devkit. Wired SDA to GPIO21 and SCL to GPI