news 2026/6/11 16:03:01

通俗解释I2C总线应答与非应答信号

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
通俗解释I2C总线应答与非应答信号

I2C通信中,为什么最后一个字节要发NACK?一文讲透应答机制的底层逻辑

你有没有遇到过这样的情况:STM32读取传感器数据时,程序卡在I²C接收循环里出不来?或者用逻辑分析仪抓包发现,明明只想要两个字节,但从设备还在不停地发第三个、第四个?

如果你排查到最后发现是“忘了发NACK”,那这篇文章就是为你写的。

我们今天不堆术语、不抄手册,就从一个最朴素的问题出发:I²C通信中,每传完一个字节后那个“应答位”到底是谁控制的?什么时候该拉低(ACK),什么时候必须放手(NACK)?

搞懂这个问题,不仅能让你写出更稳健的驱动代码,还能在调试通信故障时一眼看出波形里的“致命破绽”。


一根数据线,如何确认对方“听到了”?

想象你在嘈杂的工厂车间里,对着对讲机喊:“老张,把阀门关一下!”
如果老张没回应,你是继续喊第二遍,还是以为他已经去执行了?

在电子世界里,这种“确认收到”的机制叫应答(ACK)。而I²C总线的设计者很聪明——他们不用额外信号线,就在每个字节后面加了一个“确认周期”,让接收方亲自表态。

这个周期只有1个时钟(SCL)宽度,在这期间:
- 如果接收方把SDA拉低 → 表示“我收到了,继续”
- 如果接收方不碰SDA(保持高电平)→ 表示“停!别发了”或“我没准备好”

这就是所谓的第9位——不是数据,也不是命令,而是纯粹的握手信号。

⚠️ 注意:SDA是开漏输出,靠上拉电阻维持高电平。所以“不动作”就等于“发高电平”,也就是NACK。


谁来决定ACK还是NACK?规则其实很简单

很多人被I²C状态机图搞得头晕,其实核心规则就一条:

谁是接收方,谁负责生成ACK/NACK。

来看几个典型场景:

场景1:主设备写数据给从设备

[主] 发地址 → [从] 接收 → 拉低SDA(ACK) [主] 发寄存器地址 → [从] 接收 → 拉低SDA(ACK) [主] 发数据 → [从] 接收 → 拉低SDA(ACK)

全程都是从设备在接收,所以每次都要由它来拉低SDA表示确认。

场景2:主设备读数据(重点来了!)

[主] 发起Start + 地址+读标志 [从] 开始发送第一个字节 [主] 接收 → 此时主是接收方!→ 必须由主拉低SDA(ACK)告诉从:“我还想再听一个” [从] 发送第二个字节 [主] 接收 → 这次是最后一个 → 主不再拉低SDA(即NACK)→ 通知从:“到此为止” [主] 立刻发Stop

看到关键了吗?读操作中,主设备虽然是“发起者”,但在接收数据时,角色变成了接收方,必须主动控制ACK/NACK!

这也是为什么很多初学者会犯错:以为“主机永远主导一切”,结果在最后一步忘记关闭应答,导致从设备以为还要继续发数据,死死拽着SDA不放,总线就被锁死了。


NACK不只是“错误”,更是“控制指令”

很多人一看到NACK就以为是通信失败,其实大错特错。

NACK有三种含义,取决于上下文:

情况含义是错误吗?
写地址后立即NACK从设备不存在 / 地址错了 / 没上电✅ 是问题
写数据过程中NACK从设备忙(如EEPROM正在写入)⚠️ 正常现象,需重试
读最后一个字节后NACK主设备明确说“够了”❌ 不是错误,是正确行为

最后一个尤其重要。比如你要从温度传感器读2个字节,流程应该是:

  1. 发Start + 设备地址(写)
  2. 写寄存器地址
  3. 重复Start + 设备地址(读)
  4. 收第1字节 → 主发ACK → “继续”
  5. 收第2字节 → 主发NACK → “到此为止”
  6. 发Stop

✅ 第5步必须NACK!否则从设备会继续发第3个字节,可能造成缓冲区溢出或总线僵持。


实战演示:HAL库怎么自动处理NACK?

以STM32 HAL库为例,当你调用:

uint8_t data[2]; HAL_I2C_Mem_Read(&hi2c1, DEV_ADDR, REG_TEMP, I2C_MEMADD_SIZE_8BIT, data, 2, 100);

你传了2作为长度,HAL库内部就会这样安排:

  • 前1个字节:开启应答(ACK)
  • 最后1个字节:关闭应答(NACK),然后发Stop

它背后做了什么?其实就是这几句关键操作:

// 接收前N-1个字节:保持ACK使能 I2C_AcknowledgeConfig(I2Cx, ENABLE); // 接收最后一个字节前:提前关闭ACK I2C_AcknowledgeConfig(I2Cx, DISABLE); // 手动产生Stop条件 I2C_GenerateSTOP(I2Cx, ENABLE);

如果你写裸机驱动,这些细节就必须自己把控。一旦漏掉DISABLE Ack,通信就会卡住。


常见坑点与调试秘籍

❌ 坑1:读操作末尾没发NACK,总线被从设备“霸占”

现象:主设备已经发了Stop,但从设备还在输出数据,SDA一直被拉低。
原因:主设备没有通过NACK明确终止通信,从设备误以为主机还想收更多。
解决:确保最后一次接收前关闭应答功能。

❌ 坑2:地址扫描时误判“设备不存在”

有些开发者写了个循环,挨个试0x08~0x77的地址,看哪个能返回ACK。
但如果某个地址返回NACK,就断定“设备不在”——这也不一定准确!

