I2C Bus Introduction

Last modified by Microchip on 2023/11/09 08:53

Inter-Integrated Circuit (I2C) is a multi-controller, multi-target, half-duplex synchronous communication protocol over a 2-wire interface.

Advantages

  • Addressable nodes for low pin count requirement.
  • Improved error handling by incorporating ACK/NACK functionality.
  • Supports multiple controllers through bus arbitration.

Disadvantages

  • Increased firmware complexity.
  • Slower throughput due to protocol overhead and half-duplex design.
  • Required pull-up resistors limit clock speed, use extra PCB space, and increase power consumption.
  • Used only over short to medium distances.

The I2C protocol is half-duplex, so information travels in only one direction on the bus at a given time. One clock source is shared between all devices which determines the communication speed. The physical layer of the bus is set up with two wires labeled SDA for serial data and SCL for serial clock. Drivers only pull down the communication lines so pull-up resistors are needed to complete the physical layer. I2C is generally used for short to medium distances and requires less board space due to the reduction of wires needed.

One or more controller devices control who sends data and where. One or more target devices simply wait to be addressed. I2C can be configured to use either 7- or 10-bit addressing, which means it can support up to 128 or 1024 devices on the bus, although you will likely exceed maximum bus capacitance before reaching those limits.

I2C block diagram

The basic structure of a read transaction is a start bit, a control byte, one or more data bytes followed by a stop bit. Each transmission is followed by an acknowledge (ACK) bit or a non-acknowledge (NACK) bit.
Back to top

I2C Bus Operations

I2C read cycle

I2C Read

Let’s review an example of a controller device reading one byte from a target. The bus starts in Idle mode, which means the SDA and SCL are both high. To start the transaction, the controller pulls the SDA link low while SCL is high to send a start bit (S).

This example is based on 7-bit addressing so the controller sends a unique 7-bit target address to identify the required node by controlling the SDA line for each SCK pulse. For a data bit to be valid, the SDA line must remain constant between the rising and falling edge of clock pulses.

The controller then sends a single R/W bit indicating whether data will be read or written to complete the control byte. This is a read operation so this bit will be 1. The target then sends an ACK bit by pulling the SDA line low before the falling edge of the ninth clock pulse.

Having acknowledged the transmission, the target sends the requested data byte across the data line. The controller then acknowledges the received byte and the target starts transmitting the next byte. The controller sends a stop bit (P) by releasing the SDA before SCL to complete the data frame.

I2C read flow chart

Here’s a flowchart for the I2C read operation from the perspective of the controller to better see the process from a software implementation perspective:

Now imagine having tens to hundreds of controllers attempting to control the bus simultaneously! This condition is resolved through “clock arbitration” and is covered by the protocol definition. Essentially, the controller with the earliest dominant low data bit wins control of the bus and the others drop off to try again later.

I2C write timing

Back to top 

I2C Write

An I2C write is very similar. The differences are the R/W bit in the last position of the control byte is 0, data is provided by the controller, ACK/NACKs are provided by the target after each data byte, and a stop bit is sent by the controller to end the transaction.

I2C write flow chart

I2C address

Back to top

I²C Chip Select

The I²C bus selects a destination device by its address. In some cases, a device might have a fixed address, meaning only one device of that type can appear on the bus. However, in most cases, a device's address is determined by its hardware configuration. In the image above, a 24LC256 serial EEPROM is depicted showing its three-chip select pins which correspond to the three address bits in the I²C signal. The address the device will respond to depends on which pins are connected to the positive supply and which pins are connected to the ground.

I2C start stop

Back to top

I²C Start and Stop Conditions

Ordinarily, data on the I²C SDA line is only allowed to change states when the Clock (SCL) line is low. This is because transitions on the SDA line, while the SCL line is high, have special meanings.

Start Condition

A start condition is defined as a transition from high to low on the SDA line while the SCL line is high.

Stop Condition

A stop condition is defined as a transition from low to high on the SDA line while the SCL line is high.

