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, ®, 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").