1、I2C 总线介绍
I2C bus是Inter-IC bus的缩写,意思是IC器件之间的通讯总线;I2C 总线的特点如下:
- 只需要两个线路,serial data line(SDA)和serial clock line(SCL)
- I2C总线可以支持一主多从或者多主多从的架构;
- I2C总线上的从器件是通过地址来唯一确定的;
- I2C总线是串行,8-bit,双向传输的,支持standard-mode(100Kbits/s)、fast-mode(400kbit/s)、fast-mode plus(1Mbit/s)、high-speed mode(3.4Mbit/s)
- I2C总线上可以挂载的器件数量只受最大总线电容影响;
2、I2C总线的电气设计
上图展示了I2C的电气连接架构
- 所有I2C器件通过SDA和SCL连接到总线上
- I2C总线不同电平总线要分别接电阻上拉至当前电平值
- 不同总线电平的I2C器件通过双向电平转换器(Switches)作为电平转换
2.1 电平转换的基本逻辑和原理
如上图所示,主要有3种状态:
- 双边器件均不下拉总线(输入输出为高)。3V3部分线路上拉,这样的话MOS的G和S极都是3V3,Vgs小于导通电压,MOS不导通;如此一来,双边器件均保持其对应电平值的高电平。
- 3V3器件下拉总线到低电平。MOSFET的S极变低,而MOS的G极电平是3V3,Vgs大于阈值MOS导通;5V器件总线电平通过MOS被拉至低电平,最终实现低电平的输出输入。
- 5V器件下拉总线至低电平。MOS的D极电压降低直至比S极电压低的时候,MOS内置的漏极-基底二极管导通,MOS管的S极也就是3V3总线电平开始下降,当S极电平下降到Vgs大于阈值电平时,MOS管导通,S极电平和D极电平一致被拉到低电平;从而实现了高电平器件输出到低电平器件输入。
2.2 上拉电阻
- I2C端口为开漏输出(区别于常见IO的推挽输出),即其IO口输出是通过控制MOS管打开与关断来将漏极上的电平进行输出,所以没有高电平输出能力,必须将总线上拉至总线电平来实现高电平输出。
- 开漏输出低电平的实现如下图所示:
2.2.1 上拉电阻的阻值如何选择
- 众所周知,电阻是能耗器件,所以肯定是尽可能使得电阻上的功率损耗越小越好,即电阻在此条件下是个最小值
Rp(min)=(Vcc-Vol(max))/Iol
Vcc:上拉电平 ,Volmax):总线输出为低电平的最大电压值 ,Iol:总线的驱动电流(Vol状态下) - 上拉电阻Rp还会受信号上升时间约束,一般datasheet上有明确的最大上升时间要求,若超过这个值,有可能信号还没上升至高电平就开始下降,导致信号采样出错;
Rp(max)=tr/(0.8473 Cb)
tr:上升时间,Cb:总线电容(线路、连接和管脚的总电容)
推导公式如下:
参考一阶电路的电压随时间的变化公式 V(t)=Vcc (1-e^(-t/RC))
上升下降时间一般波形的30% - 70%,这是因为输入低电平最大值门限一般0.3Vcc,输入高电平门限一般0.7Vcc(不是绝对,参考芯片Datasheet)
当Vih=0.7*Vcc时,Vih=0.7*Vcc=Vcc*(1-e^(-t1/Rp*Cb))
当Vih=0.3*Vcc时,Vih=0.3*Vcc=Vcc*(1-e^(-t2/Rp*Cb))
上升时间即为:tr=t2-t1=0.8473Rp8Cb - 最终根据计算出来的Rp范围内选择一个合适阻值
注意:
实际电路设计中,总线上会挂载不止一个器件,这就要综合多个器件的参数进行计算,进而选择一个适合所有器件的值 - 除了上拉电阻Rp,有时在器件连接到总线上时会串入一个电阻Rs,这个电阻主要作用是消除高压毛刺;Rs跟Rp的关系如下图所示,Rs的值可以参考,若实测总线上没有高压毛刺,那Rs可以去掉;
3、I2C的数据帧结构
起始位:开始状态位,1bit,SCL为高时SDA由高至低的过程称作起始位;还有一种重复起始条件,指的是主机对于同一个从器件进行同一操作的时候,不需要先发送停止条件结束总线,再开始;
地址位:7bit,是当前总线需要访问的器件地址;特殊的情况是10bit,一般不用。7bit地址里一般前四位是由器件类型定死,我们自己可以配置的是低三位,也就意味着,同类型的器件在同一根总线上最多可以挂载8个;
读写操作位:1bit,0代表写,1代表读;
应答位:1bit,低电平,每8bit之后跟一位应答位,表示接收端接收成功;还有一种非应答位(NCK)高电平,表示终止传输。
数据位:8bit,一个字节后面必须跟着一个应答位;一般数据的第一个字节传输的是要操作的寄存器地址,后面字节是要写入或者读出的数据。
停止位:当SCL为高电平时,SDA总线由低电平向高电平切换表示停止条件
- 起始和停止条件一般由主机产生。总线在起始条件之后被认为是忙碌的状态;在停止条件的某段时间之后,总线被认为再次处于空闲状态。重复起始条件跟起始条件一样,后续总线会处于忙碌状态;
- SDA线上数据必须在SCL高电平周期保持稳定,也就是说SDA数据高低状态变化只能发生在SCL低电平的时候;
4、I2C的时钟同步与仲裁
- 同步:所有主机在SCL上产生他们自己的时钟来传输I2C总线上的报文。数据只有在SCL高电平周期有效,因此需要一个确定的时钟进行逐位仲裁。
- 如下图所示,多个主机在同一个总线上产生自己的时钟信号;SCL线被有最长低电平周期的器件保持低电平,此时低电平周期短的器件会进入高电平的等待状态;所以,低电平周期由低电平时钟周期最长的器件决定,高电平周期由高电平周期最短的器件决定。
主机只能在总线空闲的时候启动传输。两个或多个主机在起始条件的最小持续时间内产生一个起始条件;
当SCL为高电平时,仲裁在SDA线上发生;在其他主机发送低电平时,发送高电平的主机将断开他的输出,因为总线上电平与自己电平不一致。
5、I2C与CBUS的兼容
C-BUS接收器可以连接到标准的I2C总线。但是必须连接第三条叫DLEN的线,而且要省略响应位。通常I2C的传输是8位的字节传输,兼容C-BUS的器件有不同的格式。在混合总线中,想要访问操作C-BUS器件,需要发送特定的C-BUS地址(0x0000001x);发送C-BUS地址后,DLEN线被激活,发送C-BUS格式的报文,如下图所示: