I2C(Inter-Integrated Circuit:内置集成电路)总线的概念:
I2C通讯只需要2条双向总线——一条数据线SDA(serial data:串行数据线),一条时钟线SCL(serial clock:串行时钟线)。SDA线用于传输数据,SCL线用于同步数据收发。SDA线传输数据是大端传输(字节高位先传),每次传输8bit,即1字节。支持多主控(multi-mastering),任何时间点只能有一个主控。每个连接到总线的设备都有一个独立的地址addr,共7个bit,主机正是利用该地址对设备进行访问。SDA和SCL总线都需要连接上拉电阻,当总线空闲时,两根线均为高电平。连接到总线上的任意器件输出低电平都会将总线信号拉低,即各器件的SDA和SCL都是线与的关系。多个主机同时使用总线时,需要用仲裁方式决定哪个设备占用总线,不然数据将会产生冲突。
I2C总线的位传输
数据传输:SCL为高电平时,SDA线必须保持稳定,SDA上传输1个bit数据;数据改变:SCL为低电平时,SDA线才可以改变电平。
I2C总线的开始和结束信号
开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。起始信号由主控制器产生。
结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。结束信号也只能由主控制器产生。
I2C总线的字节格式
发送到SDA线上的每个字节必须是8位,每次传输可以发送的字节数量不受限制,每个字节后必须跟一个ACK应答位,数据从最高有效位(MSB)开始传输。如果从机要完成一些其他功能后(如一个内部中断服务程序)才能接收或发送下一个完整的字节,可以使时钟线SCL保持低电平迫使主机进入等待(wait)状态。当从机准备好新的字节数据传输时,释放时钟线SCL,数据传输便继续进行。
I2C应答信号ACK/NACK
主机每发送完8bit数据后等待从机ACK。即在第9个clock,若从机发回ACK,SDA会被拉低。若没有ACK,SDA会被置高,这会引起主控发生RESTART或STOP流程。相关的响应时钟脉冲由主机产生,在相应的时钟脉冲期间,发送器释放SDA线(高电平)。在响应的时钟脉冲期间,接收器必须将SDA线拉低,使它在这个时钟脉冲的高电平期间保持稳定的低电平。通常,被寻址的接收器在接收到的每个字节后,必须产生一个响应,当从机不能响应从机地址时,从机必须使数据线保持高电平,主机然后产生一个停止条件终止传输或者产生重复起始条件开始新的传输。
I2C总线上的所有数据都是以8位字节传送的,发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。 对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。 如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。
SDA 线上发送的每个字节必须为8 位,其后必须跟一个响应位。传输过程中每次可以发送的字节数量不受限制。首先传输的是数据的最高位(MSB)。 如果从机要在完成一些其他功能之后才能接收或发送下一个完整的数据字节,则可以使时钟线SCL 保持低电平,从而迫使主机进入等待状态。当从机准备好接收下一个数据字节,并且释放时钟线SCL 后,数据传输继续。
I2C总线传输的每个字节为8位,受控的器件在接收到8位数据后,在第9个时钟脉冲必须输出低电平作为应答信号,同时,要求主控制器在第9个时钟脉冲位上释放SDA线,以便受控器发出应答信号,将SDA线拉低,表示接收数据的应答(ACK)。如果在第9个时钟周期收到非应答信号(NACK),则表示停止数据的发送或接收。
I2C总线必须由主器件控制,即必须由主控器产生开始信号、停止信号和时钟信号。在时钟信号为高电平期间,数据线上的数据必须保持稳定,数据线上的数据状态仅在时钟为低电平期间才可以改变,而当时钟线为高电平期间,数据线上数据的改变被用来表示起始和停止条件。需要说明的是,当主控器接收数据时,在最后一个数据字节,必须发送一个非应答信号(NACK),使受控器释放数据线,以便主控器产生一个停止信号来终止总线的数据传送。
I2C时钟同步
SCL线被有最长低电平周期的器件保持低电平,此时,低电平周期短的器件会进入高电平的等待状态。当所有的器件数完它们的低电平周期后,时钟线被释放并变成高电平,所有的器件开始数它们的高电平周期,最先完成高电平周期的器件会再次将SCL线拉低。所以,产生的同步SCL时钟的低电平周期由低电平时钟周期最长的器件决定,而SCL时钟的高电平时钟周期由高电平时钟周期最短的器件决定。
如果被控器希望主控器降低数据的传送速度,可以通过将SCL线主动拉低延长其低电平时间的方法来通知主控器,当主控器在准备下一次传送发现SCL线的电平被拉低时就进行等待,直到被控器完成操作并释放SCL线的控制权。这样一来,主控器实际上受到被控器的时钟同步控制。可见,SCL线上的低电平是由时钟低电平最长的器件决定;高电平的时间由高电平时间最短的器件决定。这就是时钟同步,它解决了I2C总线的速度同步。
SCL同步是由于总线具有“线与”的逻辑功能,即只要有一个节点发送低电平时,总线上就表现为低电平。当所有的节点都发送高电平时,总线才能表现为高电平。正是由于“线与”逻辑功能的原理,当多个节点同时发送时钟信号时,在总线上表现的是统一的时钟信号,这就是SCL的同步原理。
I2C总线的仲裁机制
当SCL线是高电平时,仲裁在SDA线上发生。在其他主机发送低电平时,发送高电平的主机将会断开它的数据传输级,因为总线上的电平与它自己的电平不同(线与连接)。
假设主控器1要发送的数据DATA1为“101 ……”;主控器2要发送的数据DATA2为“1001 ……”总线被启动后两个主控器在每发送一个数据位时都要对自己的输出电平进行检测,只要检测的电平与自己发出的电平一致,他们就会继续占用总线。在这种情况下总线还是得不到仲裁。当主控器1发送第3位数据“1”时(主控器2发送“0”),由于“线与”的结果SDA上的电平为“0”,这样当主控器1检测自己的输出电平时,就会测到一个与自身不相符的“0”电平。这时主控器1只好放弃对总线的控制权;因此主控器2就成为总线的唯一主宰者。
SDA线的仲裁也是建立在总线具有线“与”逻辑功能的原理上的。节点在发送1位数据后,比较总线上所呈现的数据与自己发送的是否一致。是,继续发送;否则,退出竞争。SDA线的仲裁可以保证I2C总线系统在多个主节点同时企图控制总线时通信正常进行并且数据不丢失。总线系统通过仲裁只允许一个主节点可以继续占据总线。
上图是以两个节点为例的仲裁过程。DATA1和DATA2分别是主节点向总线所发送的数据信号,SDA为总线上所呈现的数据信号,SCL是总线上所呈现的时钟信号。当主节点1、2同时发送起始信号时,两个主节点都发送了高电平信号。这时总线上呈现的信号为高电平,两个主节点都检测到总线上的信号与自己发送的信号相同,继续发送数据。第2个时钟周期,2个主节点都发送低电平信号,在总线上呈现的信号为低电平,仍继续发送数据。在第3个时钟周期,主节点1发送高电平信号,而主节点2发送低电平信号。根据总线的线“与”的逻辑功能,总线上的信号为低电平,这时主节点1检测到总线上的数据和自己所发送的数据不一样,就断开数据的输出级,转为从机接收状态。这样主节点2就赢得了总线,而且数据没有丢失,即总线的数据与主节点2所发送的数据一样,而主节点1在转为从节点后继续接收数据,同样也没有丢掉SDA线上的数据。因此在仲裁过程中数据没有丢失。
总结:SDA仲裁和SCL时钟同步处理过程没有先后关系,而是同时进行的。
不难看出:
①对于整个仲裁过程主控器1和主控器2都不会丢失数据;
②各个主控器没有对总线实施控制的优先级别;
③总线控制随机而定,遵循“低电平优先”的原则,即谁先发送低电平谁就会掌握对总线的控制权。
根据上面的描述,“时钟同步”与“总线仲裁”可以总结如下规律:
①主控器通过检测SCL线上的电平来调节与从器件的速度同步问题——时钟同步;
②主控器通过检测SDA线上自身发送的电平来判断是否发生总线“冲突”——总线仲裁。因此,I2C总线的“时钟同步”与“总线仲裁”是靠器件自身接口的特殊结构得以实现的。
I2C总线的7位地址格式和7位寻址
- SCL由master提供,只有master才能同时控制SCL和SDA。
- SCL为低电平时才能改变数据,SCL为高电平时,数据有效。
- 起始条件:当SCL为高电平时,master拉低SDA,总线进入start状态。
- 结束条件:当SCL为高电平时,master拉高SDA,总线进入stop状态。
- 无论是发送地址还是数据,其后都紧跟着一个ACK/NACK。ACK和NACK由slave提供。
- ACK:在第9个CLK周期,slave拉低SDA,发送一个ACK。
- NACK:在第9个CLK周期,slave保持SDA为高,发送一个NACK。
- 一次可以传输多个字节,直到master发送start/stop。
- 如果slave设备来不及处理data,它可以保持SCL为低,强制master进入等待状态。
在起始条件(S)后,发送一个从机地址。地址共有7bit,紧接着的第8bit是数据的读写标志位 ——“0”表示写,“1”表示读。数据传输一般由主机产生停止位(P),但是如果主机仍希望在总线上通信,它可以产生重复起始条件(Sr)和寻址另一个从机,而不是首先产生一个停止条件。在这种传输中,可以有不同的读/写格式组合。
子地址:
带有i2c总线的器件除了有从机地址(salve address)外,还可能有子地址。从机地址是指该器件在i2c总线上被主机寻址的地址,而子地址是指该器件内部不同器件或存储单元的编址。例如,带i2c接口的EEPROM就是拥有子地址器件的典型代表。
主机发送数据流程:
(1)主机在检测到总线为“空闲状态”(即 SDA、SCL 线均为高电平)时,发送一个启动信号“S”,开始一次通信的开始
(2)主机接着发送一个命令字节。该字节由 7 位的外围器件地址和 1 位读写控制位 R/W组成(此时R/W=0)
(3)相对应的从机收到命令字节后向主机回馈应答信号 ACK(ACK=0)
(4)主机收到从机的应答信号后开始发送第一个字节的数据
(5)从机收到数据后返回一个应答信号 ACK
(6)主机收到应答信号后再发送下一个数据字节
(7)当主机发送最后一个数据字节并收到从机的 ACK 后,通过向从机发送一个停止信号P结束本次通信并释放总线。从机收到P信号后也退出与主机之间的通信。
注意:①主机通过发送地址码与对应的从机建立了通信关系,而挂接在总线上的其它从机虽然同时也收到了地址码,但因为与其自身的地址不相符合,因此提前退出与主机的通信;②主机的一次发送通信,其发送的数据数量不受限制。主机是通过 P 信号通知发送的结束,从机收到 P 信号后退出本次通信;③主机的每一次发送后都是通过从机的 ACK 信号了解从机的接收状况,如果应答错误则重发。
主机接收数据流程:
(1)主机发送启动信号后,接着发送命令字节(其中 R/W=1)
(2)对应的从机收到地址字节后,返回一个应答信号并向主机发送数据
(3)主机收到数据后向从机反馈一个应答信号
(4)从机收到应答信号后再向主机发送下一个数据
(5)当主机完成接收数据后,向从机发送一个“非应答信号(ACK=1)”,从机收到ASK=1 的非应答信号后便停止发送
(6)主机发送非应答信号后,再发送一个停止信号,释放总线结束通信
注意:主机所接收数据的数量是由主机自身决定,当发送“非应答信号/A”时从机便结束传送并释放总线(非应答信号的两个作用:前一个数据接收成功,停止从机的再次发送)。