I2c
I2C, short for Inter-Integrated Circuit and pronounced "I-squared-C," is a two-wire serial communication protocol developed by Philips in 1982, letting multiple chips on the same board talk to each other over just two shared signal lines — one carrying data, one carrying a clock — regardless of how many separate devices are connected to those same two wires. That two-wire efficiency is the entire reason I2C became so widely adopted: a microcontroller can address dozens of separate sensors, memory chips, and peripheral devices using the same pair of physical wires the whole time, rather than needing a dedicated set of wires running to every single device. How I2C actually lets multiple devices share just two wires without talking over each other looks like this:
A few things are worth knowing about why I2C's shared, two-wire design needs some clever electrical tricks to actually work safely:
Both I2C signal lines use open-drain outputs with pull-up resistors rather than devices directly driving the lines high and low, and that specific electrical choice is exactly what lets many devices share the same two wires without ever risking a damaging short circuit between them. An open-drain output can only actively pull its line toward ground or release it entirely — it can never actively drive the line high — so a pull-up resistor on each line does the job of pulling it back up whenever every connected device has released it. Because no device can ever actively drive a line high while another drives it low, two devices disagreeing about the line's state simply results in the line being pulled low, not a direct, damaging conflict between two actively opposing drivers, exactly the kind of wiring safety a shared bus with many participants genuinely needs.
Each I2C device on the bus answers to its own unique address, typically 7 bits long giving up to 127 possible device addresses, and this addressing scheme is exactly what lets a controller talk to one specific device out of many without any of the others interfering. Every transaction begins with the controller broadcasting a target address on the shared data line, and every connected device compares that broadcast address against its own fixed or configurable address — only the one device whose address matches responds by acknowledging, while every other device recognizes the mismatch and stays completely silent for the rest of that transaction. This is exactly why a single microcontroller can manage an entire collection of sensors, memory chips, and peripheral devices over the same pair of wires: the shared bus itself never changes, only which address gets targeted changes from one transaction to the next.
I2C's clock-stretching capability lets a slower device deliberately pause an entire transaction by holding the clock line low, which is a genuinely unusual feature among serial protocols and exists specifically to accommodate devices that can't always keep pace with the controller's requested clock speed. Normally the controller alone generates and controls the clock signal, but I2C's open-drain clock line means any device can also pull it low if needed — a slower peripheral that needs extra time to prepare a response can hold the clock line low, which the controller is required to recognize and simply wait out before continuing, effectively letting the slower device dictate a temporary pause in the transaction's pace. This flow-control mechanism is unusual among common serial protocols and is exactly what lets I2C accommodate a genuinely diverse mix of fast and slow devices sharing the identical bus without needing to pre-negotiate a single compromise speed that works for every device simultaneously.
I2C's flexibility and low pin count come at a real cost in both maximum speed and practical bus length, which is exactly why faster or longer-distance applications typically reach for a different protocol entirely rather than pushing I2C beyond what it was designed for. Standard I2C tops out around 100 kilohertz to 400 kilohertz in its common modes, with faster variants reaching several megahertz under more demanding electrical conditions, but even the fastest I2C variants fall well short of what protocols like SPI can achieve, and I2C's pull-up-resistor-based electrical design limits practical bus length and the number of devices that can reliably share one bus before signal integrity degrades. This tradeoff — low pin count and flexible multi-device addressing in exchange for comparatively modest speed and limited reach — is precisely why I2C dominates low-speed sensor and configuration interfaces inside a single board, while higher-speed or longer-distance applications reach for SPI, UART, or other protocols better suited to those specific different demands.
Read I2C as an addressed, shared-bus protocol built around electrical safety, not just a generic two-wire serial link: open-drain signaling with pull-up resistors is what lets many devices coexist on the same two wires without ever risking a direct electrical conflict, device addressing is what lets a controller pick exactly which one of those many devices to talk to, and clock stretching is the deliberate accommodation that lets genuinely different-speed devices share that same bus — a combination of tradeoffs that makes I2C the standard choice for low-speed, multi-device, single-board communication, not a universal answer for every serial communication need.