I2C Basic 示例
示例说明
本示例展示了如何初始化和配置 I2C 接口,以及如何通过 I2C 主机与 MPU9250 传感器通信,包括读取从机寄存器数据并在完成后释放相关资源。
运行方法
示例完整代码见 I2C Basic Master 示例。运行前的配置说明、对应 GPIO 引脚、构建与烧录流程详见示例目录下的 README.md 文件。
如需自定义配置项及查看默认值,可参考 宏定义说明 部分。
头文件说明
本示例所使用的头文件涵盖了 FreeRTOS 任务管理、日志输出、I2C 驱动以及系统配置等基础模块。为 I2C 初始化、数据读取和资源释放提供支持。
各头文件按功能分类如下:
FreeRTOS 任务调度 :提供任务创建与调度功能。
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
系统工具 :提供输入输出、系统配置以及日志输出功能。
#include <stdio.h>
#include "sdkconfig.h"
#include "esp_log.h"
I2C 驱动 :提供 I2C 主机模式下的初始化、读写操作及资源释放功能。
#include "driver/i2c_master.h"
宏定义说明
本示例中涉及的宏定义主要用于配置 I2C 主机的引脚、端口号、工作频率及超时时间,同时定义了 MPU9250 传感器的从机地址和关键寄存器地址。
宏定义按功能分类如下:
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
并再次构建/编译示例后会自动同步更新,无需手动更改代码。禁用发送与接收缓冲区有助于节省资源,适用于一般的主机通信场景。
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 初始化 部分。
传入参数 |
参数功能 |
参数说明 |
---|---|---|
|
I2C 总线句柄指针 |
总线成功创建后返回的有效句柄,用于后续对该总线的读写操作。 |
|
I2C 设备句柄指针 |
将设备添加至 I2C 总线后返回的有效设备句柄,用于后续与该设备的通信。 |
寄存器写入后读取函数
mpu9250_register_read()
用于读取 MPU6050 寄存器地址内容。
传入参数 |
参数功能 |
参数说明 |
---|---|---|
|
I2C 设备句柄 |
将设备添加至 I2C 总线后返回的有效设备句柄,用于指定目标从机设备。 |
|
目标寄存器地址 |
需要读取的目标设备寄存器地址。 |
|
数据缓冲区指针 |
用于存放从寄存器中读取的数据,调用函数后数据写入该内存区域。 |
|
读取字节长度 |
指定要从寄存器读取的字节数,需保证缓冲区大小足够容纳数据。 |
该函数通过调用 i2c_master_transmit_receive()
实现寄存器写入后读取,执行逻辑如下:
将目标寄存器地址作为写入数据发送给 MPU9250,用于指定寄存器并验证设备连接情况,从机应答确认接收成功。
从机发送寄存器内容,主机接收应答,并读取指定长度的数据。
主机将接收到的数据存储到
data
缓冲区中。
更多说明及函数原理可参考 I2C 主机写入后读取。i2c_master_transmit_receive()
的参数说明可参考 I2C 接口。
寄存器写入函数
mpu9250_register_write_byte()
用于将单字节数据写入至 MPU9250 的指定寄存器。
传入参数 |
参数功能 |
参数说明 |
---|---|---|
|
I2C 设备句柄 |
将设备添加至 I2C 总线后返回的有效设备句柄,用于指定目标从机设备。 |
|
目标寄存器地址 |
需要读取的目标设备寄存器地址。 |
|
要写入的数据 |
单字节数据。 |
函数执行逻辑如下:
将寄存器地址与要写入的数据组合为写缓冲区
write_buf[]
。调用
i2c_master_transmit()
将缓冲区数据写入从机设备的指定寄存器,实现寄存器写入。
更多说明及函数原理可参考 I2C 主机写入。i2c_master_transmit()
的参数说明可参考 I2C 接口。
主函数说明
本示例演示了 I2C 主机的初始化、与 MPU9250 传感器的通信以及资源释放。
定义变量:
定义数组
data[]
用于存放从 MPU9250 处读取的数据。定义总线句柄
bus_handle
和设备句柄dev_handle
,用于后续保存返回的句柄。
调用
i2c_master_init()
初始化 I2C 总线并添加从机设备,完成主机与从机的连接。执行成功后返回对应的句柄并打印日志提示 I2C 初始化完成。调用
mpu9250_register_read()
读取WHO_AM_I
寄存器中的内容。调用
mpu9250_register_write_byte()
将PWR_MGMT_1
寄存器的RESET_BIT
置 1,实现对 MPU9250 的复位。
备注
初始化和释放资源为 I2C 通用流程,确保总线和设备正确配置与释放,避免资源泄漏。
执行读取和写入操作属于应用特定任务,可根据实际从机功能修改寄存器操作。
程序现象
本示例中,程序通过向从机发送寄存器地址实现读写操作控制,读取时采用写寄存器地址以及读数据事务,写入时采用写寄存器地址以及写数据事务,对应时序图如下:

根据时序图,程序执行可总结为以下阶段:
起始条件:时序图中表示为
S
,主机发送起始条件,标志一次 I2C 事务开始,SDA 由高拉低,SCL 保持高电平。主机地址写入:时序图中表示为
AW : D0 W
,主机在 SCL 的上升沿向从机发送 7 位从机地址加 1 位写标志(W),SDA 输出地址和写标志,每一位数据在 SCL 高电平时被从机采样。从机应答:时序图中表示为
A
,从机接收到地址并识别为写操作后,拉低 SDA 发送 ACK。主机数据写入:时序图中表示为
Data write: 75
,主机向从机发送寄存器数据,SDA 输出数据,每一位数据对应 SCL 的高电平进行采样。从机应答:时序图中表示为
A
,从机接收到数据后拉低 SDA 发送 ACK。重复起始条件:时序图中表示为
Sr
,主机发送重复起始条件,准备进行读取操作,SDA 由高拉低,SCL 保持高电平。主机地址读取:时序图中表示为
AR : D1 R
,主机在 SCL 的上升沿向从机发送 7 位从机地址加 1 位读标志(R),SDA 输出地址和读标志,每一位数据在 SCL 高电平时被从机采样。从机数据读取:时序图中表示为
Read write: 68
,从机将寄存器数据输出到 SDA,主机在 SCL 上升沿采样数据。主机应答:时序图中表示为
N
,主机接收最后一字节后拉高 SDA 发送 NACK,表示本次读操作结束。停止条件:时序图中表示为
P
,主机发送停止条件,结束本次 I2C 事务,SDA 由低拉高,SCL 保持高电平。