真实案例:某项目中BMP280始终检测不到,打印显示所有地址都NACK。
结果用逻辑分析仪一看,地址帧其实是ACK的!但因为后续没发寄存器地址,直接进读操作,协议断了,所以整体失败。

✅ 正确做法:先写地址+寄存器 → 再读数据,才算完整事务。

🛠 调试技巧:用逻辑分析仪看第九位

这是最直观的方法。抓一段I²C波形,重点关注每个字节后的第9个SCL周期:

  • 如果是低电平 → ACK
  • 如果是高电平 → NACK

比如你期望读两个字节,波形应该是:
[Byte1][ACK][Byte2][NACK][Stop]
如果看到[Byte2][ACK],那就说明你的代码还在等下一个字节,很可能陷入超时等待。


设计建议:让I²C通信更可靠

1. 上拉电阻别省

标准值4.7kΩ,负载重可降到2.2kΩ。太大会导致上升沿缓慢,影响高速模式;太小则功耗高。

2. 多设备共存?注意地址冲突

常见传感器如AT24C02(EEPROM)、SHT30(温湿度)、OLED屏都可能使用0x78/0x7A这类地址。焊接前务必查清设备实际地址。

3. 别迷信“设备就绪”函数

HAL_I2C_IsDeviceReady()本质就是不断发地址+等待ACK。对于某些响应慢的设备(如刚上电的传感器),可能需要重试多次才能成功。

可以加个延时再探测:

HAL_Delay(10); // 上电稳定 while (HAL_I2C_IsDeviceReady(&hi2c1, addr, 2, 100) != HAL_OK) { HAL_Delay(5); }

4. 总线锁死怎么办?

如果SDA一直为低,可能是某个从设备崩溃了,死死拉着总线。

急救方法:模拟9个SCL脉冲,强迫从设备释放SDA:

// 手动翻转SCL引脚9次(GPIO模式) for (int i = 0; i < 9; i++) { HAL_GPIO_WritePin(SCL_PORT, SCL_PIN, GPIO_PIN_RESET); delay_us(5); HAL_GPIO_WritePin(SCL_PORT, SCL_PIN, GPIO_PIN_SET); delay_us(5); } // 然后发一个Stop条件恢复

结语:掌握ACK/NACK,才算真正入门I²C

你可以不会配置DMA,可以不懂时钟延展,但如果你不清楚每一个字节之后的那个“确认位”是怎么来的、谁该负责、何时该放手,那你离写出稳定可靠的I²C代码还差最后一公里。

记住一句话:

在I²C的世界里,礼貌很重要——发完数据要等对方点头(ACK),想结束对话要说“再见”(NACK + Stop)。

下次当你面对一堆跳动的波形时,不妨问自己一句:
“现在轮到谁来拉低SDA了?”

答案清楚了,问题也就解开了。

如果你在项目中遇到过因NACK引发的奇葩bug,欢迎在评论区分享经历,我们一起排雷拆弹。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 17:39:23

出门问问技术跟进:车机场景下轻量化模型优化方向

出门问问技术跟进&#xff1a;车机场景下轻量化模型优化方向 在智能座舱的演进过程中&#xff0c;语音交互早已不再是“能听清就行”的初级功能。用户如今期待的是“我说完指令&#xff0c;空调立刻调温”“连续说三句话无需重复唤醒”这样的自然体验。然而&#xff0c;理想很丰…

作者头像 李华
网站建设 2026/6/9 1:08:03

github镜像网站加速:轻松获取Fun-ASR开源代码

github镜像网站加速&#xff1a;轻松获取Fun-ASR开源代码 在语音技术日益融入日常办公与智能设备的今天&#xff0c;越来越多开发者希望快速搭建一套高效、稳定的中文语音识别系统。然而现实往往并不顺畅——从 GitHub 克隆项目时卡顿、超时甚至连接失败&#xff0c;成了国内开…

作者头像 李华
网站建设 2026/6/11 10:01:20

USB3.0高频损耗材料选择:系统学习板材特性

USB3.0高频信号为何总“掉链子”&#xff1f;一文讲透PCB材料怎么选 你有没有遇到过这样的情况&#xff1a;明明电路设计没问题&#xff0c;原理图也反复检查了&#xff0c;USB3.0却总是枚举失败、传输中断&#xff0c;甚至在量产时出现批次性连接异常&#xff1f; 别急着怀疑…

作者头像 李华
网站建设 2026/6/11 11:11:54

5G NR CSI-RS完整仿真流程

详解Matlab 5G NR CSI-RS完整仿真流程&#xff1a;从参数配置到信道估计验证 CSI-RS&#xff08;信道状态信息参考信号&#xff09;是5G NR系统中支撑信道估计、MIMO波束赋形、链路质量监测的核心参考信号。本文将基于Matlab 5G Toolbox&#xff0c;结合完整仿真代码&#xff0…

作者头像 李华
网站建设 2026/6/11 10:01:18

搜狐号媒体矩阵:扩大Fun-ASR品牌影响力覆盖

Fun-ASR&#xff1a;从技术内核到落地实践的语音识别新范式 在智能内容生产加速演进的今天&#xff0c;语音数据正以前所未有的速度成为信息流转的核心载体。无论是新闻采编中的采访录音转写、在线教育里的课程字幕生成&#xff0c;还是客服系统的通话分析&#xff0c;高效准确…

作者头像 李华
网站建设 2026/6/9 17:20:34

腾讯科技报道:AI语音赛道再添一员猛将

Fun-ASR语音识别系统技术深度解析 在智能办公与远程协作日益普及的今天&#xff0c;会议录音转写、课堂笔记生成、客服语音分析等需求激增&#xff0c;传统依赖人工听写的方式早已无法满足效率要求。与此同时&#xff0c;云端语音识别服务虽便捷&#xff0c;却因数据隐私问题让…

作者头像 李华