1. I2C协议基础:从物理层到时序解读

各位同学,咱们今天正式开讲I2C。说实话,做了这么多年嵌入式,I2C是我用得最多的总线之一。它简单、灵活,两根线就能搞定一堆外设。但越是简单的东西,出起问题来反而越让人头疼。我记得刚入行那会儿,一个温度传感器死活读不到数据,折腾了两天,最后发现是上拉电阻焊错了——嗯,这种坑咱们后面会细聊。

先搭个框架,让大家心里有数。这一章我们主要聊三块:

  • 物理层——总线长什么样,电气特性如何
  • 协议层——起始、停止、数据、应答,这些基本动作怎么玩
  • 时序图解读——拿到一张时序图,怎么快速抓住关键信息

下面这张图,是我自己画的知识结构,建议你先扫一眼,有个整体印象。

I2C协议知识体系 I2C协议 物理层 协议层 时序解读 SCL / SDA 上拉电阻 开漏输出 7位/10位地址 起始条件 停止条件 数据有效性 应答机制 SCL高电平采样 数据建立/保持 时序参数表 波形解读 💡 核心要点 I2C的精髓:两根线 + 开漏 + 上拉 + 应答 = 多设备通信

1.1 物理层:两根线怎么撑起一片天?

I2C只有两根线:SCL(时钟线)和SDA(数据线)。所有设备都挂在这两根线上,主设备负责产生时钟,从设备听令行事。

这里有个关键点——开漏输出。说白了,设备只能把线拉低,不能主动拉高。那高电平谁来给?上拉电阻。我见过不少新手在这上面栽跟头,电阻选大了信号上升沿太慢,选小了功耗又高。标准模式下一般用4.7kΩ,快速模式用2.2kΩ左右,具体还得看总线电容。

💡 我的习惯:调试阶段先用4.7kΩ,如果波形上升沿太缓再换小。别一上来就上1kΩ,那电流能让你怀疑人生。

地址方面,I2C支持7位和10位两种地址格式。7位地址最多挂127个设备,实际中够用了。每个设备有个唯一地址,主设备通过地址来选择跟谁说话。

1.2 协议层:四个基本动作,搞定一切通信

I2C的协议层其实不复杂,核心就四个动作。你把这四个搞明白了,剩下的都是组合拳。

起始条件(Start Condition)

SCL为高电平时,SDA从高切换到低。这个下降沿告诉所有从设备:注意,要开始通信了!

停止条件(Stop Condition)

SCL为高电平时,SDA从低切换到高。这个上升沿表示:本次传输结束,总线释放。

数据有效性

数据在SCL高电平时被采样,所以SDA必须在SCL高电平期间保持稳定。数据变化只能在SCL低电平时进行。这个规则很关键——你想想看,如果数据在SCL高电平时变了,那接收方就不知道你传的是啥了。

应答机制(ACK/NACK)

每传输完一个字节(8位),接收方需要在第9个时钟周期拉低SDA表示应答(ACK)。如果接收方不拉低(SDA保持高),那就是非应答(NACK),表示出问题了。

我曾经遇到一个坑:有个传感器偶尔不响应,查了半天发现是电源纹波太大,导致从设备内部复位,应答信号丢了。从那以后,我每次画板子都会在I2C设备旁边加个100nF去耦电容。

下面这个表格,把四个动作的关键点总结了一下,建议你收藏。

动作 SCL状态 SDA变化 说明
起始条件 高电平 高 → 低 下降沿,启动通信
停止条件 高电平 低 → 高 上升沿,结束通信
数据有效性 高电平 保持稳定 SCL高时采样数据
应答(ACK) 第9个时钟 被拉低 接收方确认收到
非应答(NACK) 第9个时钟 保持高 接收方未确认

1.3 时序图解读:别怕,其实有套路

很多同学看到时序图就头大。其实没那么可怕,我教你一个方法:先找起始和停止,再看数据变化,最后盯应答位。

举个例子,主设备向从设备写一个字节的数据,流程是这样的:

  1. 主设备发出起始条件
  2. 主设备发送7位从设备地址 + 1位读写位(0表示写)
  3. 从设备在第9个时钟回复ACK
  4. 主设备发送8位数据
  5. 从设备回复ACK
  6. 主设备发出停止条件

读操作稍微复杂一点,需要先发地址再切换方向,但核心逻辑是一样的。

⚠️ 特别注意:时序图里的建立时间(tSU)和保持时间(tHD)是硬指标。我见过有人用GPIO模拟I2C,延时没算好,数据建立时间不够,从设备就是不认。标准模式下,数据建立时间至少需要250ns,保持时间至少0ns(但建议留点余量)。

我个人习惯,拿到一张时序图后,先用笔把起始条件和停止条件圈出来,然后数时钟个数,最后看数据位和应答位。多练几次,你就能一眼看出问题所在。

好了,这一章的基础知识就到这里。记住,I2C的精髓就是两根线加一个应答机制。后面我们会用这些知识去排查各种通信故障,到时候你就知道今天打的基础有多重要了。