恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
I2C总线故障排查:从万用表到逻辑分析仪的完整链路
首页
资讯中心
/
I2C总线故障排查:从万用表到逻辑分析仪的完整链路
I2C总线故障排查:从万用表到逻辑分析仪的完整链路
发布时间:2026/9/29 1:03:25
I2C 总线出问题的时候最让人头疼的不是完全没反应而是时好时坏——设备偶尔能读到数据偶尔 NACK偶尔整个总线被拉死。很多人的第一反应是换器件、换板子但真正高效的排查路径应该是从最便宜的工具开始逐层缩小范围。万用表能帮你确认静态电平是否正常示波器能让你看到时序和毛刺逻辑分析仪能解码出 ACK 到底有没有出现。这篇文章就把这条排查链路完整拆开从最基础的电压测量讲到 ACK 位的判定每一步都告诉你为什么这么做、看到什么现象对应什么问题。1. 先搞清楚 I2C 的电气本质再动手1.1 开漏输出与上拉电阻的关系I2C 的 SDA 和 SCL 都是开漏open-drain结构这意味着器件只能把线拉低不能主动拉高。高电平完全靠上拉电阻把线拉到 VCC。这个特性决定了几个关键事实总线上任何一个器件把线拉低整条线就是低只有所有器件都释放总线线才会被上拉电阻拉高。上拉电阻的取值不是随便选的。它和总线电容构成一个 RC 充电回路上升时间大约为t_r ≈ 0.847 × R_pullup × C_bus标准模式100kHz要求上升时间小于 1000ns快速模式400kHz要求小于 300ns。假设你的总线电容是 200pF用 4.7kΩ 上拉上升时间约 0.847 × 4700 × 200e-12 ≈ 796ns勉强满足标准模式但快速模式就不够了。这就是为什么很多高速 I2C 场景要用 2.2kΩ 甚至 1.5kΩ 上拉。但上拉电阻也不能太小否则器件拉低时灌入的电流会超过它的承受能力。大部分 I2C 器件的低电平灌电流能力在 3mA 左右VCC 为 3.3V 时最小上拉电阻约为 3.3V / 3mA ≈ 1.1kΩ。所以 1.5kΩ 到 10kΩ 是常见范围具体要看总线电容和速率。注意很多开发板上的 I2C 上拉电阻是 10kΩ这个值在短距离、低速场景能用但一旦接上多个从机或者排线较长上升沿就会变得很缓导致通信不稳定。1.2 为什么静态测量就能排除一半问题在通电但总线空闲的状态下SDA 和 SCL 都应该是高电平等于 VCC。如果你用万用表测到某条线是低电平或者中间电平那说明有器件在持续拉低总线或者上拉电阻缺失/损坏。这个判断不需要任何复杂设备一个万用表就够了。常见的静态异常包括测量现象可能原因SDA 和 SCL 都是 0V上拉电阻未焊接、VCC 未供电、器件短路一条线高一条线低该线被某个器件持续拉低或该线上拉缺失两条线都在 1.5V 左右上拉电阻过大或总线电容过大形成分压电压在 0V 和 VCC 之间跳变总线正在通信或者有器件在反复复位万用表测量的时候要注意必须在总线空闲时测。如果主控正在不断发起通信你看到的电压是平均值不代表真实电平。可以先把主控的 I2C 外设关掉或者让程序停在初始化之前再测。2. 万用表能查到的和查不到的2.1 通断与短路排查在断电状态下用万用表的通断档可以快速确认几件事SDA 和 SCL 之间是否短路、每条线对 VCC 和对 GND 是否短路。正常的 I2C 总线SDA 对 VCC 应该有上拉电阻的阻值几 kΩSDA 对 GND 应该是开路或者很大的阻值。如果测到 SDA 对 GND 只有几欧姆那基本可以确定有器件击穿或者焊接短路。这种情况在手工焊接的板子上特别常见尤其是 QFN 封装的传感器引脚间距小很容易连锡。我自己的习惯是拿到一块新板子先不上电用万用表把 I2C 相关的几个测试点全部量一遍。SDA-SCL 之间、SDA-VCC、SDA-GND、SCL-VCC、SCL-GND五个阻值记录下来。正常的话应该是SDA-SCL开路或很大SDA-VCC等于上拉电阻值SDA-GND开路或很大SCL-VCC等于上拉电阻值SCL-GND开路或很大只要有一个不对先解决硬件问题再谈软件。2.2 万用表测动态信号的局限很多人想用万用表测 I2C 通信时的电压变化看到数字跳动就以为在通信。这个判断非常不可靠。万用表的采样率通常只有几 Hz 到几十 Hz而 I2C 的时钟是 100kHz 或 400kHz万用表看到的只是随机采样的平均值。更麻烦的是万用表的输入电容和引线电感会加载到总线上可能让本来勉强能通信的总线直接失效。所以万用表只适合静态测量不适合判断通信是否正常。要判断通信必须上示波器或者逻辑分析仪。提示如果你只有万用表可以用它测 SDA/SCL 的平均电压。空闲时应该是 VCC通信时会在 VCC 和某个中间值之间。但这个只能作为有没有在动的粗略判断不能作为通信是否成功的依据。3. 示波器上看什么才算有效信息3.1 探头选择和接地处理用示波器测 I2C第一个坑就是探头接地。很多人用探头自带的鳄鱼夹接地引线太长测出来的波形全是振铃和过冲。正确的做法是用探头自带的弹簧地针直接顶在板子上的 GND 测试点尽量缩短接地回路。探头建议用 10:1 无源探头带宽至少 100MHz。虽然 I2C 本身速率不高但你要看的是上升沿和毛刺带宽不够会把毛刺滤掉反而看不到问题。输入耦合选 DC因为你要看的是绝对电平。触发设置很关键。用 SCL 或者 SDA 的下降沿触发触发电平设在 VCC/2 左右。如果总线完全没动静可以用自动触发模式先看看有没有信号再切回正常模式抓细节。3.2 上升沿、电平和毛刺的判读抓到波形之后重点看这几个方面上升沿时间。如果上升沿明显是圆弧形说明上拉电阻太大或者总线电容太大。标准模式要求上升时间小于 1000ns快速模式小于 300ns。测量方法是从 0.3×VCC 到 0.7×VCC 的时间。高电平幅值。正常应该接近 VCC。如果只有 2V 左右VCC 是 3.3V说明上拉电阻和某个器件的漏电流形成了分压或者有器件在弱拉低。低电平幅值。正常应该接近 0V。如果低电平有 0.5V 以上说明器件拉低能力不足或者地线回路有问题。毛刺。在 SCL 或 SDA 的边沿上如果有窄脉冲可能是串扰或者反射。这种毛刺如果被从机误认为是时钟沿就会导致数据错位。我遇到过一个典型案例一块板子上 I2C 时好时坏示波器看波形发现 SCL 上升沿有大约 50ns 的振铃幅度达到 1V。后来发现是排线太长而且 SCL 和一根 PWM 信号线并排走。把排线缩短、分开走线之后问题消失。3.3 用示波器判断总线死锁总线死锁是 I2C 最常见的问题之一。现象是 SDA 被某个从机持续拉低主机无法发起新的通信。用示波器可以清楚看到SCL 在正常翻转但 SDA 一直是低电平。死锁的常见原因是主从复位不同步。比如从机在发送 ACK 的时候主机突然复位从机还在等下一个时钟而主机已经重新初始化了。这时候从机可能把 SDA 拉低等待时钟但主机不发时钟就卡住了。解决办法是主机在初始化 I2C 之前先手动发送 9 个时钟脉冲让从机把剩余的数据位发完然后发送 STOP 条件。这个操作在很多 MCU 的 I2C 外设里没有现成功能需要用 GPIO 模拟。// 用 GPIO 模拟时钟脉冲解除 I2C 死锁 void i2c_bus_recovery(void) { gpio_set_mode(SCL_PIN, OUTPUT_OD); gpio_set_mode(SDA_PIN, INPUT); for (int i 0; i 9; i) { gpio_write(SCL_PIN, 0); delay_us(5); gpio_write(SCL_PIN, 1); delay_us(5); } // 发送 STOP 条件 gpio_set_mode(SDA_PIN, OUTPUT_OD); gpio_write(SDA_PIN, 0); delay_us(5); gpio_write(SCL_PIN, 1); delay_us(5); gpio_write(SDA_PIN, 1); delay_us(5); }这段代码的逻辑是先让 SCL 翻转 9 次把从机可能卡住的位全部时钟出去然后手动构造一个 STOP 条件SCL 高时 SDA 从低变高让总线回到空闲状态。4. ACK 位到底怎么判定4.1 ACK 的时序位置I2C 每传输 8 个数据位之后第 9 个时钟周期是 ACK/NACK 位。发送方在第 9 个时钟的低电平期间释放 SDA接收方如果正确接收就在这个时钟周期把 SDA 拉低表示 ACK如果不拉低就是 NACK。用示波器看 ACK需要同时抓 SCL 和 SDA然后数时钟。第 9 个 SCL 上升沿时如果 SDA 是低电平就是 ACK如果是高电平就是 NACK。实际操作中建议用示波器的单次触发模式触发条件设为 SDA 下降沿然后展开波形数时钟。或者用逻辑分析仪直接解码省去数时钟的麻烦。4.2 用逻辑分析仪解码 ACK逻辑分析仪是排查 I2C 最顺手的工具。它能把 SDA 和 SCL 的波形直接解码成地址、数据、ACK/NACK不需要你手动数时钟。常见的逻辑分析仪配合开源软件就能用采样率建议至少 24MHz对于 400kHz 的 I2C 来说足够。解码之后你会看到类似这样的输出Start Address: 0x68 [Write] ACK Data: 0x00 ACK Data: 0x75 ACK Stop如果某个字节后面显示 NACK说明从机没有正确接收。可能的原因包括从机地址不对、从机没有上电、从机忙、从机损坏。注意有些逻辑分析仪的软件会把地址读写位合并显示有些会分开。看的时候要确认一下避免误判地址。4.3 NACK 的几种典型场景NACK 不一定是坏事要看出现在哪个位置地址字节后 NACK从机没有响应。检查从机地址是否正确注意 7 位地址和 8 位地址的区别、从机是否上电、从机是否在复位状态。数据字节后 NACK写操作从机接收到了地址但拒绝接收数据。可能是从机寄存器地址越界或者从机内部缓冲区满。数据字节后 NACK读操作这是正常的。主机在读最后一个字节之后会主动发送 NACK告诉从机我读完了然后发送 STOP。所以读操作的最后一个字节后面出现 NACK 是正确的。我见过很多人把读操作最后的 NACK 当成故障来查浪费了很多时间。记住读操作的最后一个字节主机必须发 NACK这是协议规定的。5. 从波形到根因的完整排查链路5.1 分层排查的思路I2C 排查最忌讳的就是一上来就改代码。正确的顺序是从物理层往上查静态电平断电测通断上电测空闲电平动态波形示波器看上升沿、幅值、毛刺协议解码逻辑分析仪看地址、数据、ACK软件配置时钟频率、地址、寄存器配置从机状态从机是否复位、是否忙、是否损坏每一层确认没问题再往上一层查。这样能避免在软件层浪费时间而问题其实在硬件层。5.2 一个真实的排查案例之前调试一个 GT911 触摸屏I2C 地址是 0x5D 和 0x14 二选一取决于复位时序。现象是主机能读到地址 ACK但读数据全是 0xFF。排查过程第一步万用表测静态电平SDA 和 SCL 都是 3.3V正常。第二步示波器看波形上升沿约 400ns在 400kHz 下勉强够用但有一点振铃。暂时不认为是根因。第三步逻辑分析仪解码发现地址 0x5D 有 ACK但读寄存器时返回 0xFF。0xFF 通常意味着从机没有真正驱动数据线或者寄存器地址不对。第四步查 GT911 手册发现复位时序决定了 I2C 地址。如果复位时 INT 引脚为低地址是 0x5D如果 INT 为高地址是 0x14。我们的硬件上 INT 引脚悬空导致地址不确定。第五步把 INT 引脚加上拉电阻确保复位时为高地址固定为 0x14。问题解决。这个案例说明ACK 正常不代表通信正常。从机可能响应了地址但内部状态不对返回的数据就是无效的。5.3 常见问题速查表现象可能原因排查方法完全无波形主机 I2C 未初始化、引脚复用未配置检查 GPIO 复用和时钟使能SCL 有波形 SDA 无变化SDA 引脚配置错误、从机未响应示波器双通道对比地址后 NACK从机地址错误、从机未上电逻辑分析仪解码地址数据错误时序不满足、上拉不足、干扰示波器看上升沿和毛刺总线死锁主从复位不同步手动发送 9 个时钟恢复时好时坏接触不良、上拉临界、干扰多次触发抓异常波形6. 几个容易被忽略的细节6.1 电平转换电路的影响很多系统里主控是 3.3V而从机是 5V中间需要电平转换。常见的电平转换方案有 MOS 管方案和专用芯片方案。MOS 管方案在 I2C 上有个问题当一侧拉低时另一侧通过体二极管被拉低但上升时依赖上拉电阻如果两侧上拉电阻都比较大上升沿会变得更缓。我实测过用 2N7002 做电平转换两侧各 4.7kΩ 上拉400kHz 下上升沿达到 600ns 以上通信开始出错。把上拉改成 2.2kΩ 之后恢复正常。所以加了电平转换之后上拉电阻要重新计算不能照搬原来的值。6.2 多从机场景的电容累积每增加一个从机总线电容就增加一些。PCB 走线大约每厘米 1-2pF器件引脚大约 5-10pF排线每厘米可能 10pF 以上。如果挂了 8 个从机加上排线总线电容很容易超过 400pF这是 I2C 规范的上限。超过之后上升沿会明显变缓通信距离和速率都要降。解决办法是减小上拉电阻或者用 I2C 多路复用器把总线分段每段单独挂从机。6.3 软件 I2C 和硬件 I2C 的差异软件 I2C 用 GPIO 模拟时序灵活性高但时序精度受中断影响。如果系统里有高优先级中断软件 I2C 的时钟可能会被拉长导致从机超时。硬件 I2C 由外设自动产生时序精度高但配置复杂出问题时不好调试。我的经验是调试阶段先用软件 I2C 确认从机能正常工作再切到硬件 I2C 优化性能。这样能把硬件问题和软件问题分开。6.4 上电顺序和复位时序有些从机对电源和信号的上电顺序有要求。比如某些传感器要求 VCC 先上然后 SDA/SCL 才能有电平否则会通过 ESD 保护二极管漏电导致总线异常。还有的从机需要特定的复位时序比如复位引脚拉低一定时间然后在特定引脚上产生特定电平来选地址。这些细节在手册里通常写得很清楚但容易被忽略。提示调试新器件时先把手册里的Power-Up Sequence和Reset Timing两节仔细看一遍能避免很多莫名其妙的问题。7. 工具选型与实战建议7.1 万用表、示波器、逻辑分析仪怎么选三种工具各有定位不是替代关系万用表查通断、查静态电平、查短路。几十块钱的够用。示波器看波形质量、上升沿、毛刺、死锁。建议带宽 100MHz 以上双通道。逻辑分析仪解码协议、看 ACK、看数据。几十块钱的 8 通道够用。如果预算有限优先级是万用表 逻辑分析仪 示波器。因为大部分 I2C 问题通过静态测量和协议解码就能定位示波器主要用于排查信号完整性问题。7.2 抓波形的几个实用技巧用单次触发抓偶发问题。时好时坏的问题最难查用单次触发模式设置好触发条件让设备反复运行抓到异常波形后自动停止。双通道对比 SCL 和 SDA。单独看一条线很难判断问题两条线一起看才能确定时序关系。用余辉模式看抖动。如果波形有抖动用余辉模式累积多次波形能看出抖动的范围和规律。保存波形供后续分析。很多示波器支持保存波形到 U 盘抓到的异常波形保存下来方便慢慢分析或者对比。7.3 代码层面的防御性设计硬件排查完之后软件层面也要做一些防御// I2C 读写超时保护 #define I2C_TIMEOUT_MS 100 int i2c_write_with_timeout(uint8_t addr, uint8_t reg, uint8_t data) { uint32_t start get_tick_ms(); while (i2c_is_busy()) { if (get_tick_ms() - start I2C_TIMEOUT_MS) { i2c_bus_recovery(); // 超时后尝试恢复总线 return -1; } } // 正常写入流程 return i2c_write(addr, reg, data); }这段代码的核心是任何 I2C 操作都要有超时。没有超时保护的 I2C 代码一旦总线死锁整个系统就卡住了。加上超时和恢复机制之后即使偶尔死锁也能自动恢复。另外初始化的时候建议先做一次总线恢复确保总线处于空闲状态再开始通信。这个习惯能避免很多上电时的偶发问题。7.4 关于 ACK 的一个常见误解最后说一个很多人搞混的点ACK 是接收方发的不是发送方发的。主机写数据时ACK 由从机发主机读数据时ACK 由主机发。所以看波形的时候要明确当前是谁在发送、谁在接收。在读操作的最后一个字节主机发 NACK这是告诉从机不要再发了。如果主机错误地发了 ACK从机会继续发送下一个字节导致数据错位。这个细节在写 I2C 驱动的时候特别容易出错尤其是用 GPIO 模拟的时候。我在实际项目中养成的习惯是每次调试新的 I2C 器件先用逻辑分析仪抓一次完整的读写时序确认地址、寄存器、数据、ACK 都对得上再开始写驱动代码。这样能把协议层的问题提前排除写代码的时候只需要关注业务逻辑。踩过几次坑之后你会发现I2C 的问题百分之八十都能通过静态测量 协议解码定位剩下的百分之二十才需要示波器深入分析信号完整性。工具不在多在于用对顺序。