第二讲:SCL和SDA信号时序分析——把心跳和呼吸看清楚
做I2C调试,说白了就是看两根线的时序对不对。SCL是时钟,SDA是数据,它们配合不好,设备就不说话。我刚开始修I2C总线时,总觉得时序就是几个时间参数,查手册照填就行——直到有一次,从设备死拽着SCL不放,我的逻辑分析仪愣是没看出来。
时钟拉伸,是I2C里最隐蔽的坑之一。想学会怎么揪出它,你得先把正常的SCL/SDA波形刻在脑子里。这一节,我带你从骨子里搞懂它们。
2.1 标准时序参数——I2C的“心电”指标
I2C协议定义了一组时间参数,决定了总线能跑多快、数据稳不稳。你想想看,如果SCL高电平时间太短,从设备可能来不及采样SDA;如果保持时间不够,起始条件可能被误解。下表是标准模式(100kHz)下的关键参数,我建议你记在本子上,调总线时随时回来对照。
| 参数 | 符号 | 标准模式最小值 | 标准模式最大值 | 说明 |
|---|---|---|---|---|
| SCL时钟频率 | fSCL | — | 100 kHz | 基本节奏 |
| SCL高电平时间 | tHIGH | 4.0 μs | — | 从设备干活时间 |
| SCL低电平时间 | tLOW | 4.7 μs | — | 主机等待时间 |
| SCL上升时间 | tr | — | 1000 ns | 受总线电容影响 |
| SCL下降时间 | tf | — | 300 ns | 主设备驱动能力 |
| 起始条件保持时间 | tHD:STA | 4.0 μs | — | SDA下降沿后SCL必须保持低 |
| 起始条件建立时间 | tSU:STA | 4.7 μs | — | 重复起始前SCL高+1 SDA下降 |
| 数据保持时间 | tHD:DAT | 0 | 3.45 μs | SCL下降后SDA保持 |
| 数据建立时间 | tSU:DAT | 250 ns | — | SDA先稳定,SCL再上升 |
| 停止条件建立时间 | tSU:STO | 4.0 μs | — | SDA上升前SCL先高 |
| 总线空闲时间 | tBUF | 4.7 μs | — | 停止到下一次起始 |
我的习惯:拿到一个新I2C器件,第一件事就是把它的最小tHIGH和tLOW抄到调试笔记里。很多时钟拉伸问题,就是从设备内部处理慢了,需要主机把低电平时间拉长。你如果不知道器件要求的最低tLOW,就看不出来拉伸。
2.2 正常传输波形——SCL和SDA怎么“对话”
SCL和SDA的配合,有点像跳舞。我把一次完整的数据传输拆成几个动作:
- 空闲态:SCL和SDA都是高电平(上拉电阻拉高)。总线没人在占用。
- 起始条件:SCL为高时,SDA从高到低跳变。这个下降沿告诉所有从设备:“注意,要开始发地址了”。
- 数据采样:SCL低电平时,主机改变SDA;SCL高电平时,从设备读取SDA。所以SCL的上升沿才是真正的采样点。
- 停止条件:SCL为高时,SDA从低到高跳变。总线释放。
这里有个关键点:数据在SCL高电平时必须稳定。如果SDA在SCL高时跳变,会被当成起始或停止条件。我在项目中遇到过一个人为失误:CPU的I2C中断响应太慢,导致SDA在SCL高时被软件改写了,结果总线疯狂产生虚假起始条件。
一句话总结正常时序:SCL低时数据变,SCL高时数据读。两根线各司其职,谁也不抢谁的活儿。
2.3 时钟拉伸的本质——从设备“拽住”SCL不放
时钟拉伸只发生在SCL低电平阶段。从设备觉得自己还没准备好,就把SCL继续拉低,不让主机上升。主机发现SCL一直低,就会一直等——直到从设备松手。
为什么从设备要这么做?说实话,最常见的原因是它内部的数据处理没结束,比如:
- 从设备正在写EEPROM,不能接收新数据;
- 从设备ADC转换中,数据还没稳定;
- 从设备缓冲区满了,正在倒腾数据。
从设备不是故意捣乱,它只是为了不接收它处理不了的命令。你想想看,如果它不拉低SCL,主机就会继续发数据,那数据必然丢失。
2.4 正常时序 vs 拉伸时序——波形对比
下面这张表把两种情况的SCL/SDA行为列在一起,你看完就能一眼认出拉伸。
| 特征 | 正常传输 | 时钟拉伸发生 |
|---|---|---|
| SCL低电平时间 | 固定,小于4.7 μs(标准模式) | 被延长,可能达到几十甚至几百微秒 |
| SCL高电平时间 | 由主机控制,等于tHIGH | 不变,仍由主机控制 |
| SCL波形形状 | 对称方波 | 低电平期明显变宽,高电平期不变 |
| SDA变化点 | 仅在SCL低电平时变化 | 在拉伸期间SDA可能不变(从设备未输出新数据) |
| 主机行为 | 主动产生下一个时钟 | 等待SCL释放,一直检查SCL是否为高 |
避坑指南:我曾经用一台100MHz采样率的逻辑分析仪去抓一个快模式(400kHz)的时钟拉伸,结果发现低电平“略微”变宽了0.5μs,差点忽略掉。后来才意识到,拉伸可能非常短,只有几十纳秒。所以建议用至少200MHz采样率去抓,时间分辨率要小于1个SCL周期的一半。
2.5 时序关系一图看——SCL/SDA的上升沿、下降沿与拉伸区域
我把正常传输和时钟拉伸的波形画在一起,标出关键时间点和区域。你会看到拉伸就是SCL低电平被“撑开”的那一块。
2.6 实战判断技巧——你该关注哪些点
抓到了波形,怎么确认是时钟拉伸,而不是其他问题?我给自己总结了一个检查清单,每次调I2C都会过一遍:
- 检查SCL低电平的一致性:正常传输中,所有SCL低电平时间应该差不多。如果有一个或几个明显偏长,那就是拉伸。
- 看拉伸时SDA是否稳定:拉伸期间SDA要么保持上一个值不变(从设备还没准备好),要么变成从设备想发送的数据(从设备用拉伸争取时间来输出字节)。如果是后一种,SDA会在拉伸期间变化一次然后保持。
- 识别拉伸发生在哪个时钟周期:常见的是在第9个SCL脉冲(应答位)或下一个字节的第一个时钟。如果拉伸发生在应答位之后,说明从设备还在处理上一个字节。
- 用统计工具分析:现在的逻辑分析仪软件一般都有“SCL低电平统计”功能。我看过不少拉伸问题,实际SCL低电平有时只是比正常值宽了几百纳秒,人眼很难发现,但统计图上一目了然。
我的经验:当年调试一个温度传感器,它只在温度转换完成后才释放SCL。我在-40℃环境下测试,转换时间变慢了,导致时钟拉伸时间从正常的1ms飙到3ms。主机AC定时器超时直接把总线复位了。后来我把主机的SCL超时时间改成了5ms,问题解决。记住:从设备手册里的转换时间,往往是典型值,极端温度和电压下会变。