I2C-1-----I2C协议和工作流程
(资料图)
1.I2C的线控和收发步骤
I2C 总线是一个标准的双向接口,使用一个称为主器件的控制器与从器件进行通信。物理I2C接口由串行时钟线SCL和串行数据线SDA组成。SDA和SCL线都必须通过上拉电阻器连接到VCC。上拉电阻器的大小由I2C线路上的电容量决定(有关I2C的Cbus计算后面会专门讲到)。数据传输只能在总线空闲时启动。如果在STOP条件后SDA和SCL线均为高电平,则总线被视为空闲。
除非被主器件成功寻址,否则从器件无法传输数据。I2C总线上的每个器件都有一个特定的器件地址,用于区分同一个I2C总线上的其他器件。许多从属设备在启动时需要配置以设置设备的行为。这通常在主机访问具有唯一寄存器地址的从机内部寄存器映射时完成。一个设备可以有一个或多个寄存器,用于存储、写入或读取数据。I2C与器件之间的通信由主器件发送一个 启动条件而开始, 并由主器件发送一个停止条件而终止。在SCL为高电平时在SDA线上进行的从高到低转换定义了启动条件。当主器件通过产生一个启动条件控制了总线时,除非停止条件释放总线,否则所有其他主器件都无法控制总线。在SCL为高电平时在SDA线上进行的 从低到高转换定义了停止条件。在启动条件与停止条件之间,必须执行数据通信。
主设备访问从属设备的一般程序如下:
下面是主器件要向从器件发送或写入数据时的步骤:
步骤一,主发送器发送一个启动条件并寻找从接收器的地址。
步骤二,主发送器向从接收器发送数据。
步骤三,主发送器利用一个停止条件终止传输。
下面是主器件要从从器件接收或读取数据时的步骤:
步骤一,主接收器发送一个启动条件并寻找从发送器的地址。
步骤二,主接收机将请求的寄存器发送到从发射机进行读取
步骤三,主接收器从从发送器接收数据。
步骤四,主接收器利用一个停止条件终止传输。
2.启动和停止条件
与该设备的I2C通信由主机发送START条件启动,并由主机发送STOP条件终止。当SCL为高时,SDA线上的高到低转换定义了START条件。当SCL为高时,SDA线上的低到高转换定义STOP条件。图2-1演示了Start和Stop的波形:
图2-1:启动和停止条件示例
3.重复启动条件
重复启动条件类似于启动条件,用于替代背靠背的先停止后启动条件。它看起来与START条件相同,但与START条件不同,因为它发生在STOP条件之前(当总线不空闲时)。当主设备希望启动新的通信,但不希望在STOP条件下让总线空闲时,这非常有用,这有可能导致主设备失去对另一主设备的总线控制(在多主设备环境中)。
4. 数据有效性和字节格式
在SCL的每个时钟脉冲期间传送一个数据位。SDA线上的一个字节由八位组成。字节可以是设备地址、寄存器地址,也可以是从设备写入或读取的数据。数据首先传输最高有效位(MSB),最高有效位MSB位于数据帧的开头, 最低有效位LSB位于数据帧的末尾, 后面跟随确认ACK或未确认NACK。任何数量的数据字节都可以在START和STOP条件之间从主设备传输到从设备。SDA线上的数据必须在时钟周期的高相位期间保持稳定,因为SCL为高时数据线中的变化被解释为控制命令(START或STOP)。
图2-2:单字节数据传输示例,此时SDA线稳定,SCL线高
图2-2展示了一个发送1、0、1、0、1、0、1、0的示例,以十六进制表示为AA,包含一个ACK。当SCL为高电平时,会将数据线中的变化视为控制指令,例如启动和停止。数据的每个字节,包括地址字节,后面都跟随一个来自接收器的ACK位。ACK位允许接收器向发送器告知它已成功收到字节,可以发送另一个字节了。在接收器可以发送ACK之前,发送器必须释放 SDA 线。要发送ACK位,接收器必须在ACK/NACK相关时钟周期,即周期9的低相位期间拉低 SDA 线。当SDA线在ACK/NACK相关时钟周期期间保持高电平时,将被视为NACK。必须考虑设置时间和保持时间。
5.确认(ACK)和不确认(NACK)
有几个条件会导致生成NACK。
条件一,接收器正在执行某个实时功能,且未准备好开始与主器件进行通信,因此无法接收或发送数据。
条件二,在传输期间,接收器收到了它无法理解的数据或指令。
条件三,在传输期间,接收器无法再接收更多的数据字节。
条件四,主接收器已读取数据,并通过NACK向从器件表明了这种情况。
图2-3:NACK示例,SDA线在ACK/NACK相关时钟周期期间保持高电平时,视为NACK
6.数据传输
数据必须发送到从设备或从从设备接收数据,但实现这一点的方式是读取或写入从设备中的寄存器。寄存器是从存储器中包含信息的位置,无论是配置信息还是要发送回主存储器的一些采样数据。主设备必须将信息写入这些寄存器,以便指示从设备执行任务。虽然I2C从设备中有寄存器是常见的,但请注意,并非所有从设备都有寄存器。有些设备很简单,只包含一个寄存器,可以通过在从地址之后立即发送寄存器数据而不是寻址寄存器来直接写入。单个寄存器设备的一个例子是8位I2C开关,它通过I2C命令控制。由于它有1位来启用或禁用信道,所以只需要1个寄存器,而主机只在从地址之后写入寄存器数据,跳过寄存器号。
1.在I2C总线上写入从设备:
图2-4显示了一个向从器件写入两个字节时的位和条件模式。主器件在总线上生成一个启动条件。主器件生成一个7位的从器件地址以及最后一个位,即读取/写入位。在本例中,此位是一个写入位,被设置为0,表示为负W。假设总线上存在一个具有此地址的从器件,则此从器件 会生成ACK。随后,主器件会发送8个连续寄存器位或曰字节,从器件随后会生成一个ACK以 确认收到这些位。接下来,主器件会发送第二组连续位,也就是第二个字节,从器件会随即再次确认,以告知主器件它已收到此字节。然后,主器件会生成停止条件以终止此事务。
要在I2C总线上写入,主设备将在总线上发送一个启动条件,其中从设备的地址以及设置为0的最后一位(R/W位)表示写入。在从设备发送确认位后,主设备将发送它希望写入的寄存器的寄存器地址。从设备将再次确认,让主设备知道它已经准备好了。此后,主设备将开始向从设备发送寄存器数据,直到主设备发送了所需的所有数据(有时仅为一个字节),并且主设备将在STOP条件下终止传输。灰色显示主机控制SDA线,白色显示从机控制SDA线。
图2-4:显示了将单个字节写入从寄存器的示例
2.从I2C总线上的从设备读取:
从从设备上读取与写入非常相似,但需要额外的步骤。为了从从设备读取数据,主设备必须首先指示从设备要读取的寄存器。这是通过主机以与写入类似的方式开始传输,发送R/W位等于0(表示写入)的地址,然后是它希望从中读取的寄存器地址来完成的。一旦从设备确认该寄存器地址,主设备将再次发送START条件,随后是R/W位设置为1的从设备地址(表示读取)。这一次,从设备将确认读取请求,主设备释放SDA总线,但将继续向从设备提供时钟。在数据的这一部分,主设备将成为主接收机,从设备将成为从发射机。
主设备将继续发送时钟脉冲,但将释放SDA线路,以便从设备可以传输数据。在数据的每个字节结束时,主机将向从机发送ACK,让从机知道它已经准备好接收更多数据。一旦主设备接收到预期的字节数,它将发送NACK,向从设备发出信号以停止通信并释放总线。主机将使用STOP(停止)条件进行跟踪。
图2-5:显示了从从寄存器读取单个字节的示例
图2-5是一个从从器件读取两个字节的位和条件模式。主器件在总线上生成一个启动条件。主器件生成7位的从器件地址以及最后一个位, 即读取/写入位。在本例中,此位是一个读取位,被设置为 1,表示为字母R。假设总线上存在一个 具有此地址的从器件,则此从器件 会生成一个ACK。随后,从器件会发送8个连续寄存器位或一个字节,主器件随后会生成一个ACK以确认收到这些位。接下来,从器件会发送第二组连续位,也就是第二个字节,但主器件将不确认,即NACK,告知从器件它已接收完这些数据。然后,主器件会生成停止条件以终止此进程。这两种模式代表主器件与从器件之间进行的最基本读取和写入操作。
标签: