ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

I2C通信排查实战:万用表、示波器与ACK深度分析

I2C通信排查实战:万用表、示波器与ACK深度分析 1. 为什么I2C排查值得单独写一篇I2C这玩意儿说简单是真简单两根线一挂上拉电阻一焊代码里调个库函数就能读写。但说难也是真难多少人卡在一个ACK位上耗掉一整个下午示波器抓出来的波形看着挺正常可设备就是不响应。我自己就经历过用万用表量了半天电压都对着最后发现是从机地址写错了一位这种事。这篇东西面向的是手上有实际板子、正在调I2C外设的嵌入式开发者不管你是用STM32的硬件I2C还是ESP32上跑软件模拟或者是Linux下通过i2c-dev操作传感器排查思路是通用的。我会从最基础的工具选择讲起把万用表、示波器、逻辑分析仪各自能干什么、不能干什么说清楚然后一步步走到ACK位的深度分析最后给出一套可以照着走的排查流程。核心关键词就几个I2C、万用表、示波器、ACK、排查流程。整篇内容围绕这五个词展开不跑题。先说一个基本认知I2C的问题90%出在物理层和时序层只有10%是软件逻辑问题。但很多人一上来就怀疑代码改了半天驱动结果发现是上拉电阻没焊。所以排查顺序很重要从物理层往上走别跳步。2. 排查工具的选择与各自的能力边界2.1 万用表能做什么、不能做什么万用表在I2C排查里的定位很明确静态检查工具。它测不了动态波形但能帮你排除一大批低级问题。具体来说万用表能干这几件事测SDA和SCL的对地电压。正常空闲状态下两根线都应该被上拉电阻拉到VCC附近。如果你用的是3.3V系统量出来应该在3.2V到3.3V之间。如果只有1点几伏甚至0V那说明上拉电阻没接、阻值太大、或者线路短路了。测上拉电阻的阻值。断电情况下量SDA到VCC、SCL到VCC的电阻应该在1k到10k之间。常见值是4.7k和2.2k。如果量出来是无穷大电阻虚焊或者根本没焊。如果量出来接近0那可能是短路。测线路通断。从主控引脚到从机引脚用蜂鸣档量一下是不是真的连通了。PCB走线断裂、排线接触不良这些都能查出来。测供电电压。从机芯片的VCC引脚是不是正常供电这个用万用表最直接。但万用表有个致命局限它看不到时序。I2C通信速率通常在100kHz到400kHz甚至到1MHz或3.4MHz。万用表的采样率根本跟不上你只能看到平均电压看不到单个bit的跳变。所以万用表只能告诉你线路上有电压不能告诉你数据在正确的时间跳变了。注意用万用表测I2C线路电压时一定要在总线空闲状态下测。如果正在通信万用表读数是抖动的平均值没有参考意义。2.2 示波器的核心价值与选型考量示波器是I2C排查的主力工具。它能同时抓SDA和SCL的波形让你看到每一个bit的跳变、每一个ACK位的电平。选示波器看几个关键指标带宽I2C最快也就几MHz理论上20MHz带宽的示波器就够了。但考虑到要看清上升沿的细节建议至少100MHz带宽。带宽不够的话上升沿会被圆滑掉你看到的波形和实际波形差别很大。通道数至少双通道一个接SDA一个接SCL。四通道更好可以同时看使能信号、中断信号等。存储深度这个很关键。I2C一次传输可能有几十个字节如果存储深度不够你只能看到一小段波形。建议至少1Mpts。触发能力能不能做协议触发比如触发在地址匹配但ACK缺失的条件下。高端示波器有这个功能能帮你快速定位问题。我用过力科的示波器它的I2C协议解码功能做得比较完善能直接在波形上叠加解码结果地址、数据、ACK位一目了然。鼎阳的示波器也有协议解码选件性价比更高一些。如果预算有限国产的入门级示波器也能用只是解码功能可能需要额外购买选件。示波器抓I2C波形的几个实操要点探头要用10x档1x档的带宽不够而且容性负载大会影响信号质量。探头地线要尽量短长地线会引入振铃和噪声。触发方式选下降沿触发或边沿触发触发电平设在VCC的一半左右。时基设置要合适100kHz的I2C一个bit是10微秒一个字节加ACK是90微秒。时基设在10微秒/格到50微秒/格比较合适。2.3 逻辑分析仪性价比之选逻辑分析仪和示波器的区别在于示波器看的是模拟波形逻辑分析仪看的是数字电平。逻辑分析仪只关心高还是低不关心具体的电压值。对于I2C排查来说逻辑分析仪其实更实用。原因有几个通道多便宜的逻辑分析仪就有8通道甚至16通道可以同时抓多条总线。自带协议解码直接告诉你这次传输的地址是什么、数据是什么、ACK有没有。采样率高能抓到高速I2C的细节。价格便宜几十块钱的入门款就能用。但逻辑分析仪看不到信号质量。如果上升沿太慢、有振铃、电平幅度不够逻辑分析仪可能显示正常但实际芯片已经识别错了。所以逻辑分析仪和示波器是互补的不是替代关系。我的建议是先用量子分析仪抓协议层确认地址、数据、ACK对不对如果有问题再用示波器看物理层的信号质量。2.4 工具选择速查表工具能解决的问题不能解决的问题推荐使用场景万用表电压、通断、电阻时序、波形上电前静态检查示波器信号质量、时序、ACK电平长时间协议解码物理层深度分析逻辑分析仪协议解码、地址数据信号质量、电平幅度协议层快速定位专用I2C调试器主动发起读写、扫描地址物理层问题从机地址确认3. I2C物理层排查从电压到上拉电阻3.1 上电前的静态检查在给板子通电之前先用万用表做一轮静态检查。这一步能排除掉大部分低级错误。第一步确认SDA和SCL没有对地短路。用万用表的二极管档或者电阻档量SDA对GND、SCL对GND的电阻。正常应该是几十千欧以上如果接近0说明有短路可能是焊接桥连或者芯片内部损坏。第二步确认上拉电阻存在且阻值合适。量SDA到VCC、SCL到VCC的电阻。常见上拉电阻值在1k到10k之间。阻值的选择有个计算公式上拉电阻的最大值由上升时间决定R_max t_r / (0.8473 × C_bus)其中t_r是允许的最大上升时间标准模式I2C是1000ns快速模式是300ns。C_bus是总线电容包括PCB走线电容和引脚电容一般估算为10pF到50pF每英寸走线。举个例子如果总线电容是100pF快速模式下t_r300ns那么R_max 300ns / (0.8473 × 100pF) ≈ 3.5kΩ。所以上拉电阻不能太大否则上升沿太慢。上拉电阻的最小值由灌电流决定R_min (VCC - V_OL) / I_OL标准模式I2C的I_OL是3mA快速模式是6mA。V_OL通常取0.4V。如果VCC3.3V快速模式下R_min (3.3 - 0.4) / 6mA ≈ 483Ω。所以上拉电阻不能太小否则灌电流超过芯片承受能力。综合下来3.3V系统、快速模式I2C上拉电阻选2.2k到4.7k比较稳妥。第三步确认从机地址。这个虽然不算物理层但值得在静态检查阶段就确认。查从机芯片的数据手册找到7位地址。注意有些芯片的地址是固定的有些可以通过引脚配置。常见坑是数据手册写的是8位地址包含读写位而代码里需要的是7位地址。比如数据手册写0xA0实际7位地址是0x50。3.2 上电后的电压测量上电之后先别急着通信用万用表量一下SDA和SCL的静态电压。正常情况两根线都应该被上拉到VCC。3.3V系统量出来应该在3.2V到3.3V。如果量出来是1.5V左右说明上拉电阻太大或者有多个设备在拉低线路。如果量出来是0V说明线路被短路到地了。这里有个细节有些I2C从机在未初始化时会拉低SDA或SCL。比如某些传感器在上电复位期间会保持SCL为低。这种情况下你需要先给从机发送复位序列或者等待从机初始化完成。还有一种情况总线死锁。如果主机在通信过程中复位而正好在从机拉低SDA的时候从机会一直等待时钟信号导致SDA一直被拉低。这时候量SDA电压就是低的。解决方法是在SCL上手动发送9个时钟脉冲让从机释放SDA。实操心得我遇到过GT911触摸屏I2C通信失败的情况量电压发现SDA被拉低到0.3V。后来查出来是触摸屏的复位时序不对芯片没有正常初始化。重新调整复位引脚的时序后SDA就恢复正常了。所以电压异常不一定是硬件问题也可能是从机状态不对。3.3 用示波器看信号质量电压正常不代表信号质量好。用示波器看SDA和SCL的波形重点关注几个方面上升沿时间。从0.3×VCC上升到0.7×VCC的时间。标准模式要求小于1000ns快速模式小于300ns。如果上升沿太慢波形会变成圆顶可能导致从机识别错误。上升沿慢的原因通常是上拉电阻太大或者总线电容太大。下降沿时间。I2C的下降沿是由开漏输出拉低的通常很快在几十纳秒级别。如果下降沿也很慢说明线路阻抗有问题。电平幅度。高电平应该接近VCC低电平应该接近0V。如果高电平只有2V3.3V系统说明上拉不足或者有漏电。如果低电平有0.5V以上说明灌电流能力不够或者地线有问题。振铃。在跳变沿上如果有明显的振铃说明阻抗不匹配。振铃可能导致从机误触发。解决方法是在线路末端加小电阻22Ω到100Ω做阻抗匹配或者缩短走线长度。毛刺。如果波形上有窄毛刺可能是串扰或者电源噪声。检查SDA和SCL是否走得太近或者电源去耦是否充分。3.4 上拉电阻的选型计算实例假设你有一个3.3V系统I2C总线上挂了3个设备PCB走线总长度约10cm走线电容约1pF/cm加上每个引脚的电容约10pF总线总电容C_bus ≈ 10cm × 1pF/cm 3 × 10pF 40pF。快速模式I2Ct_r最大300ns。R_max 300ns / (0.8473 × 40pF) ≈ 8.8kΩ。快速模式I_OL6mAV_OL0.4V。R_min (3.3 - 0.4) / 6mA ≈ 483Ω。所以上拉电阻在483Ω到8.8kΩ之间。考虑到功耗和上升沿的余量选2.2kΩ比较合适。如果通信速率只有100kHz可以放宽到4.7kΩ。如果总线上设备更多、走线更长总线电容会增大R_max会减小。比如C_bus200pF时R_max ≈ 1.8kΩ。这时候2.2kΩ就有点勉强了需要降到1.5kΩ左右。4. 协议层排查地址、数据与ACK4.1 I2C数据帧格式回顾在深入ACK排查之前先把I2C的数据帧格式理清楚。I2C的每一次传输都有固定的结构起始条件StartSCL为高时SDA从高变低。这是通信开始的标志。地址帧7位从机地址 1位读写位。读写位0表示写1表示读。地址是从高位开始发送的。ACK/NACK位发送完8位地址后主机释放SDA从机如果存在且地址匹配会把SDA拉低这就是ACK。如果从机不存在或地址不匹配SDA保持高这就是NACK。数据帧每个数据字节8位高位先发。每发送一个字节接收方都要回一个ACK。停止条件StopSCL为高时SDA从低变高。通信结束。这里有个容易混淆的点地址是7位但传输时是8位。第8位是读写位。所以如果你看到示波器上解码出来是0xA0那实际7位地址是0x50写操作。如果是0xA17位地址还是0x50读操作。4.2 用示波器抓ACK位ACK位是I2C排查的核心。用示波器抓ACK需要把触发点设在地址帧的第9个时钟周期。具体操作探头接SDA和SCL地线接好。触发方式选SCL的下降沿触发触发电平设在VCC/2。时基设在10微秒/格左右让屏幕上能看到完整的地址帧。单次触发模式然后让主机发起一次I2C传输。抓到波形后数时钟周期。第1到第7个时钟周期是地址位第8个是读写位第9个是ACK位。在第9个时钟周期如果SDA被拉低说明从机回了ACK。如果SDA保持高说明从机没有响应。注意有些示波器的协议解码功能会自动标注ACK位。如果解码显示ACK或A说明从机响应了。如果显示NACK或N说明从机没有响应。4.3 ACK缺失的常见原因ACK缺失是I2C排查中最常见的问题。原因可以分成几类地址错误。这是最常见的。从机地址写错了从机自然不会响应。检查数据手册确认7位地址。注意有些芯片的地址是可以通过引脚配置的检查配置引脚的电平。从机未上电或未初始化。从机芯片没有供电或者复位引脚没有释放或者时钟配置不对。用万用表量从机的VCC和复位引脚。从机忙。有些从机在上一次操作完成之前不会响应新的请求。比如EEPROM在写周期内不会响应。查数据手册确认从机的忙状态时间。时序问题。SCL频率太高从机跟不上。或者起始条件、停止条件的时序不对。用示波器检查时序参数是否符合数据手册要求。信号质量问题。上升沿太慢、振铃、电平幅度不够导致从机识别错误。用示波器检查信号质量。总线电容太大。挂的设备太多走线太长导致上升沿太慢。减少设备数量或者减小上拉电阻。从机地址冲突。总线上有两个设备地址相同同时响应导致信号冲突。检查所有设备的地址。4.4 用逻辑分析仪做协议解码逻辑分析仪的优势在于协议解码。把SDA和SCL接到逻辑分析仪的两个通道设置I2C解码就能看到完整的传输内容。解码结果通常包括起始条件地址7位 读写位ACK/NACK数据字节停止条件如果解码结果显示NACK说明从机没有响应。这时候可以尝试用逻辑分析仪的地址扫描功能遍历所有可能的7位地址看哪个地址有ACK。这个功能在不确定从机地址的时候特别有用。我用过一款几十块钱的逻辑分析仪配合开源软件能直接扫描I2C地址。扫描一遍就能知道总线上有哪些设备、地址是什么。这比查数据手册快多了。4.5 从机主动更新主机寄存器的场景有些应用场景比较特殊从机需要主动更新主机的寄存器。比如某些传感器在检测到事件后会通过I2C通知主机。标准I2C是主从架构从机不能主动发起通信。但有些芯片支持从机主动模式通过拉低一个中断引脚来通知主机然后主机再发起读操作。排查这种场景时重点看中断引脚。用示波器抓中断引脚的波形确认从机有没有拉低。如果中断引脚正常但主机读不到数据那问题可能在主机的读时序上。还有一种情况从机通过I2C的多路复用器MUX连接到主机。MUX的通道切换需要时间如果主机在MUX切换后立即发起通信可能会失败。解决方法是在MUX切换后加一个小延时。5. 完整排查流程与实战案例5.1 从零开始的排查步骤我整理了一套从零开始的I2C排查流程按顺序走基本能覆盖90%的问题。第一步静态检查断电用万用表量SDA、SCL对GND的电阻确认没有短路。量上拉电阻的阻值确认在合理范围。量SDA、SCL到主控和从机的通断确认线路连通。确认从机地址查数据手册注意7位和8位的区别。第二步上电检查上电用万用表量从机VCC确认供电正常。量SDA、SCL的静态电压确认被上拉到VCC。量从机复位引脚确认复位已释放。第三步示波器看波形接示波器双通道分别接SDA和SCL。触发方式选SCL下降沿单次触发。让主机发起一次传输抓波形。检查起始条件、地址帧、ACK位、停止条件。检查上升沿时间、电平幅度、有无振铃。第四步逻辑分析仪解码接逻辑分析仪设置I2C解码。抓一次完整传输看解码结果。确认地址、数据、ACK是否正确。如果有NACK用地址扫描功能确认从机地址。第五步软件层检查确认I2C时钟频率设置正确。确认读写时序符合数据手册要求。确认没有其他任务占用I2C总线。确认中断优先级没有冲突。5.2 实战案例STM32读取BH1750失败我之前用STM32的硬件I2C读取BH1750光照传感器一直读不到数据。按流程排查静态检查上拉电阻4.7k电压3.3V通断正常。BH1750的地址是0x237位代码里写的是0x468位写地址这个没问题。上电检查VCC正常SDA和SCL静态电压3.3V复位引脚正常。示波器抓波形发现地址帧发送后第9个时钟周期SDA保持高没有ACK。说明从机没有响应。逻辑分析仪解码确认地址是0x46NACK。这时候怀疑是地址问题。用逻辑分析仪扫描地址发现0x23有ACK。原来代码里虽然写了0x46但底层驱动在发送时又做了一次左移导致实际发送的地址变成了0x8C。修正驱动后通信正常。这个案例的教训是地址的7位和8位格式一定要统一。有些驱动库要求传7位地址有些要求传8位。混用就会出错。5.3 实战案例ESP32休眠后I2C复位ESP32在深度休眠后唤醒I2C总线有时候会死锁。原因是休眠期间SDA被从机拉低唤醒后主机没有发送足够的时钟脉冲来释放总线。解决方法是在I2C初始化之前先手动发送9个时钟脉冲。具体做法是把SCL配置为GPIO输出手动翻转9次然后把SDA和SCL重新配置为I2C功能。这个问题的根源是I2C总线的状态机没有复位。标准I2C协议里如果SDA被拉低而SCL为高这被解释为起始条件。从机在等待时钟脉冲。发送9个脉冲后从机会完成当前字节的接收然后释放SDA。实操心得ESP32的I2C复位问题在休眠应用中很常见。建议在I2C初始化函数里都加上总线复位逻辑不管有没有用到休眠。这样能避免很多偶发性的通信失败。5.4 常见问题速查表现象可能原因排查方法解决方法静态电压0V短路或从机拉低万用表量电阻查短路点或发送时钟脉冲静态电压1.5V上拉不足量上拉电阻减小上拉电阻ACK缺失地址错误逻辑分析仪扫描修正地址ACK缺失从机未上电量VCC检查供电ACK缺失时序不对示波器看时序调整时钟频率数据错误信号质量差示波器看波形减小上拉加阻抗匹配偶发失败总线死锁示波器看SDA加总线复位逻辑读不到数据寄存器地址错误查数据手册修正寄存器地址通信速率上不去总线电容大量上升沿减小上拉电阻6. 几个容易被忽略的细节6.1 时钟拉伸的处理I2C从机可以通过拉低SCL来暂停通信这叫时钟拉伸。主机必须支持时钟拉伸否则会出错。用示波器看SCL波形如果发现SCL在某一段时间内保持低电平那就是从机在拉伸时钟。主机这时候应该等待而不是强行继续发送时钟。有些主机的硬件I2C不支持时钟拉伸或者支持得不好。如果从机需要时钟拉伸可能需要改用软件I2C。6.2 多主机的仲裁如果总线上有多个主机需要处理仲裁。仲裁发生在SDA上如果一个主机发送高电平另一个发送低电平发送低电平的主机赢得仲裁发送高电平的主机退出。用示波器看SDA波形如果发现SDA的电平和预期不符可能是仲裁发生了。多主机系统的排查更复杂建议先用单主机确认基本通信正常再逐步加入其他主机。6.3 电平转换的处理如果主控和从机的电压不同比如主控3.3V从机5V需要电平转换。常见的电平转换方案有MOS管电平转换成本低但速率受限。专用电平转换芯片速率高但成本高。电阻分压只适合单向通信I2C是双向的不适用。电平转换电路出问题也会导致I2C通信失败。用示波器看转换后的波形确认电平幅度和上升沿是否正常。6.4 软件I2C的时序控制软件I2C的时序完全由代码控制灵活性高但容易出问题。常见问题包括延时不够导致时序不满足从机要求。延时太长导致通信速率太低。没有正确处理时钟拉伸。没有正确处理ACK。用示波器看软件I2C的波形重点检查SCL的高电平和低电平时间是否符合数据手册要求。软件I2C的延时通常用空循环或者定时器实现需要根据主频精确计算。6.5 I2C扩展和多路复用的排查当总线上设备太多或者地址冲突时会用I2C多路复用器来扩展。MUX的排查要点确认MUX的地址和通道选择寄存器。确认MUX的通道切换时间。确认MUX的使能引脚状态。用示波器看MUX的通道选择引脚确认切换信号正常。如果MUX切换后通信失败可能是切换时间不够加一个小延时试试。7. 写在最后I2C排查这件事工具是手段思路是关键。万用表、示波器、逻辑分析仪各有各的用处但最重要的是按顺序排查先静态后动态先物理层后协议层先确认地址再查数据。我自己的习惯是拿到一块新板子先不上电用万用表把I2C线路全部量一遍。确认没有短路、上拉电阻正常、线路连通。然后再上电用示波器抓一次波形确认信号质量。最后用逻辑分析仪解码确认协议层没问题。这套流程走下来大部分问题都能定位到。还有一个经验遇到问题先怀疑硬件再怀疑软件。我见过太多人一上来就改代码改了半天发现是上拉电阻没焊。硬件问题用工具一量就清楚软件问题反而需要更多时间调试。最后分享一个小技巧如果手头没有逻辑分析仪可以用示波器的协议解码功能代替。虽然不如逻辑分析仪方便但也能看到地址、数据和ACK。如果连示波器都没有那就用万用表量静态电压至少能排除掉短路和上拉问题。工具不是越贵越好关键是用对地方。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进