The I2C communication protocol operates in half-duplex synchronous mode, enabling connectivity between MCUs and secondary modules such as OLED displays, Electronically Erasable Programmable Read- Only Memory (EEPROM), compasses, etc. Figure 1 represents a typical I2C bus, where there is a master module, a slave module, a Serial Clock Line (SCL) to establish synchronicity between the master and slave, a Serial Data Line (SDA) to transmit messages between the master and slave, and a pull-up resistor (Rp) on SCL and SDA.

To use the I2C communication protocol, both the master and slave must be I2C enabled. The arrowhead on the SCL line indicates that the master controls the timing for communication, while the double-arrowhead on the SDA line indicates that data can be sent either from the master to the slave or from the slave to the master, but one at a time.
Figures 2 to 7 represent an example of I2C communication between a master (MCU) module and a slave (Compass-HMC6352) module.

- Idle: Before I2C communication takes place, both SCL and SDA lines remain pulled HIGH by the pull-up resistors, implying that the system is Active-LOW.
- START condition: The master issues a START condition marking the beginning of communication, where both SCL and SDA lines are pulled LOW. Note that the SDA line is pulled LOW before the SCL line is pulled LOW.
- D7 to D0: Bits D7 to D1, as shown in Figure 3, represent the slave’s 7-bit address, 0b0100001. The slave has only one possible address, as per the manufacturer datasheet, and thus cannot be customised. All I2C slaves have a 7-bit address, which is either fixed or customisable by tying certain pins of a slave to either the power rail HIGH (1) or to ground LOW (0). Note that more than one slave can be multiplexed to a master on the SCL and SDA lines; however, each slave address must be unique to avoid data collision. Based on the 7-bit address standard, a total of up to 127 slaves can be multiplexed to a master; however, too many slaves easily result in an increased parasitic inductance/capacitance on the bus. Bits D7 to D0 represent the control byte and are transmitted from the master to the slave, corresponding to the clock pulses. Note that the MSB (D7) is transmitted first, while the LSB (D0) is transmitted last. The LSB represents the Write/Read bit, which indicates if the master will Write (0) a command to or Read (1) data from the slave.

- ACK: The slave responds with an acknowledge ACK bit once it has received the control byte containing its address. Note that the master must transmit the correct slave’s address; otherwise, the slave, intended to receive a message, will not respond with an ACK. Slave addresses must be unique, as data collision can easily occur when two or more slaves, with the same address, respond to a master at a similar time.

- command byte: The master transmits the command byte, 0b01000001, as per the manufacturer data sheet of the slave, to start taking measurements.
- ACK: The slave responds with an ACK bit.

- Idle: Momentarily the SCL and SDA lines are pulled HIGH by the pull-up resistors.
- Repeated START condition: A new START condition is established, rather than stopping and starting the I2C module.
- D7 to D0: The slave’s address is transmitted once again, however, followed by a Read (1) bit.
- ACK: The slave responds with an ACK bit.

- MSB: The MSB of the acquired data from the slave is transmitted to the master.
- ACK: The master responds with an ACK bit.

- LS byte: The LSB of the acquired data from the slave is transmitted to the master.
- NACK: The master responds with a NACK bit.
- STOP: The master issues a STOP condition marking the end of communication, where both SCL and SDA lines are pulled HIGH by the pull-up resistors. Note that the SCL line is pulled HIGH before the SDA line is pulled HIGH.
- Idle: Following an I2C communication event, both SCL and SDA lines remain pulled HIGH by the pull-up resistors.
Note that for some I2C-enalbed modules, the master is only required to transmit commands, such as OLED displays. In such a case, the master does not read data byte(s) from the slave, which in turn means that the master does not transmit an ACK/NACK bit. In other words, at the end of data transmission, the master only transmits a STOP condition.