I²C — Inter-Integrated Circuit Bus

I²C connects many sensors, EEPROMs, RTCs and power ICs using just two wires. Learn open-drain signalling and pull-ups, start/stop conditions, 7-bit addressing, ACK/NACK, register read/write sequences with repeated start, clock stretching, speed modes, pull-up resistor sizing from bus capacitance, multi-master arbitration and bus-recovery techniques.

I²C (two-wire interface, TWI) uses SDA (data) and SCL (clock). Both lines are open-drain: devices can only pull them low, and pull-up resistors bring them high. This allows many devices, and even multiple masters, to share the bus without short circuits.

Each device has an address; the master starts a transaction, sends the address and a read/write bit, and the addressed device acknowledges. Typical sensor access is 'write the register number, then read its value' — a pattern you will use constantly.

An analogy

I²C is a meeting where anyone may lower a flag (pull the line low) but nobody may force it up — springs (pull-ups) raise it. The chairperson (master) calls a name (address); only that person answers 'present' (ACK).

Open-drain and pull-ups

No device ever drives I²C lines high; they only release them and pull-ups raise the voltage. This wired-AND behaviour makes a low from any device win, enabling ACKs, clock stretching and multi-master arbitration. Too-large pull-ups give slow rising edges; too-small ones exceed the drivers' sink current.

Anatomy of a transaction

Every transfer follows the same pattern:

Speed modes and clock stretching

Standard mode 100 kHz, Fast 400 kHz, Fast-mode Plus 1 MHz, High-speed 3.4 MHz. A slow slave may hold SCL low (clock stretching) until it is ready — the master must wait, and some MCU implementations handle this poorly. Data rate is modest: a 2-byte register read at 400 kHz takes ~100 µs.

Robustness in real products

Address conflicts (two identical sensors) are solved with address pins, I²C multiplexers (TCA9548A) or separate buses. Long cables and many devices raise capacitance above the 400 pF limit — use bus buffers/extenders (P82B715). Implement timeouts on every transaction, the 9-clock recovery procedure, and SMBus features (PEC CRC, alert line) for power-management devices. For multi-master systems, arbitration happens bit by bit: the master that sends a 1 but reads a 0 loses and backs off.

Formulas

Worked example: Address byte

Given: 7-bit address 0x48

Find: Bytes for write and read.

Answer: Write 0x90, read 0x91

Worked example: Pull-up range

Given: 3.3 V, 400 kHz, C_b = 200 pF

Find: R_p limits.

Answer: Use ≈ 1.2–1.5 kΩ

Worked example: Temperature conversion

Given: TMP102 returns 0x19 0x00

Find: Temperature.

Answer: 25.0 °C

Reading a temperature sensor register (TMP102-style) with HAL

#define TMP102_ADDR   (0x48u << 1)      /* HAL expects the 8-bit (shifted) address */
#define REG_TEMP      0x00u

int16_t tmp102_read_centi(void)
{
    uint8_t buf[2];
    /* START, 0x90 (W), reg 0x00, REPEATED START, 0x91 (R), 2 bytes, NACK, STOP */
    if (HAL_I2C_Mem_Read(&hi2c1, TMP102_ADDR, REG_TEMP, I2C_MEMADD_SIZE_8BIT,
                         buf, 2, 10) != HAL_OK) {
        return INT16_MIN;                   /* caller handles the error      */
    }
    int16_t raw = (int16_t)((buf[0] << 8) | buf[1]) >> 4;   /* 12-bit, signed */
    return (int16_t)(raw * 625 / 100);      /* 0.0625 C/LSB -> centi-degrees */
}
/* Example: bytes 0x19 0x00 -> raw 0x190 = 400 -> 2500 = 25.00 C */

The repeated start keeps bus ownership between the register write and the read. Integer maths (×625/100) avoids floating point. Always check the return status — a missing ACK usually means wrong address or wiring.

Bus recovery when a slave holds SDA low

void i2c_bus_recover(void)
{
    gpio_config_open_drain(SCL); gpio_config_open_drain(SDA);
    for (int i = 0; i < 9 && !gpio_read(SDA); i++) {   /* clock out the stuck byte */
        gpio_write(SCL, 0); delay_us(5);
        gpio_write(SCL, 1); delay_us(5);
    }
    gpio_write(SDA, 0); delay_us(5);                    /* generate a STOP:      */
    gpio_write(SCL, 1); delay_us(5);                    /* SDA low -> high while */
    gpio_write(SDA, 1); delay_us(5);                    /* SCL is high           */
    i2c_peripheral_reinit();
}

If the MCU resets mid-read, a slave may still be driving a 0 bit and SDA stays low forever. Toggling SCL up to 9 times lets it finish its byte; then a STOP resets the bus state machine.

Common mistakes

Applications

Key takeaways

Going further