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.3V系统设1.65V,5V系统设2.5V。我曾经因为阈值设错了,抓了一下午全是毛刺,后来才发现是电平判断出了问题。

3.2 起始条件与停止条件:波形的"书签"

先看起始条件。I2C协议规定:SCL高电平时,SDA从高变低,这就是START。停止条件相反:SCL高电平时,SDA从低变高。

我抓到的波形长这样(简化描述):

SCL: ▔▔▁▁▔▔▁▁▔▔▁▁▔▔▁▁...
SDA: ▔▔▁▁▁▁▔▔▔▔▁▁▁▁▔▔...
      ↑START          ↑STOP

你仔细看:在START之后,SCL开始产生规律的时钟脉冲。每个脉冲对应一个数据位。AT24C02的时序要求SCL最高频率400kHz(快速模式),我实际测到的是100kHz左右——标准模式,稳妥。

关键点: 起始条件之后,总线就被主机占用了。从机(AT24C02)会一直监听,直到收到停止条件。如果中途总线空闲时间超过一定阈值,从机可能复位。我遇到过因为停止条件没发完整,导致下一次通信失败的坑。

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——通常意味着地址错误、器件忙或者写入失败。

避坑指南: 我曾经在调试时发现,AT24C02在写操作之后需要5ms左右的内部写入时间(tWR)。如果在这段时间内发新的START,从机会回复NACK。解决办法是:每次写操作后,发一个START并检查ACK,直到收到ACK为止。这叫"轮询等待"。

3.4 完整写操作时序:从START到STOP

现在我们把整个写操作串起来。AT24C02的页写(Page Write)可以一次写最多8个字节,但为了清晰,我们先看单字节写。完整的波形序列:

  1. START条件:SCL高,SDA下降沿
  2. 发送器件地址:0xA0(7位地址1010000 + 写位0),共8位 + ACK
  3. 发送字地址:要写入的EEPROM内部地址,比如0x00,共8位 + ACK
  4. 发送数据:要写入的字节,比如0x55,共8位 + ACK
  5. STOP条件:SCL高,SDA上升沿

我抓到的实际波形总长度大约是:5个字节 × 9个时钟周期 = 45个时钟周期,加上START和STOP的建立/保持时间,总共约500μs(100kHz下)。

你想想看,如果一次写8个字节(页写),只需要在字地址之后连续发8个数据字节,每个字节后跟一个ACK。这样效率高很多。但要注意:字地址会自动递增,如果超过页边界(AT24C02每页8字节),地址会回卷到页首——这是个常见的坑。

3.5 完整读操作时序:随机读与连续读

读操作比写操作稍微复杂一点。以随机读为例,需要先"假装写"来设置地址,再重新START来读。波形序列:

  1. START条件
  2. 发送器件地址(写):0xA0 + ACK
  3. 发送字地址:要读取的地址,比如0x00 + ACK
  4. 重复START条件:SCL高,SDA下降沿(注意:没有STOP!)
  5. 发送器件地址(读):0xA1 + ACK
  6. 读取数据:主机释放SDA,从机驱动SDA,主机在第9个时钟发NACK表示读完
  7. STOP条件

这里有个细节:重复START(Sr)和普通START波形一模一样,区别在于它前面没有STOP。逻辑分析仪上看起来就是两个START挨得很近。我刚开始学的时候,老是把重复START误判成普通START,后来养成了习惯:看波形上下文,如果前一个操作是地址写,紧接着又来一个START,那基本就是重复START。

连续读(Sequential Read): 如果你在读完一个字节后不发NACK,而是发ACK,AT24C02会继续输出下一个地址的数据。地址自动递增。直到你发NACK + STOP为止。这个特性在读取大块数据时非常有用。

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模式(开漏)、确认电压域
我的调试习惯: 先用逻辑分析仪抓一把完整的读写波形,然后对照数据手册的时序参数表,逐项检查建立时间(tSU)、保持时间(tHD)、时钟低电平时间(tLOW)、时钟高电平时间(tHIGH)。AT24C02的tLOW最小值是1.3μs(100kHz)或0.6μs(400kHz),如果SCL低电平时间太短,从机可能采样不到数据。

3.8 本章小结:时序分析的核心思路

说白了,I2C时序分析就三步:

  1. 找边界:先找到START和STOP,确定一帧数据的起止
  2. 数时钟:每9个时钟一组,前8位是数据,第9位是ACK/NACK
  3. 对地址:第一组数据是器件地址+读写位,后面跟着字地址和数据

掌握了这个思路,任何I2C器件的时序你都能读得懂。AT24C02只是个开始,后面我们会用同样的方法分析传感器、RTC、ADC等常见I2C外设。

嗯,最后说一句:别怕波形乱。逻辑分析仪是你的眼睛,数据手册是你的地图。两者结合,没有调不通的I2C。

I2C读写时序流程图(以AT24C02为例) 写操作流程 START 发送器件地址(写) ACK 发送字地址 ACK 发送数据 ACK STOP 读操作流程 START 发送器件地址(写) ACK 发送字地址 ACK 重复START 发送器件地址(读) ACK 读取数据 NACK+STOP 注意:读操作使用重复START(Sr)而不是STOP+START,以保证总线不被释放