This is the documentation for the latest (main) development branch. If you are looking for the documentation of previous releases, use the drop-down menu on the left and select the desired version.

I2C

Introduction

I2C (Inter-Integrated Circuit) is a simple, bidirectional, two-wire synchronous serial bus. It requires only two lines to transmit information between devices connected to the bus.

I2C is a serial communication bus that uses a multi-master-slave architecture. It was developed by Philips in the 1980s for connecting low-speed peripherals to motherboards, embedded systems, or mobile phones.

The master device initiates data transmission on the bus and generates the clock for data transmission. Any addressed device is considered a slave. The roles of master and slave, transmitter and receiver, are not fixed but depend on the direction of data transmission. If the master sends data to a slave, the master first addresses the slave, then sends data to it, and finally terminates the data transmission. If the master receives data from a slave, the master first addresses the slave, then receives data from it, and finally terminates the reception process. In this case, the master is responsible for generating the clock and terminating data transmission.

Function List

  1. Configuration — Pin and speed configuration.

  2. Initialization — Initialize the driver.

  3. Data Write — Write data to the I2C device.

  4. Data Read — Read data from the I2C device.

  5. Data Write, Read — Write the internal offset address or command to the I2C device, then read data.

Function Overview

Master Device Can only be used as a master controller. Configurable Speed 100KHz to 400KHz. Combined Read and Write Supports I2C read, write offset address or command followed by read, and write offset address or command followed by write data. Multi-Slave Speed Adaptation Supports operation with slaves of different speeds.

Configuration

I2C needs to be configured in the device table, mainly configuring the actual pins used on the board, and the clock and data lines. Other configurations can use the default settings in the SDK.

Note

The SCL and SDA pins of I2C are configured with pull-ups by default in the device table. Generally, the pull-up resistors for I2C should be within a certain range, neither too large nor too small, as determined by the slave device. This can be calculated from the parameters in the I2C slave device manual.

I2C Address

The I2C slave device address used by the driver interface is a 7-bit address, excluding the read/write bit. When calling the read/write interfaces, the underlying driver will left-shift the address by one bit and then OR it with the read/write bit.

Main Functions

Initialize I2C

Before using I2C, call the wm_drv_i2c_init() function to allocate resources for I2C using wm_device_t. Example:

wm_device_t *i2c_dev = wm_dt_get_device_by_name("i2c0");
wm_drv_i2c_init("i2c0");

The first parameter specifies the device name, which is defined in the device table. Currently, there is only one I2C master device, so you can only fill in “i2c0”.

Warning

After initializing I2C, if wm_drv_i2c_deinit is not called, calling wm_drv_i2c_init again will return NULL.

Write

After preparing the data to be sent, call the function wm_drv_i2c_write to send the data to the I2C slave device.

This interface has two write data options, used for two different scenarios:

  • Scenario 1

    Only the register address or command needs to be written. In this case, only the first write data buffer and buffer size are passed, and the data parameter is set to NULL, with data_size set to 0.

  • Scenario 2

    The internal address or command of the slave device needs to be passed. In this case, the first data buffer and buffer size are passed as the internal address or command, and the second parameter data and data_size are passed as the data to be written.

Example of writing to an EEPROM:

wm_device_t *i2c_dev = wm_dt_get_device_by_name("i2c0");

wm_drv_i2c_config_t config = {
    .addr     = 0x50,
    .speed_hz = 400000,
};

uint8_t sub_addr = 5;

/* Write 5 bytes to the EEPROM at offset 5 */
wm_drv_i2c_write(i2c_dev, &config, &sub_addr, 1, "hello", 5);

Read Data

Use the wm_drv_i2c_read function to read data from the I2C slave device. This interface reads data from the I2C slave device.

Example of reading from an EEPROM:

wm_device_t *i2c_dev = wm_dt_get_device_by_name("i2c0");

wm_drv_i2c_config_t config = {
    .addr     = 0x50,
    .speed_hz = 400000,
};

uint8_t sub_addr = 5;
uint8_t buf[5];

/* Read 5 bytes from the EEPROM at offset 5 */
wm_drv_i2c_write(i2c_dev, &config, &sub_addr, 1, NULL, 0);
wm_drv_i2c_read(i2c_dev, &config, buf, 5);

Write-Read Data

Use the wm_drv_i2c_write_read function to read data from the I2C slave device. This interface requires writing the internal address of the slave device, then reading the specified length of data.

Example of using write-read to read from an EEPROM:

wm_device_t *i2c_dev = wm_dt_get_device_by_name("i2c0");

wm_drv_i2c_config_t config = {
    .addr     = 0x50,
    .speed_hz = 400000,
};

uint8_t sub_addr = 5;
uint8_t buf[5];

/* Read 5 bytes from the EEPROM at offset 5 */
wm_drv_i2c_write_read(i2c_dev, &config, &sub_addr, 1, buf, 5);

Precautions

Warning

The address used by I2C is a 7-bit address, excluding the read/write bit. When calling the interfaces, the underlying driver will left-shift the address by one bit and then OR it with the read/write bit.

Application Example

For a basic example of using I2C, please refer to examples/peripheral/i2c

API Reference

To find I2C-related APIs, please refer to:

I2C API Reference