I2C byte write

Back to top

I²C Byte Write

Please put this data at this address.

An I²C byte write is used to write a byte of data to a specific address.

I²C Byte Write

Back to top

EEPROM Byte Write Procedure

  1. Check for bus idle
  2. Send start condition, wait for it to complete
  3. Write control byte (with device address)
  4. Check for bus idle
  5. Write high byte of memory address
  6. Check for bus idle
  7. Write low byte of memory address
  8. Check for bus idle
  9. Write byte of data
  10. Check for bus idle
  11. Send stop condition, wait for it to complete
  12. Wait for the write cycle to complete (ACK from EEPROM)

Example Code (PIC18)

Specific I²C function names and parameters may differ depending on your target device, compiler, and/or peripheral library.

I2C page write

Back to top

I²C Page Write

Get ready to drink from the fire hose.

An I²C page write is used to write a stream of 64 bytes to the device (some devices might have different page sizes).

Back to top

EEPROM Page Write Procedure

  1. Check for bus idle
  2. Send start condition, wait for it to complete
  3. Write control byte (wi device address)
  4. Check for bus idle
  5. Write high byte of memory address
  6. Check for bus idle
  7. Write low byte of memory address
  8. Check for bus idle
  9. Write byte of data
  10. Check for bus idle - go to 9 until 64 bytes written
  11. Send stop condition, wait for it to complete
  12. Wait for the write cycle to complete (ACK from EEPROM)

I2C current address read

Back to top

I²C Current Address Read

Just tell me what you have where you are right now.

I²C current address reads are used to read one byte from the current address. The current address will be one beyond the address that was last acted upon.

Current address read code

Back to top

EEPROM Current Address Read Procedure

  1. Send start condition - wait for it to complete
  2. Send control byte
  3. Check for bus idle
  4. Read in one byte
  5. Send NACK, and wait until ACK sequence complete
  6. Send stop condition - wait for it to complete

Back to top

Example Code (PIC18)

Specific I²C function names and parameters may differ depending on your target device, compiler, and/or peripheral library.

I2C random read

Back to top

I²C Random Read

I want something very specific.

An I²C random read can be used to read a single byte of data from a specific address, or it can be used to move the address pointer for use in a sequential read.

I2C random read code

Back to top

EEPROM Byte Write Procedure

  1. Check for bus idle
  2. Send start condition, wait for it to complete
  3. Write control byte (with device address)
  4. Check for bus idle
  5. Write high byte of memory address
  6. Check for bus idle
  7. Write low byte of memory address
  8. Check for bus idle
  9. Send restart condition - wait for it to complete
  10. Write control byte
  11. Check for bus idle
  12. Read one byte
  13. Send NACK condition - wait for ACK sequence to complete
  14. Send stop condition, wait for it to complete
  15. Wait for the write cycle to complete (ACK from EEPROM)

Back to top

Example Code (PIC18)

Specific I²C function names and parameters may differ depending on your target device, compiler, and/or peripheral library.

The first half is the same as for a byte write while the second half is like a current address read, but with a Repeated Start so the bus doesn't go idle.

A repeated start or restart doesn't return the bus to an idle state, which prevents another Master or Slave from grabbing the bus in the middle of the random read sequence.

I2C sequential read

Back to top

I²C Sequential Read

Start wherever you are and give me all you've got!

An I²C sequential read begins reading at whatever the current address is inside the device. You simply keep reading in bytes (interspersed with idle checks) until you've read enough. To stop the reading, send a NACK and then a STOP condition.

Back to top

EEPROM Sequential Read Procedure

  1. Check for bus idle
  2. Send start condition, wait for it to complete
  3. Write control byte (with device address)
  4. Check for bus idle
  5. Read one byte - go to 4 until you've had enough data
  6. Send NACK condition - wait for ACK sequence to complete
  7. Send stop condition, wait for it to complete

Back to top

Learn More

Back to top