【转】I2C总线协议
I2C总线(Inter Integrated-Circuit)是由PHILIPS公司在上世纪80年代发明的一种电路板级串行总线标准,通过两根信号线——时钟线SCL和数据线SDA——即可完成主从机的单工通信。总线硬件连接极其简单,不同I2C设备挂接在总线上,只需在信号线安装上拉电阻即可完成硬件线路的搭建。另外,I2C总线采用器件地址的硬件设置方法,通过软件寻址方式完全避免了片选寻址的弊端,从而使硬件系统扩展更为灵活。
由于简单有效,I2C在业界得到广泛应用。基于I2C衍生出来的标准有SMBus、PMBus、IPMI、DDC和ATCA等。常见集成I2C硬件接口的设备有微控制器、温度传感器、LED控制器、EEPROM、ADC/DAC、RTC、时钟振荡器和I/O控制器等。
I2C总线最主要的优点是其简单性和有效性,其次I2C支持多主机(Multi-Mastering),任何能够进行发送和接收的设备都可以成为主机。主机控制数据的传输和时钟的频率。在任何时间点只能有一个主机。因为只有两条线,在处理地址和应答时,I2C存在一定的开销,效率不如设备直接相连的SPI总线。
下面就I2C总线的主要特点、总线操作、同步和仲裁、电接口特点等作简单介绍。
一、主要特点
- I2C只有两根信号线:串行数据线SDA和串行时钟线SCL;
- I2C总线上所有器件的SDA、SCL引脚输出驱动都为漏极开路结构,通过外接上拉电阻实现总线上所有节点SDA、SCL信号的“线与”逻辑关系;
- 总线上的所有设备通过软件寻址且具有唯一的地址(7位或10位)。7位“从机专用地址码”,其高4位为设备类型地址(由生产厂家制定),低3位为器件引脚定义地址(由使用者定义);10位地址不常见;
- 任何时刻都只存在简单的主/从关系,按数据传输的方向,主机可以是主发送器或主接收器;
- 支持多主机。在总线上存在多个主机时,通过冲突检测和仲裁机制防止多个主机同时发起数据传输时存在的冲突;
- I2C总线上所有器件都具有“自动应答”功能,保证数据传输的正确性;
- 主机和从机的区别在于对SCL的发送权,只有主机才能发送SCL;
- I2C总线不仅广泛应用于电路板级的内部通信,还可以通过I2C总线驱动器进行不同系统间的通信;
- 支持传输速率包括标准模式(Standard Mode)100kb/s、快速模式(Fast Mode)400kb/s、增强快速模式(Fast Mode Plus)1Mb/s和高速模式(High Speed Mode)3.4Mb/s;极速模式(Ultra-Fast Mode),单向数据传输速率可达5Mb/s;
- I2C总线允许挂载最多的设备数量取决于总线上最大电容值,一般为400pf(Hs模式100pf)
表1. I2C总线概念定义
图1. I2C连接示意图(S和F模式)
I2C的数据(SDA)和时钟(SCL)信号都是双向的,通过电流源或上拉电阻接到电源(如图1示),VDD大小取决于I2C设备接口的耐压能力。两根线都为高时,总线处于空闲状态(IDLE)。I2C接口的特殊构造以实现“线与”功能,即每个信号接口都分为输出的漏极开路(或集电极开路)和输入缓冲器部分。“线与”逻辑是I2C实现时钟同步和总线仲裁的硬件基础。
“线与”功能
漏极开路/集电极开路的特点是不能输出高电平,必须通过外接上拉输出高电平。如果总线上有任何一个设备接口输出低电平,则整个总线的状态表现为低电平,由此实现I2C总线信号的“线与”功能。
“线与”功能的好处在于可以实现总线的仲裁控制。总线的控制权会交给最后一个输出低电平的设备,其它设备(输出为高)通过检测总线上的电平状态(表现为低),对比与自己输出状态不一致,则自动退出对总线的控制请求。
漏极开路/集电极开路的缺点是对于一个距离长的数据线,信号传输速率得不到有效保证。更长的走线对于输出驱动器表现为更大的容性负载,等效容性负载C和信号线的上拉电阻R构成RC振荡器。RC越大,意味着反射和振荡越强,从而影响总线的信号完整性。这也是I2C规范对总线电容值约束在400pf以内的原因。高速模式(Hs)对信号完整性的要求更高,协议有定义相关SDA/SCL处理办法,以保证在数据线够长、速率够高时,信号完整性也可以得到满足。
二、总线操作
- 数据有效性
协议没有规定I2C逻辑“1”和“0”的电平值,参考实际应用中的VDD。每传输一比特数据SDA,对应产生一个时钟脉冲SCL。SCL为高时,SDA不允许变化;只有在SCL为低时,SDA才可以变化(图2)。
图2. 位的传输
- 开始和结束条件
SDA和SCL的特定组合表示总线开始或结束一次数据传输。
开始条件(S):SCL为高时,SDA由高变低;
结束条件(P):SCL为高时,SDA由低变高。
图3. 开始和结束条件
开始/结束条件总是由主机(Master)发起的。主机发出开始条件(START)后,总线处于忙的状态;主机发出结束条件(STOP)后,总线处于空闲状态。
在操作中,如果主机发出重复开始条件(repeated START,Sr)而非结束条件(STOP),则总线仍处于忙的状态。也就是说,重复开始条件(Sr)和开始条件(S)在功能上是相同的。在本文(协议)中,除非特别说明,开始条件和重复开始条件统一表述为S。
判断开始或结束条件对于具有相应逻辑接口的设备相对简单,对于没有该接口的微控制器,需要在每个SCL周期内对SDA至少采样2次,才能正确检测到开始或结束条件。
- 字节格式
SDA上传输字节数据必须是8比特长度,每次传输不限定传输的字节数。每个字节(8位)数据传送完毕后紧接着应答信号(第9位,Acknowledge Bit)。数据传输过程中,先发送高位(MSB),再发送低位(LSB),如图4示。如果在数据传输过程中,从机如果没有准备好接收或发送下一个字节(比如内部中断需要处理等),它可以通过拉低SCL强制主机进入等待状态。直到从机释放SCL,主机才开始下一个字节的发送或接收。
图4. I2C总线的数据传输
- 应答
协议规定数据传输过程必须包含应答。接收器通过应答(1 bit)通知发送的字节已被成功接收,发送器可以进行下一个字节的传输。主机产生数据传输过程中的所有时钟,包括应答的第9个时钟。发送器在应答时钟周期内释放对SDA的控制,这样接收器可以通过将SDA拉低通知发送器数据已被成功接收(图5)。
图5. I2C总线的数据应答
参照图2说明,SCL为高的时候,SDA数据才是有效的,因此接收器发送ACK时,要保证SCL为高的同时,SDA为低电平;建立和保持时间也要满足规范要求。如果在第9个时钟周期,SDA为高,表明接收器无应答(NACK),主机可以据此发出结束条件(STOP)命令结束此次传输,或发起重传请求(repeated START)重新传输数据。有5种情况可能导致无应答(NACK):
- 总线上没有对应地址的接收器件;
- 接收器件没有准备好与主机的通信;
- 接收器件无法解析读取的数据;
- 接收器件无法收取更多的数据;
- 主机作为接收器(Master-Receiver)时,在读取从机(Slave-Transmitter)发出的最后一个字节数据后,发出NACK通知从发送器释放数据线SDA,以便主机发起结束(STOP)或重传(Sr)指令。
图6表示主机作为发送器和接收器在写和读情况下的数据格式(ACK/NACK)。
图6. I2C数据读写的格式
三、时钟同步和仲裁
I2C的一大特点是可以在同一条总线上接多个主机。两个及以上的主机同时发起传输请求时,需要通过某种机制确定哪个主机获得总线的使用权;另外,每个主机都独立产生时钟,时钟速率可能千差万别,这也需要某种机制解决时钟速率不一致的问题。这种机制就是时钟同步(Clock Synchronization)和仲裁(Arbitration)。在单主机的I2C系统中,不需要时钟同步和仲裁。
1.时钟同步
每个I2C的主机内部都有两个计数器,分别计数SCL上高电平和低电平的时间。如果总线上只有一个主机,则这两个计数器的值决定系统时钟速率。当多个主机存在时,不同设备的计数器速度可能不一致,因此涉及时钟同步的概念。
时钟同步是通过I2C接口的“线与”逻辑实现的。SCL信号线由高变低时,所有连接在SCL上的主机都开始计数低电平的时间(低电平计数器复位),由前文对“线与”逻辑的介绍可知:只有当SCL总线上所有主机的时钟输出端都为高时,SCL总线才会由低变高。SCL的低电平时间由总线上低电平时间最长的主机决定。时钟端口先跳变为高的其它主机进入等待状态(图7)。这样所有主机的时钟输出和SCL线上的状态保持相同;当SCL由低变高后,所有主机(高电平计数器)开始计数SCL高电平的时间;最早由高跳变到低的主机再次将SCL拉低。通过这种方式产生的同步时钟:其低电平时间是所有主机时钟中最长的低电平时间,其高电平时间是所有主机时钟中最短的高电平时间。
图7. 仲裁阶段的时钟同步
2.仲裁
当总线上有一个以上的主机时,协议通过仲裁的方法确定哪个主机获得总线的使用权。从机不参与仲裁的过程。
当总线处于空闲状态(IDLE)时,在最小的保持时间内(tHD;STA),多个主机都可能发起开始条件(START)在总线上传输数据。仲裁用来判断哪个主机的传输可以正常进行。
仲裁是按位进行的。仲裁开始时,对于每一位数据,SCL为高时,每个主机都检测SDA上的数据是否和自己发送的数据相同。可能需要进行多个位(bit)的比较,主机才开始检测到SDA上数据和自己发送的不一致。实际上,只要SDA上的数据和主机发送的数据一致,这些主机就可以将数据一致发送下去。当主机发送为HIGH,检测SDA上电平却为LOW,那么该主机就在仲裁中失去主控权,并将其SDA输出关闭。余下的主机获得总线控制权并继续数据的传输。如图8,当主机1在检测到SDA数据和它自身的输出DATA1不一致时,将自动关闭DATA1的输出,停止向总线上发送数据。
由此可见,在仲裁过程中胜出的主机是没有丢失数据的。在仲裁中失去总线控制权的主机在本次字节传输结束后继续产生时钟,并在总线空闲时开始上次数据的重传。如果同一个器件可以工作在主从两种模式,它在仲裁过程中失去总线控制权,那么有可能是仲裁胜出的主机将要访问该器件,该器件应该立即切换到从机模式。
图8. 两个主机的仲裁过程
从上面的原理分析可知,I2C不存在核心主机,是没有优先级的概念的。总线的控制权仅取决于主机在SDA上的竞争(SDA包含地址和数据)。
在仲裁过程中,存在以下未定条件会导致不可预期的结果:
- 主机1在主机2发送数据的过程中发出重复开始条件(Sr)
- 主机1在主机2发送数据的过程中发出结束条件(P)
- 主机1在主机发出结束条件(P)的过程中发出重复开始条件(Sr)
3.Clock Stretching
Clock Stretching 通过拉低SCL延迟数据的传输。Clock Stretching 是可选功能,实际上许多从机不包括SCL驱动器,因此也无法延迟时钟。
在字节级的数据传输中,接收器在下一个字节接收前,可能需要一段时间存储上一个接收的字节。从机可以在接收字节和发送ACK后将SCL置低,通知发送器延迟数据的发送,直到从机准备好,再次将SCL释放为止。从机以一种握手机制迫使主机进入等待状态,直到从机准备好接收下一个字节。
在位级的数据传输中,设备(例如有或没有I2C总线接口逻辑的微控制器)可以通过延长每个时钟的低电平时间降低总线的时钟速率,由此使得任何主机的速度都可以适配总线上设备的内部工作速率。
在Hs 模式,握手机制只在字节级数据传输中使用。
四、数据/地址模式
1.七位地址系统
开始条件(S)后的第一个字节包括寻址的从机地址(7 bit)和数据方向控制位R/W(1 bit),如图9。其中第8位数据方向控制位R/W:
- 0:主机写数据 TO 从机
- 1:主机读数据 FROM 从机
图9. START后的第一个字节格式
由读写位的特点可知对于I2C总线上的第一个字节,读操作都是奇数,写操作是偶数。有的厂商提供的是8位地址(包括读写位),这样对于读写会有两个不同的地址。更合理的办法是直接提供唯一的7位地址。如图10所示。
图10. 7位 vs 8位地址
主机发送结束条件(P)终止一次传输。主机也可以通过发起重复开始条件(Sr)进行一次新的传输,而不需要先产生结束条件(P)。在一次传输过程中,可能存在多种读写组合,包括:
- 主机作为发送,向从机发送(写)数据,传输的方向不变(图11);
图11. 7位地址主发从收模式
- 主机发送开始条件(S)以及其后的第一个字节,立即改为从总线上读取状态。收到从机的应答(ACK)后,主机由主发模式切换到主收模式,从机由从收模式切换到从发模式。第一个应答是从机发出的。主机先发送NACK,再发送结束条件(P)结束本次传输(图12);
图12. 主机在第一个字节后立即读取从机内容
- 混合模式(图13)。
图12. 混合模式
2.十位地址系统
采用10位地址系统扩充了I2C系统的地址范围。7位和10位地址设备可以共存于同一个I2C总线系统,并且可工作在所有速度模式。目前,使用10位地址系统的I2C设备不多。
10位从机地址由紧接着START(或Repeated Start)后的两个字节定义。
第一个字节的前七位格式为1111 0XX,其中最后两位XX表示10位地址空间的最高两位(MSB);第一个字节的第八位R/W,表示数据的方向。注意,第一个字节前七位1111 1XX为预留,方便未来协议升级。
所有7位地址系统包括的读/写模式,在10位地址系统中同样存在。举例其中两条如下:
- 主发送器向10位地址的从接收器发送数据。如图14所示,在整个过程中,数据传送方向没有改变。在START发起之后,所有从机对比总线上第一个字节的前七位(1111 0XX)是否和自身地址一致,并检测第八位是否为0(写)。可能有一个以上设备会检测到地址匹配(因为只对比了10位地址的最高2位),它们都会产生响应A1。接下来,所有上面响应的从机对比总线上第二个字节和它们各自地址的后八位(XXXX XXXX)是否一致。只有一个设备的地址匹配,并产生响应A2。被寻址的从机一直受主机控制,直到STOP或Sr指向另外的地址;
图14. 主发送器寻址从接收器(10位地址空间)
- 主接收器读取10位地址的从发送器发送的数据。数据传送方向在第二个R/W后发生改变。如图15所示,A2之前的操作和主发送器向从接收器写数据没有区别。通过Sr,匹配地址的从机得知它就是被寻址的设备,接下来从机检测Sr后的七个比特是否和先前START后的七比特一致(1111 0XX),并检测第八位(R/W)是否为1。如果是,则从机据此判断它被寻址并将要作为发送器往总线上发送数据,此时从机产生响应A3。从机一直占用总线,直到接收到STOP或Sr指向另一个从机地址。收到Sr信号后,所有从机都会对比Sr后第一个字节的前七位(1111 0XX),并检测该字节的第八位(R/W)。对于10位地址设备R/W=1,对于7位地址设备,地址(1111 0XX)不匹配,因此这些设备都不会响应Sr,不会被寻址。
图15. 主接收器寻址从发送器(10位地址空间)
3.保留地址
I2C系统保留地址如表2所示:
表2. I2C保留地址
4.通用广播地址
通用广播地址是为了寻址总线上所有设备。如果一个设备不需要使用广播功能,可以不响应广播。如果设备需要使用广播功能,则它在检测到广播地址后发送响应,并作为从接收器读取总线上发送的数据。主机不知道总线上有多少从机发送响应。总线上所有可以响应广播的从机读取广播地址后的第二个及后面的字节。不能处理这些广播数据的从机通过不发送响应的方式忽略它。同样地,如果有一个或一个以上的从机发送响应,则主机就检测不到总线上其它没有响应的设备。广播消息的含义总是定义在第二个字节(图16)。
图16. 广播消息格式
有两种可能情况:
- 最低位“B”为0
- 最低位“B”为1
“B”为0,第二个字节包括以下定义:
- 0000 0110(06h):复位并通过硬件写内容到从机的可编程部分。所有可以响应此类广播的从机,收到此两字节后,进行复位并进入它们地址的可编程部分。注意确保设备在加电后不会将SDA或SCL拉低,因为这些低电平会阻塞总线;
- 0000 0100(04h):通过硬件写内容到从机的可编程部分,作用类似(06h),但设备不会复位;
- 0000 0000(00h):这个不应该作为第二个字节用。
编程时序参考相应设备的DATASHEET。
“B”为1,两字节广播定义为“硬件广播”。主机(如键盘扫描器)在编程后,可以发送既定的从机地址到总线上,构成两字节序列的“硬件广播”。既然主机可能并不知道总线上从机的地址,它只能通过硬件广播的方式,将自身地址通知给系统。如图17所示:
图17. 主发送器的数据传输格式(硬件广播)
硬件广播的第二个字节的前七位包括主机的地址。总线上的智能设备如微控制器,读取此地址并接收主机发送的其它信息。如果主机也可以作为从机使用,则以上读取的主机地址实际上也就是(切换主从模式后的)从机地址。
在系统中,一种可能是系统复位后设备由主机发送模式切换到从机接收模式,这时由系统主机先告诉硬件主机数据应送往的从机地址,这样当硬件主机发送数据时就可以直接向指定从机(地址)发送数据了。
五、其它说明
1.软件复位
通用广播地址0000 0000后发送0000 0110(06h)可以使总线上设备进入复位过程。该功能是可选的,所有预留该功能的设备在收到该两字节序列(00 06h)后,开始响应(复位),并进入它们地址的可编程部分。注意确保设备在加电后不会将SDA或SCL拉低,因为这些低电平会阻塞总线。
2.START字节
起始字节是提供给没有I2C总线接口的单片机查询I2C总线时使用的特殊字节。
不具备I2C总线接口的单片机,必须通过软件不断地检测总线,以便及时响应总线请求。单片机的速度与硬件接口器件的速度可能存在较大的差别。为此,I2C上的数据传送需要一个较长的起始过程加以引导。引导过程由起始信号、起始字节、应答位、重复起始信号(Sr)组成。
图18. 起始字节
请求访问总线的主机发出开始条件(S)后,紧接着发送起始字节 0000 0001,总线上的单片机可以用比较低的速率采样SDA线,直到检测到起始字节中的7个“0”中的一个为止。在检测到SDA上的高电平后,单片机可以切换到较高的采样速率,采样作为同步信号使用的第二个起始信号Sr。
在起始信号后的应答时钟脉冲仅仅是为了和总线所使用的格式一致,并不要求设备在这个脉冲期间作应答。
3.Bus Clear
SCL:一般情况下,SCL不会拥堵(stuck)在低电平,出现这种情况的话,如果设备包含硬件复位引脚,推荐使用硬件复位。如果设备没有硬件复位引脚,可以通过重新上电方式触发设备内部上电复位电路(Power-On Reset Circuit)
SDA:如果SDA拥堵在低电平,主机应发送9个时钟脉冲,那些将SDA拉低的设备在这9个时钟周期内应释放总线。如果没有的话,则需要通过硬件复位或重新上电的方式清除拥堵。
4.设备号
设备号由三个字节(24bit)组成,包括以下信息:
- 12位厂商编号,每个厂商具有唯一的编号(如NXP);
- 9位设备编号,由厂商自定义(如PCA9698);
- 3位版本号,由厂商自定义(如RevX)
图19. 设备号编码规则
参考资料
I2C-bus specification and user manual Rev.6
http://www.lammertbies.nl/comm/info/I2C-bus.html
http://www.analog.com/static/imported-files/application_notes/54305147357414AN686_0.pdf
http://www.ti.com/lit/an/scaa106/scaa106.pdf
【转】I2C总线协议的更多相关文章
- [I2C]I2C总线协议图解
转自:http://blog.csdn.net/w89436838/article/details/38660631 1 I2C总线物理拓扑结构 I2C 总线在物理连接上非常简单,分别由S ...
- I2C总线协议的简要说明
为了快速的了解I2C总线协议,此处采用另类的方式进行说明. 倘若你和另外一个人只能通过一个开关加灯泡的装置在不同的两个房间进行交流,以下是很简单能说明的一个模型: 你的房间有一个开关,另外一间房间有一 ...
- I2C总线协议的总结介绍
在看天翔哥的视频之后,他强调要把I2C协议好好研究一下,那么就对一些基本的通信手段是十分有帮助的..那么就来了解一下I2C总线协议的一些知识吧. I2C(Inter-Integrated Circui ...
- I2C总线协议的软件模拟实现方法
I2C总线协议的软件模拟实现方法 在上一篇博客中已经讲过I2C总线通信协议,本文讲述I2C总线协议的软件模拟实现方法. 1. 简述 所谓的I2C总线协议的软件模拟实现方法,就是用软件控制GPIO的输入 ...
- I2C总线协议图解(转载)
转自:http://blog.csdn.net/w89436838/article/details/38660631 另外,https://blog.csdn.net/qq_38410730/arti ...
- I2C 总线协议
1.I2C协议 2条双向串行线,一条数据线SDA,一条时钟线SCL. SDA传输数据是大端传输,每次传输8bit,即一字节. 支持多主控(multimastering),任何时间点只能 ...
- I2C总线协议
1.I2C协议 2条双向串行线,一条数据线SDA,一条时钟线SCL. SDA传输数据是大端传输,每次传输8bit,即一字节. 支持多主控(multimastering),任何时间点只能有 ...
- I2C总线协议学习笔记 (转载)
1.I2C协议 2条双向串行线,一条数据线SDA,一条时钟线SCL. SDA传输数据是大端传输,每次传输8bit,即一字节. 支持多主控(multimastering),任何时间点只能有一 ...
- I2C总线协议详解
I2C总线定义 I2C(Inter-Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备.I2C总线产生于在80年代,最初为音 ...
随机推荐
- Patchwork(2013年)--CNV检测方法流程
文章题目:Patchwork: allele-specific copy number analysis of whole-genome sequenced tumor tissue 特点: 可以检测 ...
- 不成功的RMAN恢复到其他机器的例子
事实上,RMAN备份的时候,如果是使用control file 来作catalog,那么一定要把control file和spfile恢复到另外的机器上面. 否则,会出现类似如下的错误: 原来的实例: ...
- 05-python基础
1.python是什么? 解释性语言.高级语言.开源.简洁.方便.容易扩展 2.可变类型与不可变类型 可变类型:list.dict.可变集合set 不可变类型:数字,str,tuple元组,froze ...
- CS299笔记:广义线性模型
指数分布族 我们称一类分布属于指数分布族(exponential family distribution),如果它的分布函数可以写成以下的形式: \[ \begin{equation} p(y;\et ...
- Bluedroid协议栈HCI线程分析
蓝牙进程中有多个线程,其中HCI 线程是负责处理蓝牙主机端和控制器的数据处理和收发的工作. 本篇文章就是分析一下该线程的数据处理流程. 1.跟HCI相关的接口 首先看看hci的相关的接口:在hci_l ...
- CS50.3
1,int()取整函数 2,RPG(role playing game )角色扮演游戏 3,代码写了,要跑,需要compiler (编译器) 4,CLI(command-line interface) ...
- ElasticSearch查询 第二篇:文档更新
<ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...
- SSIS 更新变量
在Package中声明一个variable,在package运行的过程中,SSIS如何update Variable? 第一种方法:使用 Script Task 来更新Variable的值 1,创建一 ...
- Java 多线程(四)之守护线程(Daemon)
目录 定义 如何创建 判断 注意事项 函数setDaemon(true)必须在 start() 函数之前使用. 守护线程中产生的线程也是守护线程: 测试 @ 定义 Java 中有两种线程: 一种是用户 ...
- Grid布局20行代码快速生成瀑布流
网格布局 Grid 布局,好用又简单,至少比 Flex 要人性化一点,美中不足就是浏览器支持度差点. DOM结构 中间夹层为了后续拓展. CSS .grid { display: grid; grid ...