在上一篇文章中,我们探讨了I2C设备的硬件架构。本文将深入解析I2C通信中信号的物理特性与核心操作时序,帮助你更好地理解这一经典总线协议的工作原理。
一、 I2C设备输入缓冲器特点
1.1 用于双向通信的开漏电路
开漏是一种输出类型,它只能将总线拉低到特定电压(通常是地电平),或者“释放”总线,使其由上拉电阻拉至高电平。无论是主设备还是从设备释放总线,信号线(SDA/SCL)上的上拉电阻(RPU)都负责将总线电压拉高至电源轨。由于没有任何设备能主动将信号线驱动为高电平,这从根本上避免了总线冲突——即一个设备试图输出高电平而另一个设备输出低电平所造成的电源对地短路风险。
在多主设备环境中,I2C协议要求:若一个主设备试图输出高电平但检测到线路为低电平(表明另一设备正占用总线),则该主设备必须停止通信。这种优雅的冲突处理机制是推挽式接口所不具备的,也是I2C总线的一大优势。

图2. SDA/SCL线路的基本内部结构
图2展示了SDA或SCL线上主从设备内部结构的简化视图,包含一个用于读取数据的输入缓冲器和一个用于发送数据的下拉FET。设备只能执行两种操作:将总线拉低(对地形成通路)或释放总线(呈现高阻抗),从而允许上拉电阻将电平拉高。掌握这一概念至关重要,因为它决定了I2C双向通信的物理基础。
1.2 开漏拉低操作
如前所述,开漏输出只能拉低总线或释放总线。当NMOS管开启时,设备通过该管将电流泄放到地,导致开漏输出线被拉低。通常,I2C从高到低的电平转换速度较快,因为NMOS管会主动下拉线路。转换速度取决于NMOS管的驱动能力以及总线上的寄生电容。
图3展示了将总线拉低时的电流路径。需要发送低电平的逻辑会激活下拉FET,形成对地的低阻通路,从而强制拉低线路电平。

图3. 使用开漏接口将总线拉低
1.3 开漏释放总线操作
当从设备或主设备需要发送逻辑高电平时,其唯一能做的就是关闭下拉FET以释放总线。这使得总线进入高阻态,由上拉电阻将电压拉升至电源轨,该状态被接收方解释为高电平。当NMOS管关闭时,设备停止下拉电流,上拉电阻将SDA或SCL线拉向VDD。图4展示了NMOS关闭时的电流路径。由于高电平是靠电阻被动拉起的,需要对抗总线电容,因此从低到高的电平转换速度相对较慢。

图4. 使用开漏接口释放总线
二、 I2C通用操作
I2C总线是一种标准双向接口,采用控制器(主设备)与目标设备(从设备)进行通信。从设备只有在被主设备寻址后才能发起数据传输。总线上每个设备都有一个唯一的设备地址,用于区分其他设备。许多从设备在初始化时需要配置,以设定其工作模式,这通常通过主设备访问从设备内部的寄存器映射来完成,每个寄存器都有唯一的地址。
物理I2C接口由串行时钟线(SCL)和串行数据线(SDA)构成。两者都必须通过上拉电阻连接至电源VCC。电阻阻值需根据总线电容计算(后续章节详述)。数据传输只能在总线空闲时启动。当STOP条件之后,SDA和SCL线均保持高电平,即认为总线空闲。
主设备访问从设备的一般流程如下:
-
主设备向从设备发送数据:
- 主设备(发送器)产生START条件并寻址从设备(接收器)。
- 主设备向从设备发送数据字节。
- 主设备以STOP条件终止传输。
-
主设备从从设备接收数据:
- 主设备(接收器)产生START条件并寻址从设备(发送器)。
- 主设备发送它希望读取的寄存器地址。
- 主设备接收从设备发回的数据。
- 主设备以STOP条件终止传输。
2.1 START和STOP条件
I2C通信由主设备发送的START条件启动,并由STOP条件终止。
- START条件:在SCL为高电平期间,SDA线上发生从高到低的跳变。
- STOP条件:在SCL为高电平期间,SDA线上发生从低到高的跳变。

图5. START和STOP条件示例
2.2 重复START条件
重复START条件在功能上等同于一个STOP条件后紧跟一个START条件,但其波形与普通START条件相同。关键区别在于,它发生在一个STOP条件之前(即总线不空闲时)。这在主设备希望开始新的通信,但又不想通过释放总线(发送STOP条件)从而在多主系统中可能丧失总线控制权时非常有用。
2.3 数据有效性与字节格式
数据在SCL的每个时钟脉冲期间传输一位。一个字节由SDA线上的8位数据构成,可以是设备地址、寄存器地址或数据内容。数据传输遵循最高有效位(MSB)优先的原则。在START和STOP条件之间,主设备可以传输任意数量的数据字节。需要注意的是,当SCL为高电平时,SDA线上的数据必须保持稳定,此时的数据变化会被解读为控制命令(START或STOP)。

图6. 单字节数据传输示例
2.4 应答(ACK)与非应答(NACK)
每个数据字节(包括地址字节)后,都跟随一个由接收方发出的应答位。ACK位使接收方能告知发送方“字节已成功接收,可继续发送”。
在接收方发出ACK之前,发送方必须释放SDA线。为了发送ACK,接收方应在第9个时钟周期(ACK周期)的低电平阶段将SDA线拉低,并确保在时钟高电平阶段SDA保持稳定的低电平。建立和保持时间必须满足。
若在第9个时钟周期内,SDA线保持高电平,则被视为NACK。产生NACK的常见情况包括:
- 接收器正处理实时任务,未准备好通信。
- 接收器收到了无法识别或无效的数据或命令。
- 接收器已无法接收更多数据字节。
- 主设备作为接收器时,在读取完所需数据后,通过发送NACK告知从设备传输结束。

图7. NACK波形示例
三、 总结
I2C总线凭借其简洁的硬件架构与可靠的通信协议,在嵌入式系统中得到了广泛应用,有效减少了引脚数量、降低了布线与系统成本。这种基于开漏输出和明确时序规约的设计,是理解和应用I2C的关键。
在下一篇文章中,我们将详细剖析I2C协议中的从设备寻址机制。