3. I2C时序实战:用逻辑分析仪抓取AT24C02读写时序
说实话,很多工程师学I2C协议,看了几百遍时序图,真到调板子的时候还是抓瞎。为啥?因为书本上的波形是理想的,示波器里看到的才是真实的。我个人习惯是:先拿逻辑分析仪抓一把真实波形,再对着数据手册一行一行解析。今天我们就拿AT24C02这个经典EEPROM开刀,手把手带你读懂SCL/SDA上的每一比特。
3.1 准备工作:硬件连接与工具配置
先说说我手头的装备。一块STM32F103开发板,一个AT24C02模块,一个廉价的24MHz逻辑分析仪(几十块钱那种就够用)。连接方式很简单:
- SCL → 逻辑分析仪通道0
- SDA → 逻辑分析仪通道1
- GND → 共地
采样率我设成4MHz,够用。触发条件选SDA下降沿——这样能抓到起始条件。嗯,这里要注意:AT24C02的I2C地址是0xA0(写)和0xA1(读),器件地址引脚A0/A1/A2我全接地了,所以地址是固定的。
3.2 起始条件与停止条件:波形的"书签"
先看起始条件。I2C协议规定:SCL高电平时,SDA从高变低,这就是START。停止条件相反:SCL高电平时,SDA从低变高。
我抓到的波形长这样(简化描述):
SCL: ▔▔▁▁▔▔▁▁▔▔▁▁▔▔▁▁...
SDA: ▔▔▁▁▁▁▔▔▔▔▁▁▁▁▔▔...
↑START ↑STOP
你仔细看:在START之后,SCL开始产生规律的时钟脉冲。每个脉冲对应一个数据位。AT24C02的时序要求SCL最高频率400kHz(快速模式),我实际测到的是100kHz左右——标准模式,稳妥。
3.3 字节传输与ACK/NACK:逐位拆解
好,现在我们来拆一个完整的字节传输。以写一个字节0x55(二进制01010101)到AT24C02为例。抓到的波形放大后:
| 时钟周期 | SCL状态 | SDA状态 | 含义 |
|---|---|---|---|
| 1 | 上升沿 | 低 | 数据位7(MSB)= 0 |
| 2 | 上升沿 | 高 | 数据位6 = 1 |
| 3 | 上升沿 | 低 | 数据位5 = 0 |
| 4 | 上升沿 | 高 | 数据位4 = 1 |
| 5 | 上升沿 | 低 | 数据位3 = 0 |
| 6 | 上升沿 | 高 | 数据位2 = 1 |
| 7 | 上升沿 | 低 | 数据位1 = 0 |
| 8 | 上升沿 | 高 | 数据位0(LSB)= 1 |
| 9 | 上升沿 | 低(从机拉低) | ACK |
看到第9个时钟周期了吗?SDA被从机拉低了。这就是ACK。如果从机没拉低,那就是NACK——通常意味着地址错误、器件忙或者写入失败。
3.4 完整写操作时序:从START到STOP
现在我们把整个写操作串起来。AT24C02的页写(Page Write)可以一次写最多8个字节,但为了清晰,我们先看单字节写。完整的波形序列:
- START条件:SCL高,SDA下降沿
- 发送器件地址:0xA0(7位地址1010000 + 写位0),共8位 + ACK
- 发送字地址:要写入的EEPROM内部地址,比如0x00,共8位 + ACK
- 发送数据:要写入的字节,比如0x55,共8位 + ACK
- STOP条件:SCL高,SDA上升沿
我抓到的实际波形总长度大约是:5个字节 × 9个时钟周期 = 45个时钟周期,加上START和STOP的建立/保持时间,总共约500μs(100kHz下)。
你想想看,如果一次写8个字节(页写),只需要在字地址之后连续发8个数据字节,每个字节后跟一个ACK。这样效率高很多。但要注意:字地址会自动递增,如果超过页边界(AT24C02每页8字节),地址会回卷到页首——这是个常见的坑。
3.5 完整读操作时序:随机读与连续读
读操作比写操作稍微复杂一点。以随机读为例,需要先"假装写"来设置地址,再重新START来读。波形序列:
- START条件
- 发送器件地址(写):0xA0 + ACK
- 发送字地址:要读取的地址,比如0x00 + ACK
- 重复START条件:SCL高,SDA下降沿(注意:没有STOP!)
- 发送器件地址(读):0xA1 + ACK
- 读取数据:主机释放SDA,从机驱动SDA,主机在第9个时钟发NACK表示读完
- STOP条件
这里有个细节:重复START(Sr)和普通START波形一模一样,区别在于它前面没有STOP。逻辑分析仪上看起来就是两个START挨得很近。我刚开始学的时候,老是把重复START误判成普通START,后来养成了习惯:看波形上下文,如果前一个操作是地址写,紧接着又来一个START,那基本就是重复START。
3.6 手动解析波形:实战演练
好,现在我们来手动解析一段真实的波形数据。假设逻辑分析仪抓到了以下SCL/SDA电平序列(只列出SCL上升沿时刻的SDA值):
START
1: SDA=1 (器件地址位6)
2: SDA=0 (器件地址位5)
3: SDA=1 (器件地址位4)
4: SDA=0 (器件地址位3)
5: SDA=0 (器件地址位2)
6: SDA=0 (器件地址位1)
7: SDA=0 (器件地址位0)
8: SDA=0 (写位)
9: SDA=0 (ACK)
10: SDA=0 (字地址位7)
11: SDA=0 (字地址位6)
...
我们来解析前9位:10100000。二进制1010000 = 0x50,左移1位加写位0 = 0xA0。没错,就是AT24C02的写地址。第9位SDA=0,说明从机应答了。
继续解析字地址:假设后面8位是00000000,那就是地址0x00。再后面8位是数据。如果数据是01010101,那就是0x55。
你看,只要按部就班,手动解析并不难。我建议你拿自己抓的波形练练手,先解析地址,再解析数据,最后验证对不对。
3.7 常见时序问题与排查方法
在实际项目中,我遇到过不少时序问题。这里列几个典型的:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 从机一直NACK | 地址错误、器件未上电、总线冲突 | 检查地址位、测量VCC、看SDA是否被拉死 |
| 数据写进去读出来不对 | 字地址错误、页边界回卷、tWR未等待 | 检查地址递增逻辑、加轮询等待 |
| 波形上有毛刺 | 信号反射、地线过长、上拉电阻太小 | 加33Ω串联电阻、缩短地线、换4.7kΩ上拉 |
| SCL/SDA电平不对 | 电平不匹配、开漏输出配置错误 | 检查GPIO模式(开漏)、确认电压域 |
3.8 本章小结:时序分析的核心思路
说白了,I2C时序分析就三步:
- 找边界:先找到START和STOP,确定一帧数据的起止
- 数时钟:每9个时钟一组,前8位是数据,第9位是ACK/NACK
- 对地址:第一组数据是器件地址+读写位,后面跟着字地址和数据
掌握了这个思路,任何I2C器件的时序你都能读得懂。AT24C02只是个开始,后面我们会用同样的方法分析传感器、RTC、ADC等常见I2C外设。
嗯,最后说一句:别怕波形乱。逻辑分析仪是你的眼睛,数据手册是你的地图。两者结合,没有调不通的I2C。