I2C Basic 示例

[English]

示例说明

本示例展示了如何初始化和配置 I2C 接口,以及如何通过 I2C 主机与 MPU9250 传感器通信,包括读取从机寄存器数据并在完成后释放相关资源。

运行方法

示例完整代码见 I2C Basic Master 示例。运行前的配置说明、对应 GPIO 引脚、构建与烧录流程详见示例目录下的 README.md 文件。

如需自定义配置项及查看默认值,可参考 宏定义说明 部分。

头文件说明

本示例所使用的头文件涵盖了 FreeRTOS 任务管理、日志输出、I2C 驱动以及系统配置等基础模块。为 I2C 初始化、数据读取和资源释放提供支持。

各头文件按功能分类如下:

  1. FreeRTOS 任务调度 :提供任务创建与调度功能。

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
  1. 系统工具 :提供输入输出、系统配置以及日志输出功能。

#include <stdio.h>
#include "sdkconfig.h"
#include "esp_log.h"
  1. I2C 驱动 :提供 I2C 主机模式下的初始化、读写操作及资源释放功能。

#include "driver/i2c_master.h"

宏定义说明

本示例中涉及的宏定义主要用于配置 I2C 主机的引脚、端口号、工作频率及超时时间,同时定义了 MPU9250 传感器的从机地址和关键寄存器地址。

宏定义按功能分类如下:

  1. I2C 主机配置

  • 使用配置宏定义 I2C 时钟线 (SCL) 与数据线 (SDA) 所使用的 GPIO 引脚编号。示例中时钟线对应 GPIO 4;数据线对应 GPIO 5。

#define I2C_MASTER_SCL_IO           CONFIG_I2C_MASTER_SCL
#define I2C_MASTER_SDA_IO           CONFIG_I2C_MASTER_SDA
  • 定义 I2C 使用的端口号,本示例固定使用 I2C_NUM_0

#define I2C_MASTER_NUM              I2C_NUM_0
  • 使用配置宏定义 I2C 主机的时钟频率。示例中时钟频率为 400000 Hz。

#define I2C_MASTER_FREQ_HZ          CONFIG_I2C_MASTER_FREQUENCY
  • 定义主机模式下的发送缓冲区与接收缓冲区。本示例中均禁用(设为 0),因为 I2C 主机无需使用内部缓冲。

#define I2C_MASTER_TX_BUF_DISABLE   0
#define I2C_MASTER_RX_BUF_DISABLE   0
  • 定义超时时间,用于在 I2C 读写操作中限制等待时长,避免总线阻塞,单位为毫秒。

#define I2C_MASTER_TIMEOUT_MS       1000

备注

  • 配置宏以 CONFIG_ 开头,由 ESP-IDF 构建系统根据 menuconfig 设置自动生成,保存在 sdkconfig 文件中。

  • 定义 GPIO 引脚时使用配置宏而非直接写入引脚数字,可以在编译时灵活修改引脚而无需修改源代码,便于项目扩展和管理。

  • 如果想修改使用的引脚,只需修改 menuconfig 并再次构建/编译示例后会自动同步更新,无需手动更改代码。

  • 禁用发送与接收缓冲区有助于节省资源,适用于一般的主机通信场景。

  1. MPU9250 传感器配置

  • 定义 MPU9250 设备的从机地址以及关键寄存器地址,便于后续读写寄存器。

#define MPU9250_SENSOR_ADDR         0x68
#define MPU9250_WHO_AM_I_REG_ADDR   0x75
#define MPU9250_PWR_MGMT_1_REG_ADDR 0x6B
#define MPU9250_RESET_BIT           7

备注

  • 从机设备地址和寄存器地址由具体 I2C 从机型号决定,并非用户自定义。如果使用其他 I2C 从机,需要参考目标器件手册修改对应宏定义。

  • WHO_AM_I 寄存器用于读取传感器芯片 ID,以验证设备是否正常连接。

  • PWR_MGMT_1 寄存器用于电源管理,复位操作可通过设置第 7 位(RESET_BIT)完成。

任务函数说明

本示例为了实现 I2C 主机与 MPU9250 传感器的通信,包含三个核心函数:I2C 主机初始化函数、寄存器读取函数和寄存器写入函数。

I2C 主机初始化函数

i2c_master_init() 用于初始化 I2C 主机并绑定目标设备。

该初始化步骤具有通用性,适用于所有涉及 I2C 外设的场景,仅需根据具体器件修改端口号、从机地址及相关配置参数。具体步骤说明,以及涉及的结构体成员说明,可查看 I2C 初始化 部分。

参数解释

传入参数

参数功能

参数说明

bus_handle

I2C 总线句柄指针

总线成功创建后返回的有效句柄,用于后续对该总线的读写操作。

dev_handle

I2C 设备句柄指针

将设备添加至 I2C 总线后返回的有效设备句柄,用于后续与该设备的通信。

寄存器写入后读取函数

mpu9250_register_read() 用于读取 MPU6050 寄存器地址内容。

参数解释

传入参数

