I2C总线详解

时间:2024-06-01 10:45:53

1 I2C简介

总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线。而I2C总线最大的优点之一就在于,它只需数据(SDA)和时钟(SCL)两根总线就可以支持主设备与多个从设备之间进行通信。图1显示了嵌入式系统的典型I2C总线。 微控制器代表I2C主控制器,作为主设备,并控制各个从设备,这些从设备包括但不限于,IO扩展器,各种传感器,EEPROM,ADC/DAC等等。 而所有这些都只由主设备的2个引脚控制。
I2C总线详解

图1 典型I2C总线

2 I2C电气特性

I2C总线由两根双向信号线组成。一根是数据线SDA,另一根是时钟线SCL。I2C采用了漏极开路的设计,只会拉低总线,或“释放”它并让上拉电阻将其拉高。空闲状态下(即总线上无数据传输时),两条信号线经由上拉电阻后同时处于高电平。图2展示了拉低总线时的电流流动。 当想要传输低电平的逻辑时,会**下拉场效应管,这将导致总线接地短路,实现总线的拉低。
I2C总线详解

图2 使用漏极开路接口拉低总线

当从设备或主设备希望传输逻辑高电平时,它只需通过关闭下拉场效应管来释放总线。即可使得总线电压上浮,并且上拉电阻器将总线电压上拉到电源电压,这将被解释为高电平。图3展示了通过上拉电阻的电流流动。关闭下拉场效应管相当于使其开路,从而使得总线无法接地,实现总线的拉高。
I2C总线详解
图3 使用漏极开路接口释放总线

3 I2C接口

I2C总线具有标准双向接口,由主设备触发从设备的数据传输,从设备不能主动传输数据。

3.1 START和STOP条件

当主设备想要与从设备通信时,主设备通过发送STAR或STOP条件来启动或停止数据传输。 图4展示了一个START和STOP条件示例,当SCL为高电平时,SDA线上由高到低的转换定义了START条件。 当SCL为高电平时,SDA线上由低到高的转换定义了STOP条件。
I2C总线详解

图4 START和STOP条件示例

3.2 数据有效性和字节格式

如图5所示,当主设备发送START条件后,SCL在每个时钟脉冲期间SDA仅能传输一个数据位,也就是说SDA传输一个字节需要8个SCL时钟周期。 这个字节可以是器件地址,寄存器地址,也可以是写入从器件或从器件读取的数据。 数据首先传输最高位(MSB)。 在START和STOP条件之间,可以从主设备向从设备传输任意数量的数据字节。注意:SDA线上的数据必须在时钟周期的高电平期间保持稳定,因为当SCL为高电平时数据线的变化被解释为控制命令(START或STOP)。

3.3 ACK和NACK

在每个数据字节或地址字节传输完成后,还有一个来自接收方的ACK/NACK位。
当在ACK/NACK相关时钟周期期间SDA线保持低电平时,这被解释为ACK。ACK位表示字节数据传输有效,可以发送下一个字节。在接收方发送ACK之前,发送方必须释放SDA线。使得接收器能够在ACK/NACK相关时钟周期的低相位期间下拉SDA线。
当在ACK/NACK相关时钟周期期间SDA线保持高电平时,这被解释为NACK。 有几个条件会导致生成NACK:
• 通信方无法接收或发送,因为它正在执行某些实时功能,并且尚未准备好开始与主站通信。
• 在传输期间,接收方获取它不理解的数据或命令。
• 在传输期间,接收方不能再接收任何数据字节。
• 主接收器完成读取数据并通过NACK向从设备指示。
I2C总线详解
I2C总线详解

图5 ACK、NACK及单字节数据传输示例

4 I2C 数据传输

I2C总线上的每个从设备都有其特定的设备地址,以便主设备对I2C总线上的多个从设备进行管理。为了实现主设备对从设备数据的写入和读取,通常方式是通过从设备中的寄存器来实现的。
寄存器作为从设备的数据存储单元,包含某些特定的信息。主设备无论是准备写入配置信息,或是读取数据信息,必须先向从设备的寄存器写入特定指令,以指示从设备完成相应任务。

4.1 对从设备写入数据

如图6所示,当主设备通过I2C总线向从设备写入数据时,主设备需首先在总线上发送带有从设备地址的起始条件,并且最后一位设置为0(R/W位),该位表示写入。 从设备发送应答位后,主设备将发送它希望写入的寄存器的寄存器地址。 从设备将再次确认,让主设备知道它准备好了。 在此之后,主设备将开始将数据发送到从设备的寄存器,直到主设备发送了所需的所有数据(有时这只是一个字节),主设备将以STOP条件终止传输。 I2C总线详解

图6 对从寄存器写入单个字节的示例

4.2 对从设备读取数据

如图7所示,对从设备的读取与写入非常相似,但需要一些额外的步骤。 为了对从设备读取,主设备必须首先向从设备指示它希望从哪个寄存器读取。 这是由主设备以与写入类似的方式开始传输,通过发送R/W位等于0(表示写入)的地址,然后是希望从中读取的寄存器地址。 一旦从设备确认该寄存器地址,主设备将再次发送START条件,然后是从设备地址,R/W位设置为1(表示读取)。 这次,从设备将确认读取请求,主设备释放SDA总线,但将继续向从设备提供时钟。 在通讯的这一部分期间,主设备将成为主接收器,从设备将成为从发送器。
主设备将继续发送时钟脉冲,但将释放SDA线,以便从设备可以传输数据。 在每个数据字节结束时,主设备将向从设备发送ACK,让从设备知道它已准备好接收更多数据。 一旦主设备收到了预期的字节数,它就会发送一个NACK,向从设备发出信号以停止通信并释放总线。然后主设备将以STOP条件结束通讯。
I2C总线详解

图7 对从寄存器读取单个字节的示例