1.I2C通信
(1)I2C是由Phllips公司开发的一种用于数据总线。
(2)两根通信线:SCL(serial clock) ,SDA(serial data)
(3)同步半双工
(4)带数据应答
(5)支持总线挂载多设备(一主多从,多主多从)
1.1 I2C硬件电路
(1)所有I2C设备的SCL连接在一起,SDA连在一起。
(2)设备的SDA和SCL都要配置成开漏输出模式。
(3)SCL和SDA各添加一个上拉电阻,阻值一般为4.7k欧姆左右。
主机与从机的理解:
(1)主机STM32的CPU权力很大,包括1.对SCL线的完全控制,任意时刻,都是由主机掌控SCL线。2.在空闲状态下,主机可以发动对SDA的控制(只有在从机发送数据和从机应答时,主机才会转变SDA的控制权给从机。)
(2)从机的权力比较小,从机可以是姿态传感器OLED,存储器,时钟模式等。1.对SCL时钟,在任何时刻都只能被动的读取,从机不允许控制SCL线。2.对于SDA数据线,从机不允许主动发起对SDA控制,只有在主机发送读取从机命令后或从机应答时,从机才可以短暂获取SDA控制权。
对于SDA,SCL的输入输出配置
对SCL,一直都是主机输出,从机输入。
对SDA ,主机和从机都纪要输出也要输入。
为了防止SDA的主机和从机出现一个输出高电平,一个输出低电平导致短路,我们的I2C采用:
弱上拉电阻+开漏输出的电路结构。
(1)当K断开时,SDA被上拉电阻拉成高电平。
(2)当K连接时,被下拉拉成低电平。
(3)低电平是一个无穷大的力,高电平是一个弱上拉。
1.2 使用弱上拉电阻和开漏输出的电路结构优点
(1)完全杜绝了电路短路现象,保证了电路的安全。
(2)避免了引脚模式的频繁切换。开漏加弱上拉模式同时兼具了输入和输出的功能。若想输出,就去拉杆子或放杆子,操作杆子变化即可。
(3)有“线与”现象,只要有任意一个或多设备输出了低电平,总线就处于低电平,只有所有设备都输出高电平总线才处于高电平。
2.I2C时序基本单元
2.1.起始条件
起始条件:SCL高电平期间,SDA从高电平切换到低电平。
2.2.终止条件
终止条件:SCL高电平时期,SDA从低电平切换到高电平。
注:起始和终止条件都是由主机产生的,从机不允许产生,所以在空闲状态时,从机必须始终双手放开,不允许主动跳出来去碰总线。(若允许,那是多主机模式)
2.3.发送一个字节
发送一个字节时,SCL和SDA全程由主机控制。
发送一个字节:SCL低电平期间,主机将数据一次放在SDA线上(高位先行),然后释放SCL(主机释放时钟线,SCL回弹到高电平)从机将SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节。
过程:最开始,SCL低电平,主机若想发送0,就拉低SDA 到低电平,如果想发送1,就放手,SDA回弹到高电平,在SCL低电平期间,允许改变SDA电平,当主机放好后,主机就会松手时钟线,SCL回弹到高电平,在高电平期间,从机读取SDA1,所以高电平期间,SDA不允许改变(因为时钟线是主机控制的,从机不知道主机什么时候产生下降沿,所以从机一般在释放上升沿的过程中就读取好了),一段时间后,主机拉低SCL,传输下一位。
2.4.接收一个字节
接收一个字节:主机控制SCL,从机控制SDA。且主机接收前,需要线释放SDA。
接收一个字节:SCL低电平期间,从机将数据依次放在SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节。(主机在接收前,需要先释放SDA)
过程:释放SDA相当于切换成输入模式。(所以设备包括主机,都始终处于输入模式,当主机需要发送时,就可主动去拉低SDA,而主机在被动接收时,就必须先释放SDA,不要去动它,防止影响别人发送,因为总线是“线与”的特征,任何一个设备拉低了,总线就是低电平,如果接收时,主机拽着SDA不放手,那么从机无论发送什么,都是低电平)
2.5.发送应答
发送应答:主机在接收完一个字节后,在下一个时钟发送一个数据,数据0表应答,数据1表非应答
2.6.接收应答
接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表应答,数据1表非应答(主机接收前,需释放SDA)
理解:主机调用发送一个字节后,就要紧跟着调用接收应答的时序,用来判断从机有没有收到刚才给它的数据,如果从机收到了,在应答位这里,主机释放SDA时,从机就应立刻把SDA拉下来,然后在SCL高电平期间,主机读取应答。
3.I2C时序
3.1 I2C时序——按指定地址写
按指定地址写:对于“指定设备(slave address)”在“指定地址(reg address)”下写“指定数据(data)”
顺序:开始——发送从机地址(7位)+0(1位,0表示写)——接收应答——发送指定地址(指定寄存器)——接收应答——发送数据——接收应答——“重复发送数据接收应答”——结束
3.2 I2C时序——按当前地址读
按当前地址读:对于"指定设备(slave address)"在当前地址指针指示下,读取“从机数据(data)”
顺序:开始——发送从机地址(7位)+1(一位,1表示读)——接收应答——接收从机数据——发送应答——”重复接收从机数据发送应答“——接收从机数据——发送不应答——结束
3.3 补充:“当前地址指针”
在从机中,所以寄存器被分配到一个线性区域中,并且,有个单独的指针变量,指示着其中一个寄存器,这个指针上电默认,一般指向0地址,并且,每写入一个字节和读出一个字节之后,这个指针就会主动自增一次,移动到下一个位置,那么在调用当前地址读时序时,没有指定的寄存器读,主机会读上一次指针指的地方的下一位。
3.4 I2C时序——按指定地址读
指定地址读:对于”指定设备(slave address)“在”指定地址(reg addresss)“下,读取”从机数据(data)“
顺序:开始——发送指定从机地址(7位)+0(一位,0表示写)——接收应答——发送指定地址(即指定寄存器)——接收应答——重新开始——发送指定从机地址(7位)+1(一位,1表示读)——接收应答——接收从机数据——发送应答——”重复接收从机数据发送应答“——接收从机数据——发送非应答——结束