4. I3C 通信基本流程:START、STOP、ACK/NACK、数据读写时序归纳总结
好,我们直接切入正题。I3C 的通信流程,说白了就是一套精心设计过的握手协议。你想想看,总线上挂着的设备有好几个,怎么让它们有序地说话、安静地闭嘴,就得靠我们今天聊的这些信号:START、STOP、ACK/NACK,还有具体的数据怎么读写。
我记得早期调 I2C 的时候,经常在时序上栽跟头。I3C 虽然快了很多,但基础逻辑是相通的。掌握好这部分,后面动态地址分配那些花活,你才能看得明白。
4.1 通信的起点与终点:START 与 STOP 条件
任何一次 I3C 通信,都由 START 条件开启,由 STOP 条件结束。这两个信号,由主设备(我们通常叫它 Controller)产生。
- START 条件: 在 SCL(时钟线)为高电平时,SDA(数据线)从高电平切换到低电平。
- STOP 条件: 在 SCL 为高电平时,SDA 从低电平切换到高电平。
这里有个小陷阱。I3C 为了提升总线速度,引入了一种叫“START 重复”(Repeated START)的机制。它允许你在不发 STOP 的情况下,直接发起一个新的事务。这在多寄存器读写时特别有用,能省下不少时间。
我的个人习惯: 在画原理图或写驱动时,我习惯把 START 条件看作是喊了一声“大家注意,我要说话了!”;而 STOP 条件就是“我说完了,你们继续”。这能帮你快速理解波形图。
4.2 应答机制:ACK 与 NACK
每个字节(8位数据)传输完成后,接收方必须给出一个应答位(ACK/NACK)。这是 I3C 保证通信可靠性的基石。
- ACK(应答): 发送方释放 SDA 线,接收方在第 9 个 SCL 周期将 SDA 拉低,表示“收到了,继续发”。
- NACK(非应答): 接收方在第 9 个 SCL 周期保持 SDA 为高,表示“没收到 / 不想收 / 收不了”。
在 I3C 里,NACK 的用途比 I2C 更丰富。比如,从设备还没准备好数据时,它会主动发送 NACK 让主设备等一下。我曾经在项目里因为没处理好从设备的 NACK,导致整个系统卡死,嗯,那会儿排查了好久才发现是时序握手的问题。
注意: 在 I3C 的动态地址分配过程中,如果从设备不响应广播地址,主设备会连续收到 NACK。这时候不要死等,要设置超时机制,否则总线会一直挂着。
4.3 数据读写的基本时序
I3C 的数据传输,是在 SCL 时钟驱动下一位一位进行的。SDA 线上的数据在 SCL 低电平时改变,在 SCL 高电平时被采样。这就是为什么我们看波形图,数据总是在时钟上升沿附近稳定下来。
一个标准的数据传输序列如下:
- START 条件:发起通信。
- 发送从设备地址:第一个字节是 7 位或 8 位地址 + 读写位。
- 等待 ACK/NACK:从设备应答。
- 发送/接收数据:按需进行多字节传输。
- STOP 条件:结束通信。
下面这张表,是我总结的读写操作时序对比,你在调试时可以对照着看:
| 操作类型 | 主设备行为 | 从设备行为 | 典型流程 |
|---|---|---|---|
| 写操作 | 发送地址 + W;发送数据字节 | 每收到一个字节,回复 ACK | START → 地址+W → ACK → 数据1 → ACK → ... → STOP |
| 读操作 | 发送地址 + R;接收数据并回复 ACK/NACK | 发送数据字节 | START → 地址+R → ACK → 数据1 → 主发ACK → ... → 最后数据 → 主发NACK → STOP |
| 重复 START | 在 STOP 前,再次产生 START | 跟随新的地址与操作 | ...数据n → ACK → 重复START → 新地址... → STOP |
4.4 核心逻辑可视化
为了让你更直观地理解 I3C 通信的全貌,我画了下面这张图。它展示了从 START 开始,到地址发送、确认,再到数据读写,最后以 STOP 结束的完整流程。绿色节点代表正常路径,红色节点代表异常处理(NACK)。
图中 NACK 的分支路径很关键。遇到 NACK,你不能无休止地重试。我在实际开发中就遇到过这种情况:一个从设备在初始化时不稳定,偶尔会丢包。我当时的处理是,在驱动中加了一个最多重试 3 次的循环,每次重试前发一次 STOP 复位总线状态。这个习惯一直保留到现在。
4.5 避坑指南:时序中的常见问题
- 上升沿时间过长: I3C 的速度很高,SDA 和 SCL 的上升时间必须严格符合规范。如果 PCB 走线过长或上下拉电阻没选对,波形会变缓,导致采样出错。我建议你在做硬件测试时,用示波器看一下上升沿斜率。
- ACK 时钟重叠: 在多字节传输时,前一个字节的 ACK 时钟和后一个字节的第一个数据时钟可能会混在一起。嗯,这里要确保驱动在每个字节传输后,都留出足够的准备时间。
- STOP 后总线释放: 有些从设备在收到 STOP 后,需要一小段时间来完成内部处理。如果主设备紧接着发下一个 START,可能造成冲突。我个人经验是,在 STOP 后至少插入 1~2 个时钟周期的空闲时间。
核心总结: I3C 的通信流程,就是 START → 地址 → ACK/NACK → 数据流 → STOP。你把它理解成一场对话:喊人、确认身份、聊正事、再见了您嘞。所有的奇技淫巧,包括后面的动态地址分配,都建立在这个基础之上。