Skip to content

I2C通信协议

I2C协议简介

I2C(Inter-Integrated Circuit)是一种串行通信协议,用于在微控制器和其他数字设备之间进行通信。I2C协议支持多主多从通信,允许多个设备通过一条数据线(SDA)和一条时钟线(SCL)进行通信。

1. I2C协议特点

  1. 多主多从:I2C协议支持多主多从通信,允许多个主设备和一个或多个从设备同时进行通信。
  2. 串行通信:I2C协议采用串行通信方式,数据在SDA线上按位传输。
  3. 半双工:I2C协议是半双工通信,即每个设备只能在发送或接收数据时使用SDA和SCL。
  4. 低功耗:I2C协议具有低功耗特性,适用于低功耗应用。
  5. 简单:I2C协议简单易用,易于实现和调试。

2. I2C协议工作原理

I2C协议的工作原理如下:

  1. 起始信号:当主设备需要与从设备通信时,它会发送一个起始信号。起始信号由主设备在SCL线上拉低,然后在SDA线上拉高。
  2. 地址信号:主设备发送从设备的地址,地址由7位(包括读写位)或是 10位(包括读写位) 组成。主设备发送地址后,从设备会根据地址判断是否响应。
  3. 数据传输:主设备发送数据或从设备发送数据。数据在SDA线上按位传输,每个位在SCL线上的上升沿或下降沿采样。
  4. 应答信号:从设备在接收完数据后,会发送一个应答信号。应答信号由从设备在SCL线上拉低,然后在SDA线上拉高。
  5. 停止信号:当主设备完成数据传输后,它会发送一个停止信号。停止信号由主设备在SCL线上拉低,然后在SDA线上拉高。

I2C协议的程序实现

  1. 创建一个 Bus 总线 : i2c_new_master_bus 生成一个 bus_handle
  2. 添加一个设备 : i2c_master_bus_add_device 生成一个 dev_handle
  3. 读写数据 : i2c_master_transmit_receive

I2C协议的程序代码

1. 创建一个 Bus 总线

c
#include "driver/i2c_master.h"

i2c_master_bus_config_t i2c_mst_config = {
    .clk_source = I2C_CLK_SRC_DEFAULT,
    .i2c_port = TEST_I2C_PORT,
    .scl_io_num = I2C_MASTER_SCL_IO,
    .sda_io_num = I2C_MASTER_SDA_IO,
    .glitch_ignore_cnt = 7,
    .flags.enable_internal_pullup = true,
};

i2c_master_bus_handle_t bus_handle;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));

i2c_device_config_t dev_cfg = {
    .dev_addr_length = I2C_ADDR_BIT_LEN_7,
    .device_address = 0x58,
    .scl_speed_hz = 100000,
};

i2c_master_dev_handle_t dev_handle;
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));

2. 主机只写入数据

i2c_master_write_slave

c
i2c_master_transmit(dev_handle, data_wr, DATA_LENGTH, -1)

I2C 主机写入操作还支持在单次传输事务中传输多个 buffer

c
i2c_master_transmit_multi_buffer_info_t lcd_i2c_buffer[3] = {
    {.write_buffer = &control_phase_byte, .buffer_size = control_phase_size},
    {.write_buffer = cmd_buffer, .buffer_size = cmd_buffer_size},
    {.write_buffer = lcd_buffer, .buffer_size = lcd_buffer_size},
};

i2c_master_multi_buffer_transmit(handle, lcd_i2c_buffer, sizeof(lcd_i2c_buffer) / sizeof(i2c_master_transmit_multi_buffer_info_t), -1);

2. 主机只读取数据

i2c_master_read_slave

c
i2c_master_receive(dev_handle, data_rd, DATA_LENGTH, -1);

2. 写入命令并返回读取数据

i2c_master_transmit_receive

c
i2c_master_transmit_receive(dev_handle, 0x58, &write_data, 1, &read_data, 1, 1000 / portTICK_PERIOD_MS);