参数功能

参数说明

dev_handle

I2C 设备句柄

将设备添加至 I2C 总线后返回的有效设备句柄,用于指定目标从机设备。

reg_addr

目标寄存器地址

需要读取的目标设备寄存器地址。

data

数据缓冲区指针

用于存放从寄存器中读取的数据,调用函数后数据写入该内存区域。

len

读取字节长度

指定要从寄存器读取的字节数,需保证缓冲区大小足够容纳数据。

该函数通过调用 i2c_master_transmit_receive() 实现寄存器写入后读取,执行逻辑如下:

  1. 将目标寄存器地址作为写入数据发送给 MPU9250,用于指定寄存器并验证设备连接情况,从机应答确认接收成功。

  2. 从机发送寄存器内容,主机接收应答,并读取指定长度的数据。

  3. 主机将接收到的数据存储到 data 缓冲区中。

更多说明及函数原理可参考 I2C 主机写入后读取i2c_master_transmit_receive() 的参数说明可参考 I2C 接口

寄存器写入函数

mpu9250_register_write_byte() 用于将单字节数据写入至 MPU9250 的指定寄存器。

参数解释

传入参数

参数功能

参数说明

dev_handle

I2C 设备句柄

将设备添加至 I2C 总线后返回的有效设备句柄,用于指定目标从机设备。

reg_addr

目标寄存器地址

需要读取的目标设备寄存器地址。

data

要写入的数据

单字节数据。

函数执行逻辑如下:

  1. 将寄存器地址与要写入的数据组合为写缓冲区 write_buf[]

  2. 调用 i2c_master_transmit() 将缓冲区数据写入从机设备的指定寄存器,实现寄存器写入。

更多说明及函数原理可参考 I2C 主机写入i2c_master_transmit() 的参数说明可参考 I2C 接口

主函数说明

本示例演示了 I2C 主机的初始化、与 MPU9250 传感器的通信以及资源释放。

  1. 定义变量:

  • 定义数组 data[] 用于存放从 MPU9250 处读取的数据。

  • 定义总线句柄 bus_handle 和设备句柄 dev_handle,用于后续保存返回的句柄。

  1. 调用 i2c_master_init() 初始化 I2C 总线并添加从机设备,完成主机与从机的连接。执行成功后返回对应的句柄并打印日志提示 I2C 初始化完成。

  2. 调用 mpu9250_register_read() 读取 WHO_AM_I 寄存器中的内容。

  3. 调用 mpu9250_register_write_byte()PWR_MGMT_1 寄存器的 RESET_BIT 置 1,实现对 MPU9250 的复位。

  4. 释放 I2C 资源

  • 调用 i2c_master_bus_rm_device() 移除从机设备。参数说明可参考 I2C 接口

  • 调用 i2c_del_master_bus() 删除 I2C 总线。参数说明可参考 I2C 接口

备注

  • 初始化和释放资源为 I2C 通用流程,确保总线和设备正确配置与释放,避免资源泄漏。

  • 执行读取和写入操作属于应用特定任务,可根据实际从机功能修改寄存器操作。

程序现象

本示例中,程序通过向从机发送寄存器地址实现读写操作控制,读取时采用写寄存器地址以及读数据事务,写入时采用写寄存器地址以及写数据事务,对应时序图如下:

I2C-timing-diagram

根据时序图,程序执行可总结为以下阶段:

  1. 起始条件:时序图中表示为 S,主机发送起始条件,标志一次 I2C 事务开始,SDA 由高拉低,SCL 保持高电平。

  2. 主机地址写入:时序图中表示为 AW : D0 W,主机在 SCL 的上升沿向从机发送 7 位从机地址加 1 位写标志(W),SDA 输出地址和写标志,每一位数据在 SCL 高电平时被从机采样。

  3. 从机应答:时序图中表示为 A,从机接收到地址并识别为写操作后,拉低 SDA 发送 ACK。

  4. 主机数据写入:时序图中表示为 Data write: 75,主机向从机发送寄存器数据,SDA 输出数据,每一位数据对应 SCL 的高电平进行采样。

  5. 从机应答:时序图中表示为 A,从机接收到数据后拉低 SDA 发送 ACK。

  6. 重复起始条件:时序图中表示为 Sr,主机发送重复起始条件,准备进行读取操作,SDA 由高拉低,SCL 保持高电平。

  7. 主机地址读取:时序图中表示为 AR : D1 R,主机在 SCL 的上升沿向从机发送 7 位从机地址加 1 位读标志(R),SDA 输出地址和读标志,每一位数据在 SCL 高电平时被从机采样。

  8. 从机数据读取:时序图中表示为 Read write: 68,从机将寄存器数据输出到 SDA,主机在 SCL 上升沿采样数据。

  9. 主机应答:时序图中表示为 N,主机接收最后一字节后拉高 SDA 发送 NACK,表示本次读操作结束。

  10. 停止条件:时序图中表示为 P,主机发送停止条件,结束本次 I2C 事务,SDA 由低拉高,SCL 保持高电平。