3. I2C 地址与数据传输格式:7位地址与10位地址、读写位、数据帧格式
I2C 总线上的每个从设备都有一个唯一的地址,主设备通过地址来寻址特定的从设备进行通信。理解地址格式与数据帧结构是编写 I2C 驱动的基础,也是确保传感器数据正确采集的前提。
3.1 7位地址与10位地址
I2C 协议支持两种地址长度:7位地址 和 10位地址。绝大多数传感器(如温度、湿度、加速度计等)使用 7 位地址,以节省总线带宽并简化驱动逻辑。
| 特性 | 7位地址 | 10位地址 |
|---|---|---|
| 地址范围 | 0x00 ~ 0x7F(128个地址,其中16个保留) | 0x000 ~ 0x3FF(1024个地址) |
| 总线上的地址字节数 | 1字节(高7位为地址,最低位为读写位) | 2字节(第一个字节高5位为11110,后跟地址高2位 + 读写位;第二个字节为地址低8位) |
| 常见应用场景 | 温度传感器、加速度计、EEPROM、ADC/DAC | 复杂多路复用器、高端电源管理芯片、地址冲突较多的系统 |
| 驱动复杂度 | 低,直接使用 7 位地址即可 | 较高,需要处理地址扩展头 |
驱动开发提示: 在 Linux 内核中,I2C 从设备地址统一使用 7 位表示。对于 10 位地址设备,内核通过
I2C_TENBIT 标志位来区分。在设备树中,10 位地址需要显式声明 reg = <0x10 0x1234> 格式。
3.1.1 7位地址帧格式
主设备发送的第一个字节包含 7 位从设备地址和 1 位读写标志。地址字节的格式如下:
3.1.2 10位地址帧格式
10 位地址使用两个字节进行传输。第一个字节的高 5 位固定为 11110,后跟地址的高 2 位(A9、A8)和读写位;第二个字节为地址的低 8 位(A7 ~ A0)。
3.2 读写位(R/W)
读写位是地址字节的最低位,用于指示数据传输方向:
- R/W = 0(写操作):主设备向从设备发送数据。主设备在发送地址后,继续发送寄存器地址或数据字节。
- R/W = 1(读操作):主设备从从设备读取数据。主设备发送地址后,从设备开始发送数据字节到主设备。
驱动开发关键点: 在 Linux I2C 驱动中,读写位由内核 I2C 核心自动处理。驱动开发者只需在
i2c_msg 结构体中设置 flags 字段:0 表示写,I2C_M_RD 表示读。无需手动拼接地址字节。
3.3 数据帧格式
I2C 数据传输以帧为单位,每帧包含一个起始条件、地址字节、若干数据字节和一个停止条件。每个字节后跟随一个应答位(ACK/NACK)。
3.3.1 完整写操作数据帧
3.3.2 完整读操作数据帧
3.4 应答位(ACK/NACK)机制
每个字节传输完成后,接收方必须在第 9 个 SCL 时钟周期内拉低 SDA 线(ACK)或保持高电平(NACK)。
| 应答类型 | SDA 电平 | 含义 | 典型场景 |
|---|---|---|---|
| ACK(应答) | 低电平 | 接收方已成功接收字节,可以继续传输 | 地址匹配成功、数据写入成功、读数据时主设备希望继续读取 |
| NACK(非应答) | 高电平 | 接收方未准备好或传输结束 | 地址未匹配、从设备忙、读操作最后一个字节后主设备通知停止 |
驱动调试常见问题: 如果 I2C 通信卡在地址发送阶段,且从设备回复 NACK,通常原因包括:
• 设备地址错误(检查数据手册和原理图)
• 从设备未上电或处于复位状态
• 总线被其他设备拉死(SDA/SCL 电平异常)
• 地址 7 位/10 位模式不匹配
• 设备地址错误(检查数据手册和原理图)
• 从设备未上电或处于复位状态
• 总线被其他设备拉死(SDA/SCL 电平异常)
• 地址 7 位/10 位模式不匹配
3.5 典型传感器 I2C 地址示例
以下列出常见传感器的 7 位 I2C 地址(通常数据手册会给出 8 位地址,需要右移 1 位得到 7 位地址):
| 传感器型号 | 类型 | 7位地址(十六进制) | 地址引脚配置 |
|---|---|---|---|
| BME280 | 温湿度/气压 | 0x76 或 0x77 | SDO 引脚电平决定 |
| MPU6050 | 6轴IMU | 0x68 或 0x69 | AD0 引脚电平决定 |
| LSM6DS3 | 6轴IMU | 0x6A 或 0x6B | SA0 引脚电平决定 |
| TC74 | 温度传感器 | 0x48 ~ 0x4F | A0~A2 引脚组合决定 |
| AT24C02 | EEPROM | 0x50 ~ 0x57 | A0~A2 引脚组合决定 |
地址转换技巧: 数据手册通常给出 8 位地址(如 0xD0 表示写、0xD1 表示读)。在 Linux 驱动中,
i2c_client 的 addr 字段使用 7 位地址。转换方法:7位地址 = 8位地址 >> 1。例如 0xD0 >> 1 = 0x68。
3.6 数据帧格式总结
I2C 数据帧的核心要素可以归纳为以下流程:
- 起始条件(S):SCL 高电平时,SDA 从高到低跳变。
- 地址字节:7 位或 10 位地址 + 读写位。
- 应答位(ACK):从设备在第 9 个时钟拉低 SDA。
- 数据字节:8 位数据,MSB 先传,每个字节后跟应答位。
- 重复起始条件(Sr):用于读操作时切换方向,不释放总线。
- 停止条件(P):SCL 高电平时,SDA 从低到高跳变。
掌握地址格式和数据帧结构后,下一步就可以在 Linux 驱动中实现 I2C 读写操作,并结合中断处理完成传感器数据的实时采集。