2. I2C数据传输格式:7位与10位地址模式、读写操作位、ACK/NACK机制
I2C(Inter-Integrated Circuit)总线协议定义了主设备与从设备之间进行数据交换的完整帧格式。理解地址模式、读写控制以及应答机制,是进行I2C控制器驱动移植与中断绑定的基础。本章将深入解析这些核心概念,并结合实际驱动开发场景进行说明。
2.1 I2C总线帧结构概述
一个完整的I2C数据传输帧由以下基本单元组成:起始条件(START)、从设备地址、读写位、数据字节、应答位(ACK/NACK)以及停止条件(STOP)。总线上的所有操作都由主设备发起,从设备根据地址匹配响应。
关键帧结构要素:
- S(START):SCL高电平时,SDA由高变低,表示传输开始。
- 地址字节:7位或10位从设备地址,高位在前。
- R/W:1位读写标志,0表示写操作,1表示读操作。
- ACK/NACK:每个字节后接收方必须回复的应答位。
- 数据字节:8位数据,MSB先传,每个字节后跟ACK。
- P(STOP):SCL高电平时,SDA由低变高,表示传输结束。
2.2 7位地址模式
7位地址模式是I2C协议中最常用的寻址方式。在帧结构中,地址字节的高7位为从设备地址,最低位为读写控制位。标准模式下,总线上最多可挂载112个从设备(保留地址除外)。
| 位序 | 名称 | 说明 |
|---|---|---|
| Bit 7 (MSB) | A6 | 地址最高位,通常由器件型号固定 |
| Bit 6 ~ Bit 1 | A5 ~ A0 | 地址位,部分由硬件引脚决定 |
| Bit 0 (LSB) | R/W | 0=写操作,1=读操作 |
驱动开发提示:在Linux内核中,7位地址通过
i2c_client.addr 字段传递,驱动中通常使用 I2C_SLAVE 命令设置。注意内核内部地址存储时左移1位,保留R/W位空间。
2.3 10位地址模式
10位地址模式是为了扩展总线容量而设计的,允许挂载更多从设备。其帧结构分为两个阶段:第一个字节的前5位为保留码 11110,后跟地址高2位和R/W位;第二个字节为地址低8位。
兼容性注意:并非所有I2C控制器硬件都支持10位地址模式。在移植驱动时,需要检查控制器datasheet中的地址模式支持位。Linux内核通过
I2C_FUNC_10BIT_ADDR 功能标志来检测。
2.4 读写操作位(R/W)
读写操作位位于地址字节的最低位,控制数据传输方向:
- 写操作(R/W = 0):主设备发送数据到从设备。主设备在发送地址后,继续发送数据字节,从设备每收到一个字节回复ACK。
- 读操作(R/W = 1):主设备从从设备读取数据。主设备发送地址后,从设备开始发送数据,主设备每收到一个字节回复ACK(最后一个字节回复NACK以表示读取结束)。
组合传输(Combined Transfer):在实际驱动中,经常需要先写寄存器地址再读数据。这通过重复起始条件(Repeated START)实现,无需先发STOP再发START,保证了总线操作的原子性。
2.5 ACK/NACK机制
应答机制是I2C协议可靠性的核心。每个字节(包括地址字节和数据字节)传输完成后,接收方必须在第9个SCL周期释放SDA线并拉低(ACK)或保持高电平(NACK)。
| 场景 | 发送方 | 接收方 | SDA状态 | 含义 |
|---|---|---|---|---|
| 地址匹配 | 主设备 | 从设备 | 低电平(ACK) | 从设备存在且地址匹配 |
| 地址不匹配 | 主设备 | 从设备 | 高电平(NACK) | 无此从设备或设备忙 |
| 写数据成功 | 主设备 | 从设备 | 低电平(ACK) | 从设备已接收数据 |
| 写数据失败 | 主设备 | 从设备 | 高电平(NACK) | 从设备无法接收(如缓冲区满) |
| 读数据(中间字节) | 从设备 | 主设备 | 低电平(ACK) | 主设备要求继续发送 |
| 读数据(最后一个字节) | 从设备 | 主设备 | 高电平(NACK) | 主设备通知停止发送 |
2.6 驱动开发中的实际应用
在Linux I2C控制器驱动中,上述协议细节直接对应到硬件寄存器操作和中断处理逻辑:
- 起始/停止条件生成:通过控制I2C控制器的START/STOP位或自动模式实现。
- 地址发送与匹配检测:硬件自动发送地址并检测ACK,若收到NACK则触发中断或错误标志。
- 数据收发与应答处理:每字节传输完成后,硬件检查ACK位,驱动通过状态寄存器判断是否继续传输。
- 重复起始条件:在写寄存器地址后读数据时,驱动需设置重复起始标志,避免总线释放。
中断绑定要点:在中断服务程序中,通常通过读取状态寄存器判断当前传输阶段(地址发送完成、数据发送完成、收到NACK等),然后更新传输状态机并触发DMA或PIO下一笔传输。
2.7 常见问题与调试方法
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 地址发送后无ACK | 从设备地址错误、设备未上电、总线冲突 | 使用逻辑分析仪抓取SDA/SCL波形,确认地址位 |
| 数据发送后收到NACK | 从设备缓冲区满、不支持当前操作 | 检查从设备datasheet,确认最大传输长度 |
| 读数据时主设备未发NACK | 驱动未正确设置最后一个字节的NACK | 检查控制器NACK自动生成配置 |
| 总线挂死(SCL/SDA被拉低) | 从设备异常、时钟同步问题 | 发送9个SCL时钟恢复总线,检查上拉电阻 |
调试建议:在驱动移植初期,建议使用
i2c-tools 工具集(如 i2cdetect、i2cget、i2cset)验证硬件连接和地址映射,再逐步调试驱动中断处理逻辑。