I2C
Sample List
This chapter introduces the details of the I2C sample code. The SDK provides the following samples for the I2C peripheral.
Functional Overview
The I2C bus is a two-wire serial interface, consisting of a serial data line (SDA) and a serial clock (SCL). These wires carry information between the devices connected to the bus. Each device is recognized by a unique address and can operate as either a transmitter or receiver, depending on the function of the device. Devices can also be considered masters or slaves when performing data transfers. A master is a device that initiates a data transfer on the bus and generates the clock signals to permit that transfer. At that time, any device addressed is considered a slave.
Feature List
Up to 3 I2C.
Two-wire I2C serial interface: consists of a serial data line (SDA) and a serial clock (SCL).
Support master and slave mode.
Support 7/10-bit addressing mode.
Support standard mode (0 to 100Kb/s), fast mode (less than or equal to 400Kb/s) and fast mode plus (less than or equal to 1000Kb/s).
Support 40MHz clock source.
Interrupt or polling mode operation.
Transmit FIFO depth: 24.
Receive FIFO depth: 40.
Support GDMA transfer.
Block Diagram
Here is the overall IPs block diagram for I2C IP¹, which including ‘PAD/PINMUX’ for IO function configuration, ‘I2C IP’ for I2C protocol, ‘GPIO IP’ for interrupt handler and ‘DMAC IP’ for GDMA access.

System Block Diagram of I2C
Transfer Protocol
Each byte sent on the SDA line must be 8 bits. There is no limit to the number of bytes that can be sent per transfer, and each byte must be followed by a response bit. The most significant bit (MSB) of the data is transmitted first. If the slave needs to complete some other functions, such as an internal interrupt service routine, it can receive or send the next complete data byte. The clock line SCL can be kept low to force the master to enter the wait state. When the slave is ready to receive the next data byte and release the clock line SCL, the data transfer continues.

Schematic Diagram of I2C Transmission Protocol
Master Mode
The I2C master device supports the following communication modes: master write, master read, and master repeat read.
Users can set the I2C device mode to master mode by setting the parameters I2C_InitTypeDef::I2C_DeviveMode
to I2C_DeviveMode_Master
, and set to I2C_DeviveMode_Slave
for slave mode.
The communication timing for the above three modes will be introduced below in both 7-bit and 10-bit address mode.
7-Bit Addressing Mode
Users can set the I2C master to target to a 7-bits address slave mode by setting the parameters I2C_InitTypeDef::I2C_AddressMode
to I2CAddressMode_TypeDef::I2C_AddressMode_7BIT
.
Master Write
The API I2C_MasterWrite()
implement the I2C master write data function in polling mode.
Master-transmitter transmits to slave-receiver with a 7-bit slave address. The transfer direction is not changed. All data is transmitted in byte format, with no limit on the number of bytes transferred per data transfer. After the master sends the address and read/write bit or the master transmits a byte of data to the slave, the slave-receiver must respond with the acknowledge signal. When a slave-receiver does not respond with an ACK pulse, the master aborts the transfer by issuing a stop condition. The slave must leave the SDA line high so that the master can abort the transfer.

Master Write in 7-Bit Addressing Mode
Master Read
The API I2C_MasterRead()
implement the I2C master read data function in polling mode.
In the first response, master-transmitter becomes master-receiver, and slave-receiver becomes slave-transmitter, and the first response is still generated by the slave. If the master is receiving data, the master responds to the slave-transmitter with an acknowledge pulse after a byte of data has been received, except for the last byte. This (NACK) is the way the master-receiver notifies the slave-transmitter that this is the last byte. The slave-transmitter relinquishes the SDA line after detecting the no acknowledge (NACK) so that the master can issue a stop condition.

Master Read in 7-Bit Addressing Mode
Master Repeat Read
The API I2C_RepeatRead()
implement the I2C master write and then read data function in polling mode.
When performing a write-before-read operation, both the start condition and the slave address are sent repeatedly, but the read/write bit is reversed.

Master Repeat Read in 7-Bit Addressing Mode
10-Bit Addressing Mode
Users can set the I2C master to target to a 10-bits address slave mode by setting the parameters I2C_InitTypeDef::I2C_AddressMode
to I2CAddressMode_TypeDef::I2C_AddressMode_10BIT
.
Master Write
The API I2C_MasterWrite()
implement the I2C master write data function in polling mode.
Master-transmitter transmits to slave-receiver with a 10-bit slave address. The transfer direction is not changed.

Master Write in 10-Bit Addressing Mode
Master Read
The API I2C_MasterRead()
implement the I2C master read data function in polling mode.
Master-transmitter transmits to slave-receiver with a 10-bit slave address. The transfer direction is changed after the second read/write bit, master-transmitter becomes master-receiver, and slave-receiver becomes slave-transmitter.

Master Read in 10-Bit Addressing Mode
Master Repeat Read
The API I2C_RepeatRead()
implement the I2C master write and then read data function in polling mode.
The master sends data to the slave and then reads data from the same slave. The transfer direction is changed after the second read/write bit.

Master Repeat Read in 10-Bit Addressing Mode
Power Manager
The I2C peripheral is located in the core domain and will be powered off in low power mode.
I2C peripheral store/restore will be automatically performed based on whether the I2C clock is active.
Users can call the API io_dlps_register()
to initialize I2C peripheral store/restore and do not need to worry about I2C peripheral requiring specific handling.
Troubleshooting
How to Debug the SCL Frequency Not Matched Issue?
The I2C clock speed is related to the SCL rising time, which is affected by the pull-up resistor and capacitor. Users can configure the variable I2C_InitTypeDef::I2C_RisingTimeNs
to calibrate the I2C clock speed. The default value of I2C_InitTypeDef::I2C_RisingTimeNs
for RTL87x3D is 100, and the default value of I2C_InitTypeDef::I2C_RisingTimeNs
for RTL87x3E and RTL87x3EP is 50. The following example demonstrates the calibration method of the I2C clock speed, taking the I2C source clock as 40MHz, the I2C clock speed as 400KHz, and the I2C_InitTypeDef::I2C_RisingTimeNs
as 100.
Set the variable
I2C_InitTypeDef::I2C_RisingTimeNs
to 100.Measure the I2C clock speed. For example, if the actual frequency measured is 411KHz, the period is: 1/411KHz = 2433 ns.
Calculate the actual value of
I2C_InitTypeDef::I2C_RisingTimeNs
.SCL Low Time = SCL Low Period - SCL Falling Time + SCL Rising Time
SCL High Time = SCL High Period + SCL Falling Time
SCL Frequency = 1 / (SCL High Time + SCL Low Time)
According to the formulas a to c, SCL Period = SCL Low Period + SCL High Period + SCL Rising Time
SCL Low Period (ns) + SCL High Period (ns) = SCL Period (ns) -
I2C_InitTypeDef::I2C_RisingTimeNs
configured in the APP = 2500 - 100 = 2400Actual
I2C_InitTypeDef::I2C_RisingTimeNs
= Actual period - (SCL Low Period + SCL High Period) = 2433 - 2400 = 33Because the clock source of I2C is set to 40MHz, the precision of the I2C clock is 25ns. So the setting
I2C_InitTypeDef::I2C_RisingTimeNs
needs to be aligned to 25ns.