← all lessons
Microcontrollers · #11 of 20

I²C Communication

Addressing, ACK/NAK, Clock Stretching

Why it matters

I²C lets you connect many peripherals (IMUs, OLEDs, environmental sensors) using only two wires.

The idea

The core idea

I²C (Inter-Integrated Circuit) is a two-wire bus protocol that lets you connect many devices to a microcontroller: Both lines are open-drain and require pull-up resistors (typically 2.2kΩ–10kΩ) to 3.3V.
        <h3>Why Open-Drain?</h3>
        Open-drain means devices can only pull the line LOW, never HIGH. The pull-up resistor pulls it HIGH when no device is pulling LOW.
        This allows multiple devices to share the same bus safely:
        <ul>
          <li>Any device can pull the line LOW (wired-AND logic)</li>
          <li>If one device pulls LOW, the whole bus goes LOW</li>
          <li>All devices must release for the bus to go HIGH</li>
          <li>No conflicts — devices can't fight over the bus</li>
        </ul>

        <h3>Addressing: How Devices Are Selected</h3>
        Each I²C device has a unique 7-bit address (0x08 to 0x77). The master sends the address first:
        <ul>
          <li>7 address bits identify the device</li>
          <li>1 R/W bit: 0 = write (master→slave), 1 = read (slave→master)</li>
          <li>Combined into one 8-bit byte on the wire</li>
        </ul>
        Example: Address 0x3C (0b0111100) + Write (0) = byte 0x78 (0b01111000)

        <h3>Protocol Flow</h3>
        <div class=

Demo

Top line is SCL, bottom is SDA. Watch for:

Key takeaways

Going deeper

Troubleshooting I²C Issues

        <h4>Address Scanning</h4>
        Scan addresses 0x08–0x77: send START + address + R/W, check for ACK.
        This identifies all devices on the bus — essential for debugging.

        <h4>Pull-up Resistor Selection</h4>
        <ul>
          <li>Too weak (high resistance): Bus rises slowly, limits speed</li>
          <li>Too strong (low resistance): High current when pulled LOW, wastes power</li>
          <li>Sweet spot: 2.2kΩ–10kΩ for 3.3V (depends on bus capacitance)</li>
          <li>Long wires need stronger pull-ups (lower resistance)</li>
        </ul>

        <h4>Reading vs Writing</h4>
        <ul>
          <li><strong>Write</strong>: Master sends data bytes, slave ACKs each</li>
          <li><strong>Read</strong>: Master sends address+R, slave sends data, master ACKs (or NACKs last byte)</li>
          <li>Some devices need register writes before reads (e.g.,

Math details

I²C frame (write, 7-bit address):
  START
  [A6 A5 A4 A3 A2 A1 A0 W]
  ACK
  [D7 D6 D5 D4 D3 D2 D1 D0]
  ACK
  STOP

Implementation

LLM Prompt: I²C Sensor Reading