How Does the I2C Bus Work With Just Two Open-Drain Lines?
The Inter-Integrated Circuit (I2C) bus enables multiple master and slave devices to communicate over just two bidirectional wires: Serial Data (SDA) and Serial Clock (SCL). By using open-drain drivers paired with pull-up resistors, devices can share the bus without electrical contention, perform wired-AND arbitration, and synchronize data transfers using a structured framing protocol.
Open-Drain Architecture and Wired-AND Logic
In a standard push-pull output, a device actively drives a line both high and low. If two push-pull devices connected to the same wire try to drive opposite logic levels simultaneously, a short circuit occurs. I2C avoids this by requiring every connected device to use an open-drain (or open-collector) output stage.
An open-drain driver can only pull a line down to ground (logic \(0\)) or release it into a high-impedance state. Neither device ever actively drives the line high. Instead, external pull-up resistors connected to the supply voltage (\(V_{DD}\)) passively pull SDA and SCL to a high state (logic \(1\)) whenever all devices release the bus.
This electrical arrangement creates a natural wired-AND behavior:
- If any single device pulls the line low, the entire bus reads \(0\).
- Only when every device releases the line does the pull-up resistor bring the bus to \(1\).
The pull-up resistor value (\(R_p\)) must be chosen carefully to balance rise time against power consumption, governed by the bus capacitance (\(C_b\)):
\[t_r \approx 0.8473 \times R_p \times C_b\]
Framing Communication With Start, Stop, and Addressing
Because all devices share the same two lines, I2C uses specific signal transitions on SDA relative to SCL to mark the beginning and end of a transaction:
- START condition (S): A high-to-low transition on SDA while SCL remains high. Any master can initiate a transfer by issuing a START condition when the bus is idle.
- Data validity: While SCL is high, SDA must remain stable. Data bits on SDA are only allowed to change while SCL is low.
- STOP condition (P): A low-to-high transition on SDA while SCL remains high, releasing the bus back to the idle state.
Immediately after a START condition, the master transmits a 7-bit (or 10-bit) slave address followed by a single Read/Write (\(\text{R}/\overline{\text{W}}\)) bit. Every slave on the bus listens to this address. Only the slave whose address matches responds by pulling SDA low during the 9th clock pulse, which serves as the Acknowledge (ACK) bit. If no slave responds, SDA stays high, signaling a Not Acknowledge (NACK).
Multi-Master Arbitration and Clock Synchronization
I2C supports multiple masters on the same bus without a central arbiter. Two mechanisms make this possible:
Clock Synchronization
If two masters begin transmitting simultaneously, they may have slightly different clock frequencies. When one master pulls SCL low, the wired-AND bus stays low until all masters have released SCL. A master whose low period is shorter will wait in a high-impedance state until the slowest master releases SCL, at which point all masters begin their high period together. Similarly, the first master to pull SCL low again ends the high period for everyone. The resulting clock is a synchronized composite with the longest low period and the shortest high period.
Bus Arbitration
Arbitration happens bit by bit on the SDA line during the address and data phases. Every master monitors SDA while transmitting. If Master A sends a \(1\) (by releasing SDA) while Master B sends a \(0\) (by pulling SDA low), the wired-AND bus reads \(0\). Master A detects that the bus state does not match its intended output, immediately loses arbitration, and switches its SDA driver to high-impedance mode. Master B continues its transfer uninterrupted, unaware that any collision occurred.
Clock Stretching for Flow Control
Slower slave devices can also regulate bus speed using clock stretching. After receiving a byte, a slave that needs extra time to process data can hold SCL low. Because of the open-drain design, the master cannot force SCL high; it must wait until the slave releases SCL before clocking out the next bit. This built-in flow control ensures reliable communication between devices operating at vastly different speeds.