3、I2C时序实战:用逻辑分析仪抓波形,解析地址帧与数据帧

说实话,做飞控这些年,我见过太多人栽在I2C通信上。代码写得飞起,一上逻辑分析仪就傻眼——波形不对,地址不对,应答位丢了。嗯,今天咱们就来把这层窗户纸捅破。

我个人习惯,调试I2C设备时第一件事就是抓波形。为什么?因为代码里写的“0x68”和总线上实际跑的地址,有时候根本不是一回事。你想想看,I2C地址有7位和10位之分,还有读写位要拼接,稍不留神就翻车。

3.1 先搭好测试环境

别急着上逻辑分析仪,先把硬件接对。我一般这样连:

  • SCL → 逻辑分析仪通道0
  • SDA → 逻辑分析仪通道1
  • GND → 逻辑分析仪GND(这个最容易忘,忘了波形全是毛刺)
注意: 逻辑分析仪的采样率至少设到4MHz以上。I2C标准模式100kHz,快速模式400kHz,采样率不够你根本看不清时序细节。我曾经用1MHz采样率抓400kHz的I2C,结果波形像鬼画符,折腾了两小时才发现是采样率的问题。

3.2 I2C时序基础:起始条件与停止条件

先看最基础的两个信号。逻辑分析仪抓到的波形里,你要能一眼认出它们:

  • 起始条件(S):SCL高电平时,SDA从高变低
  • 停止条件(P):SCL高电平时,SDA从低变高

说白了,这就是I2C通信的“开始”和“结束”信号。我刚开始学的时候总记反,后来想了个笨办法:“开始是下降,结束是上升”,念三遍就记住了。

实战技巧: 在逻辑分析仪上设置触发条件为“SDA下降沿”,这样每次I2C通信开始,波形自动停在你面前,不用手动翻找。

3.3 地址帧解析:7位地址到底怎么算?

好,现在来看地址帧。这是I2C通信最容易出错的地方。我直接拿MPU6050举例,它的7位地址是0x68(二进制:1101000)。

但注意!总线上实际发送的是8位,前7位是地址,最后1位是读写位(0表示写,1表示读)。所以:

  • 写操作地址字节:0x68 << 1 | 0 = 0xD0(二进制:1101 0000)
  • 读操作地址字节:0x68 << 1 | 1 = 0xD1(二进制:1101 0001)

你看,代码里写的是0x68,但逻辑分析仪上抓到的地址字节是0xD0或0xD1。很多新手在这里卡住,对着数据手册看半天,以为芯片坏了。其实没坏,是你忘了左移一位。

我的习惯: 在代码注释里直接写明“发送地址0xD0(0x68写)”,这样回头查波形时一目了然。

3.4 数据帧解析:一个字节一个字节地看

地址发完之后,紧接着就是数据帧。每个数据帧也是8位,MSB先发。逻辑分析仪上你会看到这样的序列:

  1. 起始条件(SDA下降沿)
  2. 地址字节(8位,含读写位)
  3. 从机应答位(ACK:SDA被从机拉低)
  4. 数据字节1(8位)
  5. 从机应答位
  6. 数据字节2(8位)
  7. ... 以此类推
  8. 停止条件(SDA上升沿)

这里有个坑:应答位是低电平有效。也就是说,如果从机正常响应,SDA会被拉低一个时钟周期。如果SDA一直保持高电平,那就是NACK,说明从机没收到或者不想理你。

我曾经调试一个气压传感器,死活读不到数据。抓波形一看,地址发出去之后应答位是高的——NACK。查了半天,原来是I2C总线上拉电阻焊错了,4.7kΩ焊成了47kΩ,信号根本拉不下去。嗯,这种硬件问题,光看代码永远找不到。

3.5 用逻辑分析仪软件解析波形

现在主流逻辑分析仪软件(比如Saleae Logic、PulseView)都支持I2C协议解析。你只需要:

  1. 抓取波形后,添加I2C协议分析器
  2. 指定SCL和SDA对应的通道
  3. 软件自动标出起始条件、地址、数据、应答位、停止条件

我个人强烈建议:不要完全依赖自动解析。自动解析有时候会出错,尤其是信号质量不好的时候。你得学会手动数时钟周期,确认每个bit对不对。

手动解析步骤:

  • 找到起始条件(SDA下降沿,SCL高)
  • 从下一个SCL上升沿开始,数8个时钟周期,读取SDA电平
  • 第9个时钟周期看SDA是否被拉低(ACK)
  • 重复以上步骤直到停止条件

3.6 实战案例:读取MPU6050的WHO_AM_I寄存器

咱们来个完整的例子。读取MPU6050的WHO_AM_I寄存器(地址0x75),预期返回值应该是0x68。

完整的I2C通信序列:

  1. 起始条件
  2. 发送地址0xD0(0x68写操作)
  3. 等待ACK
  4. 发送寄存器地址0x75
  5. 等待ACK
  6. 重复起始条件(注意!这里不是停止条件)
  7. 发送地址0xD1(0x68读操作)
  8. 等待ACK
  9. 读取1个字节数据(从机发送,主机接收)
  10. 主机发送NACK(表示不再读取)
  11. 停止条件

在逻辑分析仪上,你会看到两个地址字节:第一个是0xD0,第二个是0xD1。中间没有停止条件,而是重复起始条件。这是I2C复合通信的典型用法。

常见错误: 有些人在读操作之前先发了停止条件,然后再发起始条件。这样虽然也能工作,但效率低,而且某些从机可能会复位状态机,导致读到的数据不对。正确的做法是用重复起始条件。

3.7 波形异常排查清单

最后,我整理了一份排查清单,都是我在项目中踩过的坑:

现象 可能原因 解决方法
没有起始条件 SCL或SDA被拉死 检查上拉电阻,测量引脚电平
地址发出去后NACK 地址错误或从机未上电 确认7位地址是否正确,检查从机电源
数据全是0xFF 从机未响应或总线浮空 检查上拉电阻,确认从机工作模式
波形有毛刺 信号线过长或地线未接 缩短线缆,确保共地
时钟频率不对 I2C时钟配置错误 检查主控的I2C时钟分频寄存器

嗯,今天就先聊到这儿。逻辑分析仪这东西,用多了就有感觉了。刚开始可能觉得波形密密麻麻看不懂,别急,一个一个时钟周期去数,数上十次你就熟练了。记住:I2C通信没有秘密,全在波形里


专注资料整理