I2C总线接口协议、软硬件设计与测试综述
- I2C总线产生背景
I2C(或者IIC,Inter-Integrated Circuit)总线中文叫集成电路总线,它是一种使用主从架构的半双工中/低速串行通信总线,起源于飞利浦公司(PHILIPS)在上世纪八十年代为了让主板、嵌入式系统或手机用以连接其低速周边设备而发展的一种互联总线技术。随着大规模集成电路技术的发展,把CPU/MCU及其外围设备比如EEPROM、RAM、I/O端口、ADC、DAC等集成在一个单片内而制成的CPU/MCU愈来愈方便。然而应用系统的多样化需求与有限的CPU/MCU的品种、规格是一对矛盾,此时需要通过一种可以扩展的接口技术实现CPU/MCU与更多的外围设备间的互联以满足系统设计目标。相较于并行总线互联,串行总线因为其连线少,结构简单,互联实现成本低等优势应运而生,诸如UART、CAN、USB、SPI、I2C等都是广泛使用的串行接口技术。
- I2C总线接口结构与操作特征
I2C总线由两条信号线串行数据线SDA和串行时钟线SCL组成,通过这两条信号线将各个I2C主机和从机连接起来。
I2C总线硬件接口:如下图可见,每个支持I2C接口的器件在其接口信号SDA、SCL内部都有一个漏极开路OD门输出驱动(针对MOS工艺器件)或OC门输出驱动(针对双极型晶体管工艺器件)。任一占用总线的器件在驱动SDA/SCL时,同时也会监听到自己发送的串行数据或串行时钟信号。各个总线上的I2C器件其各自的SDA信号线是逻辑线“与”的关系,其中任意一个器件SDA引脚若输出为低电平,则总线上SDA信号即呈现为低电平;各个总线上的I2C器件其各自的SCL信号线也是逻辑线“与”的关系,其中任意一个器件SCL引脚若输出为低电平,则总线上SCL信号即呈现为低电平。
空闲状态:I2C总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管或双极型晶体管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。
起始位和停止位:起始信号定义为当SCL为高期间,SDA由高到低的跳变;停止信号定义为当SCL为高期间,SDA由低到高的跳变。
设备寻址和R/W位:主机要和从机通过I2C接口通信,必须在总线上启动发生起始位之后发送目标从机的地址。支持I2C器件地址在器件手册中可以查到,并且每个器件有唯一的地址。有的器件地址在出厂时地址就设置好了,用户不可以更改;也有的设置有可编程地址引脚,通过硬件设计来确定各从机器件各自的地址。标准模式下器件地址为7位,此时I2C总线理论上最多可以接128个I2C器件(当然实践中一条I2C总线上可以连接的接口器件数量还取决于总线上总的容性负载大小、主机器件的SCL/SDA引脚驱动能力、总线上拉电阻的阻值选取等等)。主机往总线上发送地址,所有的从机都能接收到主机发出的地址,然后每个从机都将主机发出的地址与自己的地址进行对比匹配,如果某从机地址匹配成功,这个从机就会向主机发出一个响应信号。主机收到响应信号后,开始向总线上发送数据,与这个从机的通讯就建立起来了。如果主机没有收到响应信号,则表示寻址失败。R/W位表示当前主机对从机的操作是读操作还是写操作,R/W=1表示读操作,R/W=0表示写操作。
目前I2C协议规范支持7位、8位、10位地址模式。
- 7位地址模式
在7位地址模式下,从机地址在启动信号后的第一个字节开始传输,该字节的前7位为从机地址,第8位为R/W位。7位地址模式的地址范围从0x00到0x7F,共128个地址。
- 8位地址模式
8位地址模式通常用于一些特殊情况,其中从机地址包含读写位。例如,写地址为0x92,读地址为0x93,实际上这些地址的前7位是0x49。
- 10位地址模式
10位地址模式允许使用高达1024个额外的从机地址,适用于需要更多从机地址的情况。在使用10位地址时,第一个字节是一个特殊的保留序列(11110)加上高2位地址和读写位,第二个字节为低8位地址。
数据传输:SDA线上的数据必须在时钟的高电平时期保持稳定,数据线的高或低电平状态只有在SCL线的时钟信号是低电平时才能改变1。每个字节的数据传输后,接收方会发送一个应答位(ACK,)或非应答位(NACK)来告知发送方是否成功接收数据。输出到SDA线上的每个字节必须是8位,每次传输的字节不受限制,但每个字节必须要有一个应答ACK。如果一接收器件在完成其他功能(如一内部中断)前不能接收另一数据的完整字节时,它可以保持时钟线SCL为低,以促使发送器进入等待状态;当接收器准备好接受数据的其它字节并释放时钟SCL后,数据传输继续进行。
时钟同步:I2C总线通过外部上拉电阻和漏极开路(OD,Open Drain)或集电极开路(OC,Open Collector)结构实现信号的“线与”逻辑。如果一设备发送逻辑0,其他发送逻辑1,线路看到的只有逻辑0。这样避免了电平冲突,实现了时钟同步。
总线仲裁:
总线仲裁是指在多主机模式下,多个主设备竞争使用I2C总线的过程。仲裁机制基于SDA线的电平状态进行。单主机模式下不会发生时钟同步,也不需要总线仲裁。
- 电平检测:每个主设备在发送数据时都会检测SDA线的电平状态。如果检测到的电平与自己发出的电平一致,则继续占用总线;如果不一致,则放弃。
- 冲突解决:当多个主设备同时发送数据时,如果某个设备发送的逻辑与总线上已有的逻辑不一致(例如,一个设备发送0而其他设备发送1),则总线上最终的电平为0(SDA线与的结果)。发送逻辑1的设备会检测到不一致的电平,从而放弃对总线的控制权,而发送逻辑0的设备继续发送数据。
- 仲裁结果:最终,只有一个设备能够成功发送数据并占用总线。其他设备需要等待下一次总线空闲后再次尝试发送。通过这些机制,I2C总线能够有效地管理多个设备之间的通信,确保数据的正确传输和总线的合理使用。仲裁处理是逐个bit进行的。在每个bit,当SCL为高,每个主机都检查一下来看看SDA的电平是否和它发送的电平吻合。这个过程可能会持续很多个bit。只要传输是同一的,那么两个主机可以无误的完成完整的传输.当一个主机试着发送高,但是检测到SDA为低,那么这个主机知道自己失去仲裁然后关掉自己的SDA输出,另外的主机就会去完成它的传输。
- 在仲裁处理过程中没有信息丢失。失去仲裁的主机在它失去仲裁的字节末尾处产生时钟脉冲,当总线空闲时必须重启它的传输。
- 如果一个主机包含从机的功能,当它在寻址阶段丢失仲裁,那么赢得仲裁的主机可能会寻址它,丢失仲裁的主机必须立即切换到它的从模式。
需要注意的是,多主机之间的时间同步(通过SCL信号线实现)和总线仲裁(通过SDA信号线实现)是同时进行的,没有先后顺序关系。
I2C总线的速率等级:
- 普通模式
- 标准模式(Standard Mode):双向最大传输速率为100 kbit/s,总线容性负载最大400pF。
- 快速模式(Fast Mode):双向最大传输速率为400 kbit/s,总线容性负载最大400pF。
- 快速模式Plus(Fast Mode Plus):双向最大传输速率为1 Mbit/s,总线容性负载最大550pF。
- 高速模式(High Speed Mode):双向最大传输速率为3.4 Mbit/s 或者1.7 Mbit/s,总线容性负载最大分别为100pF和400pF。本模式可以向下兼容较低总线速率,但是不支持时钟同步和仲裁功能。使用本模式必须首先发送告诉模式控制码00001XXX。
- 超快速模式(Ultra Fast Mode):单向最大传输速率为5 Mbit/s。超快模式下,SDA信号是单向传输,R/W位只能是0(代表写操作),不支持1(读操作)。同时SDA和SCL信号线是推挽输出,有别于普通模式下的OD/OC输出,无需总线上拉电阻。没有ACK,只有NACK。
- I2C总线软硬件设计
硬件设计需要考虑如下方面:
- 根据系统设计要求,确定I2C总线拓扑结构及每个I2C总线上连接的器件数量及各自速率要求,同时考虑成本因素。
- 结合每个I2C总线上需要连接的各个器件手册,确认该总线上总的容性负载不超过协议规范的上限。同时合理确定SDA/SCL信号线上拉电阻值(经验值一般为2kohm~10kohm),需要结合总线速率等级和器件接口驱动能力确定阻值以满足SDA/SCL信号的上升沿/下降沿时序和其他时序要求。
- 布局布线考虑信号完整性和抗干扰等要求。
软件设计考虑如下方面:
- 总线上开始信号和结束信号的探测,对于自带I2C硬件模块的器件很容易做到,但是对于没有此模块的CPU/MCU等器件必须使用软件模拟通过操作GPIO引脚来仿真实现I2C协议。此时每个时钟周期至少对SDA信号线进行两次采样才能感知转换。
- I2C总线挂死及解决方法:
在特定情况下会出现I2C总线挂死的情况,总线挂死的表现形式为:SCL一直为高电平,SDA一直为低电平。导致总线挂死原因:
-
- 当主设备向从设备发起I2C接口写访问,连续发起8个脉冲后SCL拉低,从设备将SDA拉低以响应主设备,如果此时主设备由于某种原因异常复位,其SCL引脚输出为高阻态,总线上SCL由于上拉变为高电平;而此时从设备正常工作,I2C继续响应主设备(从设备并不知道主设备异常复位),SDA一直为低电平,直到SCL变为低电平,才会结束应答信号。那么此时对于主设备而言,检测SDA为低电平,I2C总线被占用,主设备等待I2C总线释放;对从设备而言,SDA为低电平,等待主设备将SCL拉低后结束应答,释放SDA。这样一来就导致了总线死锁:主设备等待从设备释放SDA信号,从设备等待主设备拉低SCL信号,形成了死锁循环。
- 当主设备进行读操作时,I2C从设备应答后输出数据。如果此时主设备异常复位,而从设备正好输出数据0,也会导致I2C进入死锁状态。
I2C总线防挂死措施:
-
- 选择带复位的I2C从设备(会稍微增加设计的复杂性),若主设备在I2C访问时异常复位,也会一并复位I2C从设备,I2C总线恢复到空闲状态,避免死锁。
- 在I2C设备中增加Watchdog看门狗功能(会增加器件成本和设计的复杂性)
- I2C软件程序设计中,在检测到SDA低电平超过一定时间后,在SCL总线上产生至多9个时钟脉冲,第9 bit对应ACK信号,使I2C从死锁中恢复出来。主设备每发送一个时钟脉冲就检测SDA是否被释放,如果SDA已经被释放就再模拟产生一个停止信号,这样从设备就可以完成被挂起的读写操作,从死锁状态中恢复过来。但是这种方法有一定的局限性,因为大部分主设备的I2C模块由内置的硬件电路来实现,软件并不能够直接控制SCL信号模拟产生需要的时钟脉冲。
- I2C总线相关测试验证
I2C总线设计验证包括:
- 信号完整性和时序验证,比如SDA/SCL信号上升、下降时间,SCL时钟频率/占空比,启动/停止位建立/保持时间等等。
- 协议内容验证,可以通过内置I2C协议分析功能的示波器完成对于I2C接口数据帧结构、地址分析和传输读写数据分析等等。
普通模式下I2C总线时序要求如下:
参考时序图如下:
本文力求对于I2C总线规范的由来,协议规范及接口结构、操作特征,I2C接口软、硬件设计及其相关测试验证做一个全面的阐述。欢迎大家提出宝贵意见!