目录
2.5 Acknowledge (ACK) and Not Acknowledge (NACK)
2.6 The slave address and R/W bit
3.5 Series protection resistors
一.简介
I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。I2C通信的基本原理是通过对SCL和SDA线高低电平时序的控制,来产生I2C总线协议所需要的信号进行数据传递。在总线空闲状态时,时钟线和数据线一般被上拉电阻拉高,保持着高电平。I2C通信方式为半双工,只有一根SDA线,同一时间只可以单向通信。I2C (Inter – Integrated Communication, often called as I Squared C or I Two C).
I2C总线特征
1. I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址。
2. I2C总线上可挂接的设备数量受总线的最大电容400pF 限制,如果所挂接的是相同型号的器件,则还受器件地址位的限制。
3. I2C总线数据传输速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s。一般通过I2C总线接口可编程时钟来实现传输速率的调整,同时也跟所接的上拉电阻的阻值有关(符合电气规范)。
4. I2C总线上的主设备与从设备之间以字节(8位)为单位进行双向的数据传输。
二.通信协议
2.1 START and STOP conditions
I2C协议规定,总线上数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。总线在空闲状态时,SCL和SDA都保持着高电平。
起始条件:当SCL为高时,SDA由高到低的跳变,表示产生一个起始条件;
停止条件:当SCL为高时,SDA由低到高的跳变,表示产生一个停止条件。
在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他I2C器件无法访问总线;而在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次处于空闲状态。
2.2 RESTART conditions
start是在scl是高电平的时候sda的一个下降沿来表示一个i2c的开始信号,到了i2c传输的内部,scl是低电平的时候,所有数据都是无效的,也就是说,硬件上start只是操作sda,令sda产生下降沿。
restart是在一个i2c的时间段内实现在scl高电平的时候的一个sda的下降沿呢,因此,要实现,所操作的是线令sda成高电平,在令scl来个高电平,再令sda成低电平,其实质就是操作一个scl的高电平内产生一个sda的下降沿。原文
2.2 SDA and SCL logic levels
由于I2C总线可以连接到各种不同的技术设备(CMOS,NMOS,双极性),所以逻辑‘0’(LOW)和‘1’(HIGH)的电平不是固定的,取决于 VDD的电平。 通常输入参考电平设置为:VIL为0.3VDD,VIH为0.7VDD。 一些旧式设备的输入电平固定为VIL = 1.5 V和VIH = 3.0 V,但是所有新设备都要求该规格为30%/ 70%。
2.3 Data validity
在时钟的高电平期间,SDA线上的数据必须稳定,确保数据采样的正确性。 仅当SCL线上的时钟信号为LOW时,数据线的HIGH或LOW状态才能改变。 每个传输的数据位产生一个时钟脉冲。
2.4 Byte format
SDA线上的每个字节必须为八位。 每次传输可以传输的字节数不受限制。 每个字节后面必须有一个应答位(ACK)。 首先使用最高有效位(MSB)传输数据, 如果从机在执行其他功能之前(例如,服务于内部中断)无法接收或发送另一个完整的数据字节,则它可以将时钟线SCL保持为低电平以强制主机进入等待状态。 当从机准备好另一个数据字节时,数据传输将继续,并释放时钟线SCL。(MSB 最先传输最高位)
2.5 Acknowledge (ACK) and Not Acknowledge (NACK)
ACK信号发生在每个字节之后。 接收器向发送器发送信号,告知该字节已成功接收,并且可以发送另一个字节。 期间时钟脉冲全部由主机产生。
ACK信号的定义如下:发送器在确认时钟脉冲期间释放SDA线,因此接收器可以将SDA线拉低,并在此时钟脉冲的高电平期间保持稳定的低电平(还必须考虑建立和保持时间)。如图在第九个时钟脉冲期间SDA保持高电平时,这被定义为“NACK”信号。 然后,主机可以产生停止条件以中止传输,或产生重复的开始条件以开始新的传输。
2.6 The slave address and R/W bit
I2C总线上的每一个设备都对应一个唯一的地址,主从设备之间的数据传输是建立在地址的基础上,也就是说,主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样,只不过大多数从设备的地址是7位的,然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据。
2.7 Arbitration
I2C是多主机总线,即在一个I2C总线上每个器件都可以作为主机,但同一时间只能有一个器件作为主机,完成一次数据传输。当多个主机同时发起数据传输时就需要有一个有效的仲裁机制来确定当前哪一个主机可以取得总线控制权。
仲裁的过程是一位一位地进行。 在每个位中,当SCL为高电平时,每个主机检查SDA电平是否与发送的电平匹配。此过程可能需要很多位(重复)。 实际上,只要传输相同,两个主机就可以毫无错误地完成整个通信过程。 主机1尝试发送高电平DATA1=1,但检测到SDA=0,主机1知道它已失去仲裁并关闭其SDA输出驱动器。 主机2继续完成其事务。
2.8 Clock synchronization
SCL信号总是由主机发起,但在Arbitration过程中同时存在两个主机,这时候的SCL信号是怎么产生的呢?~~~ Clock synchronization
两个主设备可以同时开始在空闲总线上进行传输,此时两个主机都会在SCL总线上发送时钟信号,但由于I2C只具有一条时钟线,所以就需要有一种规则来定义多主机同时发起通信时的有效时钟信号------时钟同步。时钟同步基于线与功能来进行的。
2.9 Clock stretching
时钟扩展通过将SCL线保持为低电平来暂停数据传输过程。 直到再次释放高电平,数据传输才能继续。 时钟扩展是可选的,实际上,大多数从设备不包括SCL驱动程序,因此它们无法扩展时钟。
在以下情况发生时总线可能会出现时钟扩展现象:1.当从机I2C接受速率低于主机发送速率时,从机会将SCL拉低,让主机处于等待状态;2.当从机正在忙于处理其他任务时,如正在响应一个外部中断,这时从机也会拉低SCL线。
三.电气规范
VCC | I2C电源电压,通常范围为1.2 V至5.5 V |
GND | 接地点 |
SDA | 串行数据(I2C数据线) |
SCL | 串行时钟(I2C时钟线) |
Rp | 上拉电阻 |
Rs | 串联电阻 |
Cp | 线电容 |
Cc | 跨通道电容 |
3.1 IO引脚配置
SDA和SCL都是双向线路,通过电流源或上拉电阻器连接到正电源电压。 总线空闲时,两条线均为高电平。 连接到总线的设备的输出级必须具有漏极开路或集电极开路才能执行线与功能。对于单个主机应用程序,如果总线上没有会延长时钟的设备,则主机的SCL输出可以是推挽驱动器设计。
每一个I2C总线器件内部的SDA、SCL引脚电路结构都是一样的,引脚的输出驱动与输入缓冲连在一起。其中输出为漏极开路的场效应管,输入缓冲为一只高输入阻抗的同相器,这种电路具有两个特点:1)由于SDA、SCL为漏极开路结构(OD),因此它们必须接有上拉电阻 ;当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线"与"关系。2)引脚在输出信号的同时还将引脚上的电平进行检测,检测是否与刚才输出一致,为"时钟同步"和"总线仲裁"提供了硬件基础。
Push-pull输出,实际上内部是用了一对互补的MOSFET,当Q1导通、Q2截止时输出高电平;而当Q1截止导通、Q2导通时输出低电平。top transistor打开(bottom transistor关闭),输出为高电平;bottom transistor打开(top transistor关闭),输出低电平。Push-pull即能够漏电流(sink current),又可以集电流(source current)。一条总线上只能有一个push-pull输出的器件,对于单个主机应用程序,如果总线上没有会延长时钟的设备,则主机的SCL输出可以是推挽驱动器设计。
Open-drain输出,则是比push-pull少了个top transistor,只有那个bottom transistor。(就像push-pull中的那样)当bottom transistor关闭,则输出为高电平。此处没法输出高电平,想要输出高电平,必须外部再接一个上拉电阻(pull-up resistor)。Open-drain只能够漏电流(sink current),如果想要集电流(source current),则需要加一个上拉电阻。可以将多个开漏输出的Pin脚,连接到一条线上,形成“与逻辑”关系,即“线与”功能,任意一个线上电平变低后,开漏线上的逻辑就为0了。
3.2 bus hangs
在I2C总线协议中,许多的配置都是依赖于线与功能来实现的,线与功能在赋予I2C总线多主机仲裁,时钟同步,时钟扩展等良好特性的同时也带来了潜在的危险-I2C bus hangs。
因为线与这个特性,只要总线上任何一个器件拉低了SDA或者SCL,其他器件都无法拉高它们,看到的都是低电平。如果有器件不释放总线,则整个总线上的通讯都会被暂停,这种现象称为I2C bus hangs:I2C总线挂死。
因为I2C主机一般是可编程的器件,受我们控制,如果主机主动拉低了总线,我们可以通过调试代码了解原因,也可以很方便的通过复位I2C外设或者复位芯片来退出这种状态。而I2C从机往往不带RESET引脚,如果挂死了总线即使整个系统复位都无法解除,仅重新上下电才可以恢复。很多系统上是不可接受的,因此我们需要更加小心的处理I2C从机挂死的情况,下面分析也是针对I2C从机挂死来写的。
3.2.1 SDA挂死
在I2C总线协议中,许多的配置都是依赖于线与功能来实现的,线与功能在赋予I2C总线多主机仲裁,时钟同步,时钟扩展等良好特性的同时也带来了潜在的危险-I2C bus hangs。
因为线与这个特性,只要总线上任何一个器件拉低了SDA或者SCL,其他器件都无法拉高它们,看到的都是低电平。如果有器件不释放总线,则整个总线上的通讯都会被暂停,这种现象称为I2C bus hangs:I2C总线挂死。
先来看下哪些情况下I2C从机需要拉低SDA线。
1.主机向从机写数据或地址时,从机如果发出ACK应答,则会第9个CLK的期间拉低SDA。
2.主机读数据的时候,从机会在bit为0时对应的CLK期间拉低SDA。
那什么情况I2C从机可能钳住SDA线呢?我们先来看一个典型的I2C主机发起对某一器件地址读操作,读到的数据为10011000b,MSB在先也就是0x98。在图中地址字节第9个CLK期间从机拉低SDA表示对地址进行应答,在返回的数据字节的第2,3,6,7,8几个CLK器件从机拉低SDA输出逻辑0电平。
根据上面讲的I2C协议SCL为高的时候,SDA电平应保持,而等到SCL为低后(也就是下降沿后)才能发生改变。如果在上面几个CLK的前半个周期SCL拉高后主机CLK不再拉低呢?从机会有什么动作?YES,从机会持续拉低着SDA,直到见到下一个他应该输出高电平的下降沿。最常见的情况就是主机在通讯的过程中产生了复位。由于复位动作通常会立刻执行,外设状态机都恢复到默认状态,也就发不出完整的CLK了。那么等到主机复位完成回来后,SCL为高,SDA被从机拉低。主机无法发起START起始条件,不能开始下一次与从机的通讯,这称为SDA挂死(复位状态SDA,SCL为高)。SDA挂死预防与解决办法:最好用模拟I2C实现,则不会死锁
(1) 尽量选用带复位输人的I2C从器件。
(2) 将所有的从I2C设备的电源连接在一起,通过MOS管连接到主电源,而MOS管的导通关断由I2C主设备来实现。
(3) 在I2C从设备设计看门狗的功能。
(4) 在I2C主设备中增加I2C总线恢复程序。每次I2C主设备复位后,如果检测到SDA数据线被拉低,则控制I2C中的SCL时钟线产生9个时钟脉冲(针对8位数据的情况),这样I2C从设备就可以完成被挂起的读操作,从死锁状态中恢复过来。这种方法有很大的局限性,因为大部分主设备的I2C模块由内置的硬件电路来实现,软件并不能够直接控制SCL信号模拟产生需要时钟脉冲。
(5) 在I2C总线上增加一个额外的总线恢复设备。这个设备监视I2C总线。当设备检测到SDA信号被拉低超过指定时间时,就在SCL总线上产生9个时钟脉冲,使I2C从设备完成读操作,从死锁状态上恢复出来。总线恢复设备需要有具有编程功能,一般可以用单片机或CPLD实现这一功能。
(6) 在I2C上串人一个具有死锁恢复的I2C缓冲器,如Linear公司的LTC4307如图2所示:LTC4307是一个双向的I2C总线缓冲器,并且具有I2C总线死锁恢复的功能。LTC4307总线输人侧连接主设备,总线输出侧连接所有从设备。当LTC4307检测到输出侧SDA或SCL信号被拉低30ms时,就自动断开I2C总线输人侧与输出侧的连接.并且在输出侧SCL信号上产生16个时钟脉冲来释放总线。当总线成功恢复后,LTC4307会再次连接输人输出侧,使总线能够正常工作。
3.2.2 CLK挂死
I2C从机主动拉低SCL线在规范中是一个合法的行为,如Clock Stretching(时钟扩展)。
SCL挂死(也就是前面所说一直拉低SCL)这种情况在标准I2C从器件上基本不会出现,因为只要芯片还在正常工作从机总算有准备好的时候,自然就就释放SCL了。往往是使用用户使用MCU作为I2C从机时,程序设计上的问题导致MCU无法完成数据传输,因此重点分析MCU I2C中断服务程序:
1.I2C中断服务程序被意外屏蔽;
2.中断服务程序中陷入了一些标志位查询的while(flag != xxx)死循环;
3.I2C功能系统被意外禁止。
3.3 半高毛刺电平
这是一个较为常见的现象,I2C的ACK后面会有有个半高的小毛刺,一般出现的位置很有规律,一般在第9,18,27 时钟周期后面。如下图所示:
在Transmitter向Receiver传输8bit数据之后,SDA控制权交由Receiver ,此时Receiver控制SDA发送一个ACK反馈信号, SDA为低电平信号,在经过SCLK为高时接收到SDA的低电平信号,在SCLK变为低电平时, SDA控制权交回到Transmitter ,在交回过程中有一小段时间SDA处于既不由Transmitter又不为Receiver控制的空闲阶段,在空闲阶段SDA默认为高电位,如果Transmitter要马上传输低电平, SDA将由高电平转为低电平,会存在一个小的毛刺。
Master设备发出最后一个bit数据后,总线的使用权交给Slave设备使用,由Slave设备发出应答信号ACK,该信号在SCL下降沿经t1延迟后发出,在SCL的下一个时钟沿后经t1后结束。而Master设备在同一个时钟沿,经常t2延迟后发出第9bit数据,这样在dt=(t2-t1)时间内,Master和Slave设备都没有使用总线,由于SDA是OC/OD输出,芯片外面通过电阻R上拉到VCC,将SDA电平拉升,但是由于dt很短,VCC还没来的及将SDA拉到稳定的高电平,Master就开始发出数据0将SDA拉低,因此就在SDA上形成了宽度很窄的半高电平,就是我们观察到的毛刺。此毛刺一般不会对I2C总线的读写时序产生影响。
在实际电路中有时候会在线上串联电阻,会造成低电平不为零的情况;某些情况下当IO口配置错误时也会造成低电平高于0的情况,需要注意与半高电平的区分。
3.4 Pull-up resistor sizing
下图给出了总线电容与上拉电阻的等效电路图,我们很容易就能看出,输出高电平比较慢,因为有电阻和电容的阻挡,需要通过RC进行指数充电,而输出低电平就比较快,因为从电容放电到地全程无遮挡。通常情况下各种芯片的输入电容相加,再加上又长又复杂的走线带来的杂散电容,改变电容值是比较困难的,所以经常通过改变电阻来改善I2C总线上的信号质量。
对于给定的VDD,由前面2.2节可知V_IH=0.7V_DD , 𝑉𝐼𝐿=0.3𝑉𝐷𝐷, 对于RC电路的v-t 充电曲线为则有:
Rp(max)是最大上升时间(tr)和估算总线电容(Cb)的函数:
电源电压限制了电阻Rp的最小值,这是因为标准模式和快速模式的最小灌电流为3 mA,对于快速模式Plus的最小灌电流为20 mA:
3.5 Bus capacitance
总线电容包括导线,连接器和引脚与地之间的总电容,由于SPEC规定的信号上升时间限制,所以总线电容就限制了Rp的取值。 图41给出了Rp(max)与总线电容之间的关系。图42给出了VDD与Rp(min)之间的关系。
规定总线电容极限是为了限制上升时间,确保在设定频率工作下正常的通信。 尽管大多数设计可以轻松地保持总线电容在此限制内,但对于一些应用场景可能会超过该限制,系统设计人员可以采用几种策略来应对较大的总线电容。 •降低的fSCL:总线可能以较低的速度运行(较低的fSCL)。 •更高的驱动电流输出:可以使用具有更高驱动电流的设备(例如,Fast-mode Plus额定值的设备)(PCA96xx)。 •总线缓冲区:用总线缓冲区设备可以将总线划分为多个段,以便每个段的电容都在限制范围内,例如PCA9517总线缓冲区或PCA9546A开关。 •开关上拉电路:开关上拉电路可通过在需要时交替切换低值上拉电阻来加速上升沿。
3.5 Series protection resistors
如图45所示,可以使用例如300Ω的串联电阻(Rs)来防止SDA和SCL线路上的高压尖峰。 如果使用串联电阻,设计人员必须在计算R和总线电容时将额外的电阻添加到他们的计算中。(在输出低电平时有影响,低电平不能到0V)。
低电平所需的0.1VDD噪声裕量限制了Rs的最大值。 Rs(max)与Rp的关系如图46所示。 请注意,串联电阻会影响输出下降时间。
3.6 level translation
3.3V和5V可以互换么?不可以,若互换,则在SDA2输出高电平时,由于体二极管的存在,SDA1---体二极管---SDA2会导通,导致SDA2的电压高于3.3V。
可以参考的MOS型号有:WNM2021-3/TR ,WNM2046C
https://www.jichudianlu.com/archives/439