systemref

I2C Protocol — Timing, Addressing, and Bus Errors

H. Maqsood Aug 25, 2026 4 min read i2c embedded
I2C is a two-wire synchronous protocol. The bus idles high. A master drives START, clocks data bits on SCL, then drives STOP. Most integration failures are caused by missing pull-ups, address conflicts, or clock stretching the master cannot handle.

I2C uses two lines: SCL (clock) and SDA (data). Both are open-drain — devices can only pull low; they release to high via pull-up resistors. The master generates the clock. A slave can hold SCL low (clock stretch) to buy time. No slave can transmit without being addressed by a master.

The bus is slow (100kHz standard, 400kHz fast mode, 1MHz+ fast-mode plus) and not suitable for high-bandwidth streaming. It is suited for configuration registers, low-rate sensors, and EEPROMs.


Transaction structure

S   ADDR(7)  R/W  A   DATA(8)  A   DATA(8)  A/N   P
│   ───────  ───  │   ───────  │   ───────  ─── │
START                ACK                   NACK  STOP
  • S (START): SDA falls while SCL is high — master-generated
  • ADDR: 7-bit address, sent MSB first
  • R/W: 0 = write, 1 = read
  • A (ACK): slave pulls SDA low on the 9th clock pulse to confirm receipt
  • N (NACK): SDA stays high — no device responded, or device is signaling an error
  • P (STOP): SDA rises while SCL is high — master-generated

Data bits are sampled on the rising edge of SCL. SDA must not change while SCL is high, except to generate START and STOP conditions.


Pull-up resistor sizing

Both lines require pull-up resistors to VCC. The pull-up value controls rise time. Too high and the line rises too slowly for the operating frequency. Too low and bus capacitance draws excessive current.

A practical formula for maximum pull-up resistance at standard speed:

R_max = (VCC × t_rise) / (0.8473 × C_bus)

At 3.3V, 100kHz, 100pF bus capacitance:
R_max = (3.3 × 1000ns) / (0.8473 × 100pF) ≈ 39kΩ

Typical values:

Speed Capacitance Recommended R
100kHz ≤50pF 10kΩ
100kHz ≤400pF 2.2kΩ
400kHz ≤100pF 2.2kΩ
400kHz ≤400pF 680Ω

Most I2C integration failures on breadboards use the default 10kΩ resistors at 400kHz with long wires. Scope SCL and SDA. If the rising edge is a slow ramp rather than a sharp rise, the pull-up is too weak for the operating speed and capacitance.


7-bit addressing

The 7-bit address space supports 128 addresses, of which 16 are reserved. Usable space: 112 device addresses. The address byte transmitted on the bus is ADDR[6:0] << 1 | R/W.

An address collision — two devices at the same address on one bus — produces a bus contention fault. Both attempt to ACK simultaneously; the master sees a valid ACK but reads corrupted data. This fails silently in software.

Most sensor ICs expose one or two address-select pins (ADDR, ADR, SA0) that set the LSBs of the address. This allows two to four instances on one bus:

// Example: BMP280 at two addresses
#define BMP280_ADDR_LOW   0x76  // ADDR pin = GND
#define BMP280_ADDR_HIGH  0x77  // ADDR pin = VCC

If you need more than four identical sensors on one bus, use a TCA9548A I2C multiplexer — eight channels, software-selectable.


Write and read transactions in C (HAL)

// Write: send register address + data byte
uint8_t buf[2] = { REG_CONFIG, 0x1A };
HAL_I2C_Master_Transmit(&hi2c1, DEVICE_ADDR << 1, buf, 2, HAL_MAX_DELAY);

// Read: write register address, then read data
uint8_t reg = REG_TEMP_MSB;
uint8_t data[2];
HAL_I2C_Master_Transmit(&hi2c1, DEVICE_ADDR << 1, &reg, 1, HAL_MAX_DELAY);
HAL_I2C_Master_Receive(&hi2c1, (DEVICE_ADDR << 1) | 0x01, data, 2, HAL_MAX_DELAY);

The read sequence is a repeated START: the master writes the register address, then issues another START (not a STOP) before switching to read mode. Most HAL implementations handle this in HAL_I2C_Mem_Read:

HAL_I2C_Mem_Read(&hi2c1, DEVICE_ADDR << 1, REG_TEMP_MSB,
                 I2C_MEMADD_SIZE_8BIT, data, 2, HAL_MAX_DELAY);

Common failure modes

Bus stuck low: A power cut mid-transaction can leave the slave holding SDA low. The master sees the bus as permanently busy. Recovery: toggle SCL nine times manually to clock out the slave's state, then issue a STOP. Some MCU HAL drivers implement HAL_I2C_DeInit + HAL_I2C_Init to reset the peripheral — this does not fix a stuck slave. Toggle the clock in GPIO mode.

NACK on valid address: The device is not ready (still initializing, or power ramp-up incomplete). Add a startup delay. Most sensors specify a power-on reset time (POR) in the datasheet, typically 1–10ms after VCC reaches the operating voltage.

Clock stretching timeout: The slave holds SCL low longer than the master's timeout. Increase the master timeout or check whether the slave requires a delay between the address byte and the first data byte (some EEPROMs do — the datasheet will say "acknowledge polling").