2. I2C协议时序:起始条件、停止条件、数据有效性、字节传输格式、应答与非应答机制
I2C(Inter-Integrated Circuit)总线协议是音频Codec驱动开发中最核心的底层通信规约。理解其时序细节,是正确读写Codec寄存器、定位驱动问题的前提。本节将逐一拆解I2C协议的五个关键要素:起始与停止条件、数据有效性、字节传输格式以及应答/非应答机制。
2.1 起始条件(S)与停止条件(P)
I2C总线在空闲时,SCL(时钟线)和SDA(数据线)均为高电平(由上拉电阻拉高)。总线上的任何通信事务,都必须以起始条件开始,以停止条件结束。这两个条件是唯一允许SDA在SCL为高电平时发生变化的时刻。
| 条件 | 时序定义 | 方向 | 关键特征 |
|---|---|---|---|
| 起始条件(S) | SCL为高电平时,SDA从高电平切换到低电平 | 主机→从机 | 表示一次传输开始;总线从空闲变为忙碌 |
| 停止条件(P) | SCL为高电平时,SDA从低电平切换到高电平 | 主机→从机 | 表示一次传输结束;总线从忙碌变为空闲 |
| 重复起始条件(Sr) | 在未产生停止条件前,再次产生起始条件 | 主机→从机 | 用于改变数据传输方向或切换从机地址,不释放总线 |
调试要点:在逻辑分析仪抓取I2C波形时,首先寻找起始条件(SDA下降沿,SCL高)和停止条件(SDA上升沿,SCL高)。如果波形中缺少停止条件,总线会一直处于忙碌状态,导致后续通信失败。这是音频Codec驱动中常见的“总线挂死”故障原因之一。
2.2 数据有效性
I2C协议对数据线上的电平变化有严格的时间约束,以确保数据的正确采样:
- 数据稳定期:在SCL时钟的高电平期间,SDA上的数据必须保持稳定不变。
- 数据变化期:只有在SCL为低电平时,SDA上的数据才允许发生高低电平的切换。
- 例外:起始条件和停止条件(SDA在SCL高电平时变化)是唯一的例外。
驱动开发启示:在编写I2C时序代码时,必须确保SCL高电平期间不改变SDA状态。如果使用GPIO模拟I2C,需要在SCL拉高后插入适当的延时(通常≥4.7μs for 100kHz标准模式),以保证从机有足够时间采样SDA。
2.3 字节传输格式
I2C总线上的数据以字节(8位)为单位进行传输,且遵循高位先行(MSB First)的顺序。每个字节传输完成后,必须跟随一个应答位(ACK/NACK),因此总线上每传输一个有效字节,实际上需要9个SCL时钟周期。
| 位序 | 名称 | 说明 |
|---|---|---|
| Bit 7 (MSB) | 最高有效位 | 最先发送,对于地址字节,此位决定是读(1)还是写(0) |
| Bit 6 ~ Bit 1 | 数据位 | 地址或数据内容 |
| Bit 0 (LSB) | 最低有效位 | 最后发送 |
| 第9个SCL | 应答位(ACK/NACK) | 由接收方拉低SDA(ACK)或保持高电平(NACK) |
一个完整的I2C写事务(以音频Codec寄存器写入为例)通常包含以下字节序列:
- 起始条件(S)
- 从机地址 + 写标志(7位地址 + 0):主机发送,共8位
- 应答位(ACK):从机应答
- 寄存器地址(高字节):主机发送,8位
- 应答位(ACK):从机应答
- 寄存器地址(低字节):主机发送,8位(如果Codec使用16位寄存器地址)
- 应答位(ACK):从机应答
- 数据字节:主机发送,8位
- 应答位(ACK):从机应答
- 停止条件(P)
2.4 应答(ACK)与非应答(NACK)机制
应答机制是I2C协议可靠性的核心。每传输完一个字节(8位数据),接收方必须在第9个SCL时钟周期内给出应答信号:
- 应答(ACK):接收方在第9个SCL时钟的低电平期间将SDA拉低,并保持到SCL高电平被采样。表示“已收到,请继续发送”。
- 非应答(NACK):接收方在第9个SCL时钟期间保持SDA为高电平(释放SDA,由上拉电阻拉高)。表示“未收到/无法接收/传输结束”。
常见故障排查:在音频Codec驱动调试中,如果主机发送从机地址后收到NACK,通常意味着:① I2C地址配置错误(如7位地址与8位地址混淆);② Codec处于复位状态或电源未稳定;③ 总线存在电气问题(上拉电阻缺失、电平不匹配)。如果主机发送寄存器地址后收到NACK,则可能是Codec不支持该寄存器地址或处于错误的工作模式。
2.5 完整读写事务流程对比
在音频Codec驱动中,最常见的两种操作是写寄存器(配置)和读寄存器(状态回读)。下表对比了两种事务的完整流程:
| 步骤 | 写寄存器事务 | 读寄存器事务 |
|---|---|---|
| 1 | 主机发送起始条件(S) | 主机发送起始条件(S) |
| 2 | 主机发送从机地址 + W(0) | 主机发送从机地址 + W(0) |
| 3 | 从机应答(ACK) | 从机应答(ACK) |
| 4 | 主机发送寄存器地址(高字节) | 主机发送寄存器地址(高字节) |
| 5 | 从机应答(ACK) | 从机应答(ACK) |
| 6 | 主机发送寄存器地址(低字节) | 主机发送寄存器地址(低字节) |
| 7 | 从机应答(ACK) | 从机应答(ACK) |
| 8 | 主机发送数据字节 | 主机发送重复起始条件(Sr) |
| 9 | 从机应答(ACK) | 主机发送从机地址 + R(1) |
| 10 | 主机发送停止条件(P) | 从机应答(ACK) |
| 11 | — | 从机发送数据字节(主机读取) |
| 12 | — | 主机发送非应答(NACK) |
| 13 | — | 主机发送停止条件(P) |
关键区别:读事务在发送完寄存器地址后,必须使用重复起始条件(Sr)重新发送从机地址并切换为读方向(R/W=1),而不能直接发送停止条件再重新开始。这是I2C协议中“组合事务”的典型应用,目的是在不释放总线的情况下改变数据传输方向。
2.6 时序参数与速率等级
I2C协议定义了多种速率模式,不同模式下时序参数不同。音频Codec通常工作在标准模式(100kHz)或快速模式(400kHz)。
| 参数 | 符号 | 标准模式(100kHz) | 快速模式(400kHz) | 说明 |
|---|---|---|---|---|
| SCL时钟频率 | fSCL | ≤ 100 kHz | ≤ 400 kHz | 总线时钟速率 |
| 保持时间(起始条件) | tHD;STA | ≥ 4.0 μs | ≥ 0.6 μs | 起始条件后SCL低电平保持时间 |
| 低电平周期 | tLOW | ≥ 4.7 μs | ≥ 1.3 μs | SCL低电平持续时间 |
| 高电平周期 | tHIGH | ≥ 4.0 μs | ≥ 0.6 μs | SCL高电平持续时间 |
| 数据建立时间 | tSU;DAT | ≥ 250 ns | ≥ 100 ns | SDA在SCL高电平前的稳定时间 |
| 数据保持时间 | tHD;DAT | ≥ 0 ns | ≥ 0 ns | SDA在SCL低电平后的保持时间 |
| 上升时间 | tr | ≤ 1000 ns | ≤ 300 ns | SCL/SDA信号上升沿 |