2. I2C的应答机制:ACK与NACK的原理归纳总结

调试I2C的人,几乎都栽过在应答位上。我自己刚入门时也觉得“不就是个拉低拉高嘛”,直到一次量产中发现整批设备间歇性死机,用逻辑分析仪抓到从机偶尔不回ACK,才真正重视起来。这个9位的传输窗口,藏着整个协议稳定性的命门。

2.1 什么是应答?为什么需要应答?

I2C协议中,每传输一个字节(8位数据)后,接收方必须在第9个SCL时钟周期给出一个应答位。说白了,这就像你给对方寄了封信,必须等对方回个“收到了”或“不收了”的信号。没有这个环节,主机永远不知道数据是否正确送达。

  • ACK(Acknowledge):接收方在第9个SCL拉低SDA,表示“收到,请继续”。
  • NACK(Not Acknowledge):接收方在第9个SCL保持SDA高,表示“没收到”或“不想再收了”。

我个人习惯把应答位叫做“协议的血压计”——血压不对,整个系统肯定有问题。你想想看,一个没有应答的协议会怎样?只能靠超时猜状态,这在实时控制中是灾难。

2.2 ACK与NACK的电气特征

时序上非常直观:第1~8个SCL传输数据位,第9个SCL传输应答位。数据位由发送方控制SDA,应答位由接收方控制SDA。我曾在项目里用逻辑分析仪抓过一段漂亮的时序,完全符合标准:

  • ACK:SDA在第9个SCL低电平阶段被从机拉低,并保持到SCL高电平结束。
  • NACK:SDA在第9个SCL保持高,主机看到这个高电平后,通常会发出停止信号。

关键指标:应答位必须在SCL高电平期间采样。逻辑分析仪上要关注第9个SCL上升沿后SDA的状态——这才是真正的应答值。很多新手把整个第9个时钟都算进去,结果看错。

为了更直观地理解整个流程,我画了一张图,展示I2C写操作中应答位如何嵌入在传输序列里:

I2C写操作应答流程 START 地址 + R/W# ACK? NACK→Stop 数据字节 ACK? NACK→Stop 更多字节? STOP 是 → 继续 ● 每个菱形“ACK?”检测第9个SCL高电平时SDA的状态:低=ACK,高=NACK

2.3 主机与从机的角色

应答的职责分配,很多人会搞混。我记了个口诀:“谁发数据,谁被应答;谁收数据,谁发应答”。具体来说:

  • 主机发送(写操作):主机发地址 + 数据字节,从机在每个字节后发ACK/NACK。
  • 主机接收(读操作):主机发地址后,从机开始发数据,此时主机需要发ACK(表示“还要”)或NACK(表示“够了”)。
操作方向发送方接收方应答发出者
写主机从机从机
读从机主机主机

我曾经调试一块SPI转I2C桥接芯片,读操作一直卡死。逻辑分析仪一看,主机在收完第一个字节后发了个NACK,从机直接释放了总线。问题出在主机的接收缓冲区只能装一个字节,读完就发NACK——但我的应用层期望读更多。这里要记住:读操作中,主机会在你想要的数据字节之后发NACK。

2.4 NACK的常见触发场景

NACK不一定是错误,它有时是正常协议终止。但数据手册和逻辑分析仪上出现的NACK,十有八九是问题。我总结了几种典型情况:

  1. 地址不匹配:总线上没有从机响应该地址,SDA保持高,主机收到NACK。
  2. 从机忙:从机正在处理内部事务(比如EEPROM正在写页),此时会NACK。
  3. 数据无效:从机发现收到的字节格式错误或校验失败,主动回NACK。
  4. 主机主动结束:读操作中主机发NACK表示“不再读”。
  5. 总线短路或上拉不足:SDA被意外拉高,导致本该是ACK的位变成了NACK。
场景NACK出现在哪个字节后?根本原因
地址不匹配地址字节后从机不存在或地址错误
从机忙任意字节后从机内部处理未完成
数据错误数据字节后校验失败或协议违规
主机主动停止最后一个数据字节后(读)主机预期结束
硬件故障随机位置重复出现上拉电阻、电平冲突或干扰

2.5 实战中的应答观察:逻辑分析仪视角

用逻辑分析仪抓应答,我最关注两个点:第九个SCL的上升沿和SDA的稳定电平。有一次量产返修率突然飙到30%,看波形全是正常ACK,但偶尔在地址字节后的第九个时钟SDA是“半高半低”——那其实是总线电容过大、SDA没来得及拉到低。我加了几根飞线临时降低了线路寄生电容,问题立刻消失。

实用技巧:在逻辑分析软件里设置“ACK检测”触发条件,抓取第一个NACK时自动暂停。这样你不需要手动翻看几万帧数据。我调试I2C设备时,一定会把这个触发条件配好,比事后逐帧扫描高效十倍。

另一个常见陷阱:重复起始条件(Sr)前的应答。一些从机在接收到读命令后会先发一个NACK表示“还没准备好”,你必须重新发起Sr再试。这时候如果软件没有重试机制,就可能被误判为设备坏了。嗯,这里要注意区分“真的坏了”和“忙但活着”。

掌握ACK/NACK的电气行为和协议角色,是诊断I2C异常的第一步。下功夫把这张应答时序图刻在脑子里,以后抓波形能一眼看出问题出在第几个字节。