I2C-SPI: Basics (I2C)

Inter-Integrated Circuit (I2C), pronounced “eye squared see,” is a master-slave configuration in which a serial data line (SDA) is shared between the master and all of its slaves. Microcontrollers often use a master-slave configuration, where  one or more master units control the flow of information to and from their slaves. The benefit of the master-slave configuration is that it typically links together multiple units on the same board to one centralized unit. In some sense, it is similar to how several workers can be supervised under one manager. The critical idea is that each slave has a communication link with the master. Thus, the master can call upon any slave at any time and ensure uncorrupted and orderly data transfer. 

As shown in the figure, an I2C bus consists of two wires only: Serial Data (SDA) and Serial Clock (SCL). The masters and slaves are tied together by the shared data bus as well as the shared clock. For simplicity, in this document, we will assume there is only one master, but this is not true for all cases. The general idea in I2C bus is that the master calls upon a specific slave and either reads data from the slave or writes data to it. The master drives the clock, ensuring that all communication between the master and its slaves is synchronous. Given that there is only one data line (one bit), all data is sent serially. Furthermore, only one entity can transmit data at a given time because there is only one line. Thus, I2C communication is half-duplex.

Like with UART, start and stop conditions are necessary to know when communication has started. The start condition is essential for slaves to know when they may need to respond to the master. The stop condition is needed since I2C can support multiple masters, so other masters need to know when the SDA is available.

The start condition is noted as when the master pulls the SDA low while keeping the clock (SCL) high. This signals to the other slaves that a transmission is about to begin. The stop condition, on the other hand, is noted as when the SDA goes from low to high after the SCL goes through the same transition and stays high.

(Source: https://learn.sparkfun.com/tutorials/i2c/all

Once data transmission has begun, data is sampled when the clock is high, and data can be changed when the clock is low. 

Given that multiple slaves can share the SDA, the master needs a way to pick out one slave from the rest. The protocol uses addresses to achieve this. Each slave has its manufacturer-assigned address, and the first thing the master does when starting communication is sending the address of the target slave through the SDA. This way, each slave is listening for their address. If the address is a match, the master needs to know that the target slave has been found. Thus, the slave sends an acknowledgment bit. If the master sees a 0 (ACK) on the SDA when the clock pulses for acknowledgment, then it knows that the slave has received the data. If none of the slaves, acknowledges, that bit remains high and the master knows the communication link is not created.  

When it comes to transmitting data, the master has two options: reading the data from a slave or writing data to it. This is accomplished by sending a read/write bit after the address has been transmitted. So altogether, when communication is started by the master, the master transmits the address of the desired slave, a read/write bit, and then it pulses the clock for an acknowledgment from the slave. The data transmission itself is as simple as sending all the bytes in the package serially, then waiting for an acknowledgment. When all data has been transmitted, the master generates the stop condition to end transmission and free up the SDA.

The acknowledgment bit can be sent by either the slave or the master, depending on the context. The first part of the transmission is always the same: the master sends the address, a read/write bit, and then gets acknowledgment from the slave. When it comes to data transmission, however, who does the acknowledgment depends on whether the transmission is a read or a write. If it is a write, then the master sends data, and the slave acknowledges whether it has received it or not. However, if it is a read, then the slave is sending data to the master instead. If the master sends a 0, then the slave should continue transmitting data. If the master sends a 1 instead, however, then the slave should stop transmitting data.