liminfo

I2C Reference

Free reference guide: I2C Reference

25 results

About I2C Reference

The I2C Reference is a searchable quick-reference for the I2C (Inter-Integrated Circuit) two-wire serial communication protocol. It covers six practical categories — Basics, Addressing, Read, Write, Multi-Master, and Debugging — giving embedded systems engineers, firmware developers, and electronics hobbyists instant access to the protocol details, C code patterns, and diagnostic commands they need when working with I2C sensors, EEPROMs, and peripherals.

Firmware engineers use this reference to recall the exact timing relationships for START and STOP conditions on SDA and SCL lines, the ACK/NACK handshake on the 9th clock cycle, 7-bit address frame format with the R/W bit, and the procedure for single-byte and multi-byte (burst) register reads using Repeated START. Platform-specific patterns are included for STM32 HAL (HAL_I2C_Mem_Read, HAL_I2C_Mem_Write) and Arduino Wire library (Wire.beginTransmission, Wire.requestFrom). The reference also covers EEPROM page write boundaries for devices like the AT24C256.

The Debugging category is particularly valuable for hardware bring-up: it covers bus recovery when SDA is stuck LOW by toggling SCL 9 times, pull-up resistor selection (4.7k for 400kHz, 10k for 100kHz on 3.3V systems), Linux i2c-tools commands (i2cdetect, i2cget, i2cset, i2cdump), logic analyzer checkpoints for verifying address bytes and ACK pulses, and Clock Stretching behavior that some masters do not support.

Key Features

  • I2C bus fundamentals: SDA/SCL open-drain wiring, pull-up resistor requirements, Standard/Fast/Fast+/HS speed modes
  • START and STOP condition timing: SDA edge direction relative to SCL HIGH, C code examples for bit-banging
  • ACK/NACK protocol: 9th clock bit, receiver holds SDA LOW for ACK, master sends NACK after last read byte
  • 7-bit addressing (0x08–0x77, 112 devices) and 10-bit extended addressing (up to 1024 devices) with General Call (0x00)
  • Read procedures: single byte, multi-byte burst read with auto-increment, STM32 HAL_I2C_Mem_Read, Arduino Wire.requestFrom
  • Write procedures: single byte, burst write, STM32 HAL_I2C_Mem_Write, Arduino Wire.beginTransmission, EEPROM page write
  • Multi-master: arbitration via SDA comparison, Clock Stretching for slave processing time, Repeated START bus ownership
  • Debugging: bus recovery with 9 SCL toggles, pull-up resistor calculation, i2cdetect/i2cget/i2cset/i2cdump commands

Frequently Asked Questions

What is I2C and how does it work?

I2C (Inter-Integrated Circuit) is a synchronous, multi-master, multi-slave, two-wire serial communication protocol. It uses SDA (Serial Data) and SCL (Serial Clock) lines, both requiring pull-up resistors to VDD. The master generates the clock and initiates all transfers. Communication begins with a START condition (SDA falls while SCL is HIGH), proceeds with address and data bytes each acknowledged by the receiver, and ends with a STOP condition (SDA rises while SCL is HIGH).

What pull-up resistor value should I use for I2C?

The optimal pull-up resistor depends on bus speed and bus capacitance. For Standard Mode (100kHz) at 3.3V, 10kΩ is typical. For Fast Mode (400kHz) at 3.3V, 4.7kΩ is recommended. For Fast Mode Plus (1MHz), 2.2kΩ or lower may be needed. The minimum resistor is (VDD - VOL) / IOL — at 3.3V with 3mA sink current this gives about 967Ω. Too high a value slows rise times and causes communication errors at higher speeds.

What is the difference between a single byte read and a burst (multi-byte) read?

A single byte read sends START, the device address + W bit, the register address, then a Repeated START followed by the device address + R bit, reads one byte, sends NACK, and STOP. A burst read is identical but instead of NACK after the first byte, the master sends ACK to request more bytes — the device auto-increments the register pointer. This is essential for reading multi-byte values like accelerometer XYZ data (6 bytes) in a single transaction.

What is Clock Stretching in I2C?

Clock Stretching allows a slave device to hold the SCL line LOW after the master releases it, effectively pausing the communication until the slave is ready to send or receive the next byte. This is used when the slave needs extra time to process data (e.g., performing an ADC conversion). Not all I2C masters support Clock Stretching — check the master's datasheet. If it is not supported, the slave must be fast enough to respond within the master's timing window.

How do I scan for I2C device addresses on Linux?

Install i2c-tools and run sudo i2cdetect -y 1 (replace 1 with your I2C bus number). The command scans the bus and prints a grid showing addresses where devices respond with ACK. Addresses appear as hex values; dashes (--) indicate no device. To read a register: sudo i2cget -y 1 0x48 0x00 w. To write a register: sudo i2cset -y 1 0x48 0x01 0x60. To dump all registers: sudo i2cdump -y 1 0x48.

How does I2C multi-master arbitration work?

When two masters attempt to start a transfer simultaneously, arbitration resolves the conflict bit by bit on the SDA line. Each master monitors SDA while transmitting — if a master drives SDA HIGH but reads it as LOW, another master is driving it LOW and wins the arbitration. The losing master immediately stops transmitting and waits. This works because I2C SDA is open-drain: any master can pull it LOW, but none can drive it HIGH against another pulling LOW.

How do I recover from an I2C bus lockup (SDA stuck LOW)?

A bus lockup occurs when a slave is mid-transfer during a power cycle and holds SDA LOW indefinitely. Recovery procedure: set SCL as output and toggle it HIGH/LOW 9 times — this clocks out the remaining bits in the slave's shift register. Then generate a STOP condition (drive SDA LOW, then SCL HIGH, then SDA HIGH). If the slave's firmware supports software reset, send a General Call Reset (0x00, 0x06) after recovery.

What is the EEPROM page write limit and why does it matter?

Serial EEPROMs (like the AT24C256) are internally organized into pages of fixed size (e.g., 64 bytes for AT24C256). A write that crosses a page boundary wraps around to the beginning of the same page rather than advancing to the next page, corrupting data. When writing more than one page, you must split the write at page boundaries and insert the required write cycle delay (typically 5ms for 24-series EEPROMs) between each page write.