做嵌入式的,谁没被 I2C 折磨过呢。焊好板子,上电,读寄存器,结果返回你一堆 0xFF,或者设备地址石沉大海,连个 ACK 都不给。这种时候,有人靠玄学改代码(把延时从 5us 改成 8us),有人靠信仰狂换芯片,但真正靠谱的路径只有一个:把信号测出来,让波形说话。这篇文章就按我自己排查 I2C 问题的完整思路来写,从万用表量静态电平开始,到示波器抓 ACK 波形,再到逻辑分析仪做协议级解码,把整个流程和盘托出,适合刚碰 I2C 的新手,也适合配了工具却还没体系化用过一遍的老哥们。
1. I2C 信号排查前的必备认知
1.1 两根线上到底在传什么
I2C 这个东西,物理层简单到就两根线:SCL(时钟)和 SDA(数据)。但恰恰因为简单,排查起来反而容易懵。很多新手上来就拿示波器怼着 SDA 看,看半天也不知道自己要找什么。原因就是没在脑子里建立起完整的时序模型。
I2C 是开漏结构的总线,这个特性非常关键。所谓开漏,就是设备只能把线拉低,不能主动拉高。线什么时候变成高电平?靠总线上的上拉电阻。所以空闲状态下,SCL 和 SDA 都应该是被上拉到 VDD 的高电平。一旦有设备要发数据,就把 SDA 拉低;要产生时钟,就把 SCL 拉低再释放。这个“只能拉低、被动拉高”的特性,决定了后面大量排查手段的逻辑——我拿万用表量某个引脚的静态电平,本质上就是在验证上拉和短路状态。
再看时序。I2C 通信的起点叫做起始条件(START):SCL 为高时,SDA 产生一个下降沿。结束是停止条件(STOP):SCL 为高时,SDA 产生一个上升沿。中间的数据,每发 8 位,第 9 个时钟周期交给接收方回应答。地址、寄存器号、数据,全是按这个节奏一帧一帧走的。理解这三板斧(起始、8位数据、应答),后面无论看示波器还是逻辑分析仪,都能顺着数出来。
1.2 为什么 ACK 是排查里最关键的一环
在 I2C 调试里,ACK(应答信号)的优先级极高。原因很简单:它是整条通信链路上第一个能体现“从机到底在不在、有没有醒、认不认你”的信号。
主机发完一个字节地址(8 位,实际是 7 位地址 + 1 位读写标志)之后,第 9 个 SCL 时钟周期,主机释放 SDA,如果从机存在并且地址匹配,它会主动把 SDA 拉低,告诉主机“我在,收到了”,这就是 ACK。如果从机不在、地址不对,或者它正忙着没法响应,SDA 就会保持高电平,主机收到的是 NACK。
所以排查 I2C 问题的第一步就是分清:是根本没出来波形(物理层挂了),还是波形出来了但没有 ACK(设备没响应),还是 ACK 有但数据是错的(协议层问题)。看到 ACK,至少说明地址对了,寻址阶段成功了,后面再查寄存器读写就有明确方向。看不到 ACK,那就是从机压根没参与通信,问题十有八九在地址、复位、电源或者上拉电阻上。顺着这个思路排查,比乱换软件配置高效得多。
1.3 工具选型:万用表、示波器、逻辑分析仪何时用哪个
很多人的困惑不是不会用工具,而是不知道到底该用哪个工具。我按自己的使用习惯整理一下:
万用表是所有排查的起手式。它便宜、随时能用,适合查静态问题:供电有没有、SCL/SDA 两个引脚是否被拉高到 VDD、上拉电阻装没装、走线有没有短路。但万用表测不了动态时序,I2C 在 100kHz 标准模式下,一个 bit 只有 10us,万用表的采样能力完全跟不上,所以看到动态问题就要上示波器。
示波器是排查时序的主力。能看真实波形,能触发捕捉,能算时间参数。带解码功能的示波器更是直接能帮你把 SDA 上的字节解出来。适合定位:起始/停止条件有没有、ACK 到底有没有、时序边沿够不够快、信号完整性是否达标。
逻辑分析仪则是“批量干活”和“看协议全景”的利器。它不能测电压幅度,只能区分高低电平,但它采样通道多、存储深度大,能把一整段通信从头录到尾,再用软件把地址、数据、ACK 全部解出来。适合看通信是怎么“跑”的:哪一帧 NAK 了、哪一次读花了多久、从机是不是在时钟拉伸。
一句话总结我的选择习惯:先拿万用表排除物理层,再上示波器抓关键波形,最后用逻辑分析仪看完整交互流程。
2. 万用表测 I2C:先把物理层和静态电平查干净
2.1 上电后量 SCL 和 SDA 的空闲电平
拿到一块 I2C 不通的板子,我的第一个操作不是写测试代码,而是拿万用表量电压。把表拨到直流电压档(20V 档或自动档),红笔点 SCL,黑笔点 GND。如果总线正常工作,空闲时应该量到一个接近电源电压的值,比如 3.3V 系统就是 3.2~3.3V,5V 系统就是 4.8~5V。
为什么?因为开漏结构配上上拉电阻,空闲时没人拉低,SDA 和 SCL 的电压就应该等于上拉电阻接的电源电压。这个电压有两个信息量:一是上拉电阻有没有接、接得对不对;二是设备有没有把总线钳在低电平。
我遇到过很典型的案例:从机芯片没焊好,其中一个引脚虚焊没跟总线连通,从机的 SDA 引脚内部处于不定状态,外部量出来就是 SCL 正常 3.3V、SDA 只有 0.8V。这种畸变电压单靠“看波形”是抓不到的,反而是万用表最能快速暴露问题。
特别注意,如果量出来 SCL 或 SDA 是 0V,先别急,把设备断电,用电阻档量这两个引脚到 GND 的阻抗。如果接近 0Ω,那就是总线被短路了,优先查焊接和走线。如果还有几百欧,往往是某个芯片内部损坏或引脚配置错误,把总线“钉死”在地上。
2.2 用蜂鸣档查上拉电阻和走线连通性
上电测试之前,断电状态下我会顺手用万用表蜂鸣档把物理链路过一遍。重点查两个方向:上拉电阻有没有贴对位置,以及 SDA/SCL 两个节点上所有设备的引脚是否真正共接。
具体做法:把板子断电,蜂鸣档(二极管/通断档),两个表笔分别点在 MCU 的 SCL 引脚和第一个从设备的 SCL 引脚,正常情况蜂鸣器应该响(导通)。再点 MCU 的 SDA 和最后一个设备的 SDA,同理。这时候注意,如果检测到导通但蜂鸣声音发闷、电阻值显示几百欧,而不是清脆的“滴”,就要警惕半焊或者过孔不良。
上拉电阻的检查也要单独做。4.7kΩ 是最常见的 I2C 上拉阻值,10kΩ 也行但边沿会慢一些,高速场景用 2.2kΩ。我看过不少翻车案例,是把 4.7kΩ 错贴成 470kΩ——从颜色上看棕红金金和黄紫红金确实容易混淆,量一下电阻才是靠谱的。阻值如果偏大,SDA/SCL 的上升沿会变成很缓的斜坡,到了高速频率下,设备就会因为电压来不及翻转到高电平而误判,表现就是通信时好时坏。
2.3 万用表的边界:它测不了什么
万用表能做的排查,止步于静态和物理层。它没法告诉你“起始条件里的下降沿是否达标”、“第 9 个时钟 SDA 到底有没有被拉低过”。这些动态信息是微秒级的,万用表完全看不见。
很多人被 I2C 问题卡住,就是因为一直拿万用表量了半天,量出来的电平都对,然后不知道下一步该干嘛。这时候就该切示波器了。有一个判断标准可以帮你快速决定何时升级工具:如果万用表量到的静态电平全部正常,且蜂鸣档通断检查也没发现问题,但通信依旧不通,那问题几乎可以肯定出在时序层面——不是没 ACK,就是 ACK 的时序不符合规范,或者波形边沿太差。此时必须看真实波形。
我的习惯是,只要项目里调试 I2C,示波器就得一直摆在桌上。万用表解决的是“有没有电、通没通”的问题,示波器解决的是“信号漂不漂亮、时序合不合规”的问题,两者是接力关系,不是二选一。
3. 示波器上手:把 I2C 波形完整抓下来
3.1 接线和触发的标准姿势
示波器测 I2C,接线其实非常简单,但很多人第一步就接错了。标准做法是双通道同时测:CH1 接 SCL,CH2 接 SDA,探头的地线夹子接到板子的 GND 参考点。这样你就能在屏幕上同时看到时钟和数据两根线的交互关系。
接完线之后,关键的几步设置:
- 触发放到 CH1(SCL),触发方式选上升沿。为什么选 SCL 上升沿而不是 SDA?因为 SCL 是时钟基准,它的上升沿标志着一个 bit 传输周期的开始,用它触发,波形在屏幕上比较稳定。
- 触发模式选 Normal(普通),不要用 Auto。Auto 模式下如果没有满足触发条件,示波器会一直乱扫,看起来像噪声一样,特别干扰判断。Normal 模式下,只有 SCL 出现上升沿才刷新波形,画面才稳定。
- 时基根据 I2C 速率来设。标准模式 100kHz 下,一个 bit 周期 10us,一帧地址加数据大概持续几百微秒,所以时基可以从 50us/div 左右开始,看到完整帧以后再缩小到 10us/div 或 5us/div 放大细节。
接好线、设好触发,再跑一段通信代码,示波器屏幕上就能稳定出现成组的方波了。我第一次看到完整 I2C 帧的时候,最大的感受是:这玩意儿确实能“一眼看穿”——SCL 是一串均匀脉冲,SDA 在对应的节拍上跳变,每一帧的开头都有一个明显的下降沿,那就是起始条件。
3.2 从波形上认出起始、数据和停止
示波器屏幕上的 I2C 波形,看起来是两条方波河:上面一条是 SCL 的等间隔脉冲;下面一条是 SDA 的跳变。看懂它们的配合,是 I2C 调试的必修课。
先看起始条件(START):在 SCL 为高电平的区间里,SDA 从高跳变到低,这个下降沿就是起始。接下来 SCL 开始产生 8 个脉冲,这 8 个脉冲对应第一个字节的 8 个 bit。SDA 在每个 bit 的高电平窗口里保持稳定——SCL 高电平期间 SDA 不能变,只有在 SCL 低电平期间才允许翻转,这是 I2C 数据传输的黄金规则,违反它的波形基本等于协议错误。
第 9 个时钟脉冲是应答位(ACK)。在这第 9 个 SCL 高电平期间,如果 SDA 被拉低,就是成功的应答。如果 SDA 一直保持高,就是 NACK。看到这里,你就完成了一次最基本的 I2C 协议级判读。
停止条件(STOP)则出现在通信结束时:在 SCL 高电平期间,SDA 从低跳变到高,一个上升沿。起始和停止都是 SDA 在 SCL 高电平时的边沿跳变,这是区分它们的唯一方式。所以看示波器波形时,不要去看 SDA 本身,要结合 SCL 的状态去理解 SDA 的行为。
3.3 带解码功能的示波器怎么用
现在的数字示波器,中端以上基本都带 I2C 解码功能,比如鼎阳、普源、力科的很多型号都有 I2C 触发和解码选项。这功能一旦用好,效率翻倍,因为示波器直接帮你把 SDA 上的字节解出来了,不用自己肉眼去数 bit。
我用过的方式是:在示波器菜单里找到 Decode(解码)或 Bus(总线)选项,选择协议类型为 I2C,然后指定哪一通道是 SCL、哪一通道是 SDA,再设一下阈值电压(一般是 1.65V 或 1.5V,视总线电平而定)。示波器就会在波形下方显示解码结果,比如“Start + Address: 0x3C Write + ACK + Data: 0x00 + NACK + Stop”。
有了这个功能,排查 ACK 问题的速度就快很多。之前靠肉眼要在波形里找第 9 个时钟,然后判断 SDA 高低,现在波形上直接标了 ACK 或 NACK,一眼就能看出是哪个地址没有得到响应。
但要注意,解码功能不是万能的。如果波形边沿太差(上升沿爬升太慢),解码器会把一个 bit 误判成两个 bit,解出来一堆乱码。这时候反而要关掉解码,用纯波形去看时序。我经验是:解码结果可信的前提是,波形本身方波轮廓清晰、边沿陡峭。如果解码乱,先修信号完整性,别急着质疑芯片。
3.4 实测:抓一个带 NACK 的波形
说一个我印象深刻的实测案例。当时调一块陀螺仪模块,读加速度寄存器,寄出去的地址 0xD0(7 位地址 0x68 + 写位 0),按理说应该 ACK。但读回来全是 0xFF。
示波器挂在 SCL/SDA 上,触发用 SCL 上升沿,跑了一遍读取代码,波形抓到之后我是这么一步步看的:
看 SDA 最开始的下降沿:起始条件存在,说明代码确实发起了通信。紧接着 SCL 出现 8 个脉冲,SDA 上也有跳变,地址字节确实发出去了。关键看第 9 个脉冲:SDA 在高电平期间纹丝不动,没有出现被拉低的痕迹。这就是明晃晃的 NACK。
看到这里,问题基本锁定:从机没认这个地址,或者从机根本没起来。接下来顺着查,发现模块的电源引脚电压虚低——万用表量出来只有 2.1V(设计是 3.3V),而芯片的低压欠压保护让内部逻辑没启动,自然不会回 ACK。补上供电之后,第 9 个脉冲 SDA 被稳稳拉低,ACK 出现了,读取数据马上就正常。
示波器的价值就在这儿:NACK 让你知道“没有从机响应”,万用表则进一步告诉你“从机没响应的原因是供电不够”。两个工具配合,定位又快又准。
4. ACK/NACK 深度解析:从波形看穿从机的“真实态度”
4.1 ACK 和 NACK 怎么从波形上精确辨认
ACK 的判断标准要精确到“第 9 个时钟周期的 SCL 高电平区间”。我教新手的时候,总是强调一个方法:先把波形展开,保证能看到完整的 9 个 SCL 脉冲,然后用光标把第 9 个脉冲的高电平区间框出来,再看这个区间里 SDA 是什么状态。
如果在这个窗口里 SDA 是低电平,且低电平一直保持到 SCL 下降到低,这是 ACK。注意一个细节:有些从机拉低 SDA 的时间窗很短,可能在第 9 拍的高电平后期才拉低,这时候如果只看“电平是否低”,容易误判。所以要确认的是“整个第 9 拍高电平区间内 SDA 的状态是否稳定为低”。
如果 SDA 在整个高电平期间都是高,那就是 NACK。还有一种情况更耐人寻味:SDA 在第 9 拍有一个“凹下去”的短暂低脉冲,但没有保持住就弹回高电平。这通常说明从机尝试了应答但能力不足——比如它的内部 I2C 控制器被复位了、或者输出驱动没准备好。这种波形我见过几次,是发生在从机刚上电、还没完成初始化但主控已经发起了通信的场景。解决办法也很简单:主控延时等从机 ready,发送前给从机留出初始化时间。
4.2 为什么总出现 NACK:五大典型原因
总结这些年摸过的坑,NACK 的出现原因基本逃不出这几类。
第一,地址根本没对上。这个最常见,也最容易忽视。I2C 地址分 7 位和 8 位两种写法,很多传感器数据手册写的是 8 位格式(比如 0x3C),但实际驱动库里用的是 7 位格式(0x1E),或者反过来。主控发出去的地址和从机地址不匹配,从机没有理由响应,必然 NACK。排查方法是看波形:如果能看到完整地址字节且解码功能显示地址值,就能直接比对。
第二,从机没上电、没复位或不处于正常模式。供电异常、复位引脚一直被拉低、或者从机进入了低功耗关断状态,它都会对总线“装死”。这种情况也别急着怀疑协议,先用万用表量供电和复位引脚。
第三,上拉电阻和总线电容不匹配。当 SDA 下降沿不够陡、或者上升沿爬升太慢时,设备和示波器对高低电平的判断都可能出错。常见症状是“在短线上能通,接了长线或加了开关后就不通”,这通常是总线上电容变大导致的。
第四,从机时钟拉伸(clock stretching)。有些传感器(比如部分气压计、触摸控制器)在响应读取前需要时间准备数据,会把 SCL 主动拉低一段时间。如果主控 I2C 外设没有处理时钟拉伸的能力,就会在从机拉低 SCL 期间误判超时,后面的 ACK 自然就错乱。
第五,总线锁死。某个从机因为内部逻辑错误把 SDA 一直拉在低电平,整个总线就瘫痪了。这时你会看到 SDA 一直为低、SCL 还在跑,但没有任何设备能响应。复位从机是常规解药,实在不行就拔电重启。
4.3 不靠解码功能:手动“数时钟”法确认 ACK
示波器没有 I2C 解码功能的情况下,也别慌。手动数时钟的方法是:先把示波器水平档位调大(比如 20us/div),把完整的 SDA 起始条件拉出来,然后从起始条件后沿开始数 SCL 脉冲。从第一个脉冲开始,数到第 9 个,在屏幕上用光标或者肉眼定位第 9 个脉冲的高电平区间,然后斜眼瞄一眼 SDA。
这个方法看着原始,但极其可靠。有一次我在客户现场,用的是一台老型号的模拟示波器,根本没有解码、没有光标测量,就是靠这个办法把 ACK 判断出来的。实际操作中要注意:SDA 会在数据位期间频繁跳变,所以眼睛要盯紧 SCL 的第 9 个上升沿,在那个边沿之后到第 9 个下降沿之前的窗口里,SDA 的状态就是应答状态。
数时钟最怕的就是数着数着数丢了。我自己的窍门是先数 5 个,再数 4 个,也就是把第 9 个脉冲当成“5+4”来定位,比从 1 一直数到 9 不容易迷路。这个方法虽然土,但可以救急。
5. 实操场上的五类典型故障复盘
5.1 设备地址不对导致的“双目失明”
某次调一块 0.96 寸 OLED 屏,写驱动后屏幕不亮,看命令交互发现发出去的命令都没回 ACK。用示波器抓波形,解码显示地址是 0x78,而模块默认地址实际是 0x3C。问题出在驱动代码里把 I2C 地址写成 8 位格式,主控 I2C 外设按 7 位地址模式发送,结果地址高半字节对不上。
这个案例很典型,I2C 地址的 7 位/8 位写法(还有部分芯片支持硬件引脚配置地址)本身就是排查时的头号刺客。尤其是一些模块,实际地址除了数据手册外还要看板卡的跳线电阻,有时候跳线没焊,地址就是备用的那个。波形上看地址字节和实际预期对不上,基本就能确诊。
5.2 上拉电阻偏大导致的“时好时坏”
有块板子 I2C 上挂了个传感器,常温下能跑,用手靠近或者按一下 PCB 就死机,重新初始化又好了。示波器看波形,发现 SDA 的上升沿从 0V 到高电平的爬升时间明显偏慢——上升沿快有 8us 多了。量了一下板上的上拉电阻,10kΩ,而这块板子总线上挂了 4 个设备,总线电容偏大,10kΩ 上拉在 400kHz 的速率下完全拉不动。
解决办法是把上拉电阻换成了 2.2kΩ,上升沿从 8us 降到了 1us 以内,问题消失。I2C 上拉电阻的选择不是固定的“4.7k 通用”,需要根据线长、设备数量、通信速率来算。总线上挂的设备多、线长,就用更小的上拉电阻;正常短距离、低速场景,4.7k 到 10k 都没问题。关键是看示波器波形里的上升沿斜率。
5.3 从机初始化慢导致的“首包 NACK”
另一个常见情况是主控比从机先完成上电,代码一跑起来立刻去读传感器寄存器,结果第一个事务 NACK,后面再重试就正常了。用示波器抓启动瞬间的波形,能看到第一个地址字节的 ACK 位置是 NACK,而从第二个事务开始就变成 ACK 了。
这说明从机刚上电还在跑内部自检,没准备好应答。处理方式有两种:一是主控在访问前加延时,等从机初始化完成;二是从机端确保上电完成后再对外通信。调试时看到这种“只有首个事务失败”的波形,基本不用怀疑硬件,加等待时间就好。
5.4 总线卡死:SDA 被钉死在地平线
最让人头大的问题是 SDA 一直为低。示波器上看,SCL 还在正常打脉冲,SDA 却纹丝不动地贴着 0V。这种情况下主控发什么都没反应,万用表量 SDA 对地也是 0Ω 级别的导通。
这类锁死的常见原因是设备闩锁(latch-up)或者从机在总线异常状态下没释放 SDA。我遇到过一次是板子热插拔导致的,后来在 I2C 线上加了浪涌保护才根治。调试时临时解决的土办法是:给 SCL 连发 9 个时钟脉冲(主机模式下的“解锁”操作),让卡在总线上的从机完成一个接收窗口并释放 SDA。如果不行,只能断电重启。
5.5 速率拔高后一串 NACK
还有种场景是代码在标准模式 100kHz 下一切正常,把主控 I2C 外设的速率调到快速模式 400kHz,立刻全乱。示波器解码结果全是乱码,ACk 也几乎消失。
问题根源基本是物理层跟不上:总线电容大、上拉电阻偏大,导致边沿变缓,在高频率下信号还没翻转到有效逻辑电平,下一个时钟就来了。示波器测上升沿时间就能验证。方案就是把上拉改小,或缩短总线长度,或者保持 100kHz 通信。有一点值得强调:400kHz 的理论速率并不等于所有接线条件下都能跑,必须配套检查波形边沿时间。
以下整理一份速查表格,方便对照:
| 故障现象 | 可疑方向 | 用哪个工具确认 | 解决方向 |
|---|---|---|---|
| 地址 NACK,无应答 | 地址格式、从机供电 | 示波器看第 9 拍 SDA | 核对 7 位/8 位地址,查供电复位 |
| 时好时坏,手碰就挂 | 上拉电阻/接触不良 | 示波器看上升沿斜率 | 换更小上拉,补焊 |
| 首事务 NACK,重试即好 | 从机初始化慢 | 示波器抓启动序列 | 主控加等待延时 |
| SDA 一直低,总线锁死 | 从机闩锁/卡死 | 万用表量电平、示波器看 SDA | 发 9 个 SCL 脉冲解锁,断电重启 |
| 高速率下乱码 | 边沿过缓 | 示波器测上升沿时间 | 减小上拉,降速,缩短线长 |
6. 进阶工具:逻辑分析仪让 I2C 调试进入“上帝视角”
6.1 为什么排障到最后还是得靠逻辑分析仪
示波器虽然能看到精确波形,但存在一个天然短板:存储深度有限。I2C 通信有时候是一场“长跑”在几百毫秒甚至几秒里持续进行的对话,尤其涉及传感器连续采样、EEPROM 反复读写时,示波器一屏只能看一小段,想要找“哪一帧开始出错”,就得手动翻很多次,效率很低。
逻辑分析仪的出现,就是为了解决这个长时调试问题。它不需要判断波形电压值,只需要把高低电平随时间变化记录成逻辑 0/1 的序列。接入电脑后,软件能把这串序列按 I2C 协议解码成起始、地址、ACK、数据、停止,整个通信过程全景以时间轴形式呈现。我一般把逻辑分析仪接到开发板的 SDA、SCL 和 GND 三根线上,配合调试串口打印,一次抓满整个开机流程,然后慢慢找哪一帧是“压死骆驼的稻草”。
6.2 逻辑分析仪解 I2C 的操作流程
以常见的逻辑分析仪(如 Saleae 类、各类 8 通道逻辑分析仪)为例,操作步骤很固定:
接线:逻辑分析仪的通道 0 接 SCL,通道 1 接 SDA,GND 接地。接好之后开启采集。
采样率设置:逻辑分析仪采样率要高于 I2C 实际速率至少 5 到 10 倍。100kHz 的 I2C,采样率至少 2MS/s;400kHz 的至少要 5MS/s。采样率太低,解码出来的 bit 会缺。
采集长度:先预估通信时长,采集长度设到能包含完整事务。软件采集完了之后,可以按缩放看到每一个 bit,也可以直接看解码结果。I2C 解码器会显示“S:0x3C W,A,D1:0x01,D2:0x02,P”这样的格式,A 就是 ACK,N 是 NACK。哪个事务出了 NACK,一目了然。
逻辑分析仪还有个特点:很多型号自带协议分析插件,比如 I2C 解码器里可以直接列出“主设备地址”、“读/写方向”、“数据长度”、“ACK 状态”,有些还支持 I2C 超时分析。用上之后,排查 ACK 问题基本不需要再盯着原始波形数时钟了。
6.3 示波器和逻辑分析仪的搭配打法
示波器和逻辑分析仪并不是二选一的替代关系。我现在的常用组合是:先用逻辑分析仪做全局扫描,找到出错的那一帧;然后把示波器触发设到对应的地址或数据条件上,精确抓取那一段的模拟波形,看信号完整性。两个工具配合,既能看大局,也能看细节。
举个场景:逻辑分析仪显示第 37 帧读操作开始后第 3 个数据字节没有 ACK。然后我把示波器调整到 I2C 总线触发,或手动抓取该时段波形,放大看那一位 SDA 的电平变化速度,确认是边沿缓还是别的干扰。如果是边沿缓,根源大概率在上拉电阻和总线电容设计;如果是突发干扰,考虑电源噪声和 PCB 走线。
这套打法,就是“定位问题用逻辑分析仪,确认根因用示波器”。调试效率比单靠任何一个工具都高。
7. 根据个人经验,再补几句实在话
做 I2C 调试这些年,最深的体会就是:这个协议之所以难调,不是因为协议本身复杂,而是因为它“看起来简单”。两根线、几个时序、一个 ACK,感觉看一眼就会,但实际排障的时候,如果有一步工具用错了、一处波形看漏了,就能把人绕进去好久。
我踩坑最多的一次,就是因为不信波形、只信代码逻辑,把一段正确的驱动反复改了十几遍,最后示波器一测才发现是传感器模块的焊盘氧化,导致 SDA 虚接。自那以后,我把“先测信号,再改代码”当成铁律。遇到 I2C 问题,先拿出万用表量物理层,再上示波器抓波形,确认 ACK 状态,最后才动代码和元器件——这个顺序帮我节省了大量时间。
还想提醒一点:示波器探头的地线夹子不要夹在离 SDA/SCL 太远的地方,探头地线过长会产生振铃,影响对波形的判断。尽量夹在芯片附近 GND 测试点上,用短的接地弹簧更好。这些小细节,很多时候就是“波形怪”和“波形干净”的区别。调试 I2C,最忌讳的就是拿着工具乱怼、恨不得所有信号一次看完,慢下来、分步骤、按逻辑推进,才是真正的快。