I2C(Inter-Integrated Circuit)
一种串行数字总线接口,只有两根信号线,总线上可以连接多个设备,硬件实现简单,可拓展性强
SCL串行时钟线 : 在I2C通信中由主设备(如微控制器或处理器)产生,用于同步数据传输,确定数据传输的速率和时序,确保所有设备在SCL上保持同步,从而正确地进行数据传输
SDA串行数据线 : 用于在I2C总线上传输实际的数据位,数据传输是通过在SCL的时钟边沿上或下改变SDA的状态来实现的
I2C总线的两根信号线有上拉电阻。当I2C器件空闲时,其输出接口是高阻态。当所有设备都有空闲时,I2C总线上是高电平
即空闲状态时数据线和时钟线都处于高电平状态
解决了计算机一对多通信问题,挂载在I2C总线的所有外部模块都是从机,从机只有被主机点名之后才能控制I2C总线,不能在未经允许的情况下去碰I2C总线,防止冲突,任何时候都是主机完全控制SCL线
开始传递信息时,必须在时钟线为高电平期间,数据信号完成从高到低的跳变,也就是下降沿,这样起始信号就发送完成了
下图是一个标准的写数据帧:
接下来是7位设备地址码,因为接入多个设备,每个设备地址码不同,为了区别要和哪个设备通讯,主机需要先控制数据线发7位地址码,为0/1的组合,128种结果。时钟线为1时,数据线要稳定为1,这样就完成一位数据的传输
比如上图1010000,是某个外设的地址,则此时单片机和该设备通讯
接下来是读 / 写数据位,写0 读1
下一位应答信号是从机(此时从机控制数据线,前面几位是主机控制,发完读写位,主机把数据线置回默认的高电平,此时SDA=1)发给主机的,从机收到之前的信息则回复0,没收到或读取完成回复1(因为两条线默认状态都是高电平1,从机拉低数据线,主机检测到变回 0 了就知道从机动了手脚,于是主机继续接管总线)
后面可以指定寄存器地址并在其中写入8位数据,停止信号与起始信号相反,SCL=1时,SDA来个上升沿
这样一个标准写数据帧就完成了
读数据和写数据差不多,下面是一个标准的读数据帧:
区别在于,发完寄存器地址后,从机应答后,主机还需要发送一位起始位,然后再发送一次设备地址,并发送 1 表示读数据,接下来便是存储器的对应寄存器地址的数据发给单片机,最后应答信号为 1,表示读取完毕
发送端在高电平发送数据,接收端在高电平取数据
问题来了,如果某一时刻,有两个设备同时要发送数据,那会怎样?数据线上是高电平还是低电平?
为了搞清楚这个问题,我们先要知道芯片是如何输出高低电平的,芯片IO口内部一般会有两颗MOS管,上面导通就输出高电平,下面导通就输出低电平,如下图:
当两个芯片连在数据线上,一高一低,则形成通路,短路了,一定有一个会烧掉
为了避免这样的情况发生,I2C总线对设备IO口进行了阉割,去掉了上面的MOS管(比喻意义,实际就是I2C总线时,我们将推挽输出换成开漏输出)
不过这样带来了问题,芯片无法输出高电平了,解决办法是在SDA上接一个上拉电阻(这个电路电路其实就是GPIO开漏输出)
这样虽然有设备不满足,但起码不会有设备烧掉
( 那再多几个设备呢?C也在低电平呢?B和C又是如何,因为有设备地址所以互不打扰吗?)
题外话:上拉电阻的取值(一般几千欧)
1、太小:会导致芯片电流过大易烧毁,同时MOS管内的电阻有的也可能有100欧,这样会导致无法把总线电压拉低到低电平的状态;
2、太大:每个设备IO口对地总有一些寄生电容,芯片从低往高电平转变的过程中,会有一个充电过程,爬坡一样,电阻越大,越慢,易导致信号失真;所以,一般随着总线设备增加,会适当减少上拉电阻值,求稳的话要用示波器看下波形
因为使用了开漏输出和上拉电阻,I2C抗干扰能力比较弱,适用于同一块电路板上的芯片进行通信,不适合超过30CM的板间通信
///
//
江协科技对于收发的补充:
因为默认是高电平,在准备数据的时候SCL要为低电平,所谓释放就是SCL 回到高电平,一回就开始读写操作
///
学习资料来源:江协科技、爱上半导体、工科男孙老师