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 Write, Read — Read data from I2C device.

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 requires configuration in the device table, with the clock and data lines configured according to the actual pins used on the Board. Other settings can use the default configurations provided in the SDK.

Note

The SCL and SDA pins for I2C are typically configured with pull-up resistors in the device table by default. Generally speaking, the pull-up resistance for I2C needs to be within a certain range, neither too large nor too small, as determined by the slave devices. This value can be calculated based on the parameters specified in the I2C slave device’s manual.

I2C Address

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

Main Functions

Initialize I2C

Before using I2C, you need to call the wm_drv_i2c_init() function to allocate resources for I2C. Use wm_device_t to specify the device, as shown in the 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 only “i2c0” can be filled in.

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 ways of writing data for two 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.

Here is an 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);

Reading Data

Use the wm_drv_i2c_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.

Here is an example of reading from an EEPROM using the write-then-read method:

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_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