3、I2C时序实战:用逻辑分析仪抓波形,解析地址帧与数据帧
说实话,做飞控这些年,我见过太多人栽在I2C通信上。代码写得飞起,一上逻辑分析仪就傻眼——波形不对,地址不对,应答位丢了。嗯,今天咱们就来把这层窗户纸捅破。
我个人习惯,调试I2C设备时第一件事就是抓波形。为什么?因为代码里写的“0x68”和总线上实际跑的地址,有时候根本不是一回事。你想想看,I2C地址有7位和10位之分,还有读写位要拼接,稍不留神就翻车。
3.1 先搭好测试环境
别急着上逻辑分析仪,先把硬件接对。我一般这样连:
- SCL → 逻辑分析仪通道0
- SDA → 逻辑分析仪通道1
- GND → 逻辑分析仪GND(这个最容易忘,忘了波形全是毛刺)
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先发。逻辑分析仪上你会看到这样的序列:
- 起始条件(SDA下降沿)
- 地址字节(8位,含读写位)
- 从机应答位(ACK:SDA被从机拉低)
- 数据字节1(8位)
- 从机应答位
- 数据字节2(8位)
- ... 以此类推
- 停止条件(SDA上升沿)
这里有个坑:应答位是低电平有效。也就是说,如果从机正常响应,SDA会被拉低一个时钟周期。如果SDA一直保持高电平,那就是NACK,说明从机没收到或者不想理你。
我曾经调试一个气压传感器,死活读不到数据。抓波形一看,地址发出去之后应答位是高的——NACK。查了半天,原来是I2C总线上拉电阻焊错了,4.7kΩ焊成了47kΩ,信号根本拉不下去。嗯,这种硬件问题,光看代码永远找不到。
3.5 用逻辑分析仪软件解析波形
现在主流逻辑分析仪软件(比如Saleae Logic、PulseView)都支持I2C协议解析。你只需要:
- 抓取波形后,添加I2C协议分析器
- 指定SCL和SDA对应的通道
- 软件自动标出起始条件、地址、数据、应答位、停止条件
我个人强烈建议:不要完全依赖自动解析。自动解析有时候会出错,尤其是信号质量不好的时候。你得学会手动数时钟周期,确认每个bit对不对。
手动解析步骤:
- 找到起始条件(SDA下降沿,SCL高)
- 从下一个SCL上升沿开始,数8个时钟周期,读取SDA电平
- 第9个时钟周期看SDA是否被拉低(ACK)
- 重复以上步骤直到停止条件
3.6 实战案例:读取MPU6050的WHO_AM_I寄存器
咱们来个完整的例子。读取MPU6050的WHO_AM_I寄存器(地址0x75),预期返回值应该是0x68。
完整的I2C通信序列:
- 起始条件
- 发送地址0xD0(0x68写操作)
- 等待ACK
- 发送寄存器地址0x75
- 等待ACK
- 重复起始条件(注意!这里不是停止条件)
- 发送地址0xD1(0x68读操作)
- 等待ACK
- 读取1个字节数据(从机发送,主机接收)
- 主机发送NACK(表示不再读取)
- 停止条件
在逻辑分析仪上,你会看到两个地址字节:第一个是0xD0,第二个是0xD1。中间没有停止条件,而是重复起始条件。这是I2C复合通信的典型用法。
3.7 波形异常排查清单
最后,我整理了一份排查清单,都是我在项目中踩过的坑:
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 没有起始条件 | SCL或SDA被拉死 | 检查上拉电阻,测量引脚电平 |
| 地址发出去后NACK | 地址错误或从机未上电 | 确认7位地址是否正确,检查从机电源 |
| 数据全是0xFF | 从机未响应或总线浮空 | 检查上拉电阻,确认从机工作模式 |
| 波形有毛刺 | 信号线过长或地线未接 | 缩短线缆,确保共地 |
| 时钟频率不对 | I2C时钟配置错误 | 检查主控的I2C时钟分频寄存器 |
嗯,今天就先聊到这儿。逻辑分析仪这东西,用多了就有感觉了。刚开始可能觉得波形密密麻麻看不懂,别急,一个一个时钟周期去数,数上十次你就熟练了。记住:I2C通信没有秘密,全在波形里。