IIC通信
• I2C(Inter IC Bus)是由Philips公司开发的一种通用数据总线
• 两根通信线:SCL(串行时钟线)、SDA(串行数据线)
• 同步,半双工
• 带数据应答
• 支持总线挂载多设备(一主多从、多主多从)
一主多从:单片机作为主机,主导I2C总线的运行,挂载在I2C总线的所有外部模块都是从机,从机只有被主机点名之后才能控制I2C总线,不能在未经允许的情况下去碰I2C总线,防止冲突。
多主多从:在总线上的任何一个模块都可以是主机。
硬件电路
• 所有I2C设备的SCL连在一起,SDA连在一起
• 设备的SCL和SDA均要配置成开漏输出模式
• SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右
左边的CPU就是单片机,作为总线的主机。总线的权利很大,包括对SCL线的完全控制,任何时候,都是主机完全掌握SCL线。另外在空闲状态下,主机可以主动发起对SDA的控制,只有在从机发送数据和从机应答的时候,主机才会转交SDA的控制给从机。
从机:挂载在I2C总线上的从机,这些从机可以是姿态传感器、OLED\存储器、时钟模块等。从机的权利比较小,对于SCL时钟线,在任何时候都只能被动的读取,从机不允许控制SCL线。对于SDA数据线,从机不允许主动发起对SDA的控制,只有在主机发送读取从机的命令后,或者从机应答的时候,从机才能短暂地获取到SDA的控制权
所有I2C设备的SCL连在一起,SDA连在一起。
先忽略这两个电阻,假设我们就按照上图连接。那如何规定每个设备SCL和SDA的输入输出模式呢?SCL应该好规定,因为现在是一主多从,主机拥有SCL的绝对控制权,所以主机的模式可以配置成推挽输出,所有从机的SCL都配置成浮空输入或者上拉输入。数据流向是,主机发送,所有从机接收。但是到SDA线这里,就比较麻烦了,因为这是半双工的协议,所以主机的SDA在发送的时候是输出,在接收的时候是输入。同样,从机的SDA也会在输入和输出之间反复切换,如果能协调好输入输出的切换时机,那也没问题。但如果总线时序没有协调好,极有可能发生两个引脚同时处于输出的状态,又正好是一个输出高电平,一个输出低电平,那这个状态就是电源短路。所以为了 避免总线没有协调好导致电源短路这个问题,I2C的设计,禁止所有的设备输出强上拉的高电平,采 用外置弱上拉电阻加开漏输出的电路结构, 所以设备的SCL和SDA均要配置成开漏输出模式。
所有的设备,CPU和被控IC,他引脚的内部结构都是上图所示:
左边的一部分是SCL,右边是SDA的结构。
首先引脚的信号进来,都可以通过一个数据缓冲器或者施密特触发器,进行输入,因为输入对电路没有任何影响,所以任何设备在任何时候都是可以输入的,但是在输出的部分,采用的是开漏输出的配置。
推挽输出:上面一个开关管接到正极,下面一个开关管接到负极。
上面导通,输出高电平
下面导通,输出低电平
开漏输出:去掉强上拉的开关管,输出低电平时,下管导通,是强下拉;输出高电平时,下管断开,但是没有上管了,此时引脚处于浮空的状态,这就是开漏输出。
输出低电平,这个开关管导通,引脚直接接地,是强下拉;输出高电平,引脚管断开,处于浮空状态,这样所有的设备都只能输出低电平而不能输出高电平。但这样的话,为了避免高电平造成的引脚浮空,这时就需要在总线外面SCL和SDA各外置一个上拉电阻。
I2C时序基本单元
• 起始条件:SCL高电平期间,SDA从高电平切换到低电平
• 终止条件:SCL高电平期间,SDA从低电平切换到高电平
起始条件:
在I2C 总线处于空闲状态时:SCL和SDA都处于高电平状态,是由SCL和SDA由外挂的上拉电阻拉高至高电平,总线处于平静的高电平状态。
主机需要进行数据收发时,当从机捕获到SCL高电平,SDA下降沿信号时,就会进行自身的复位,等待主机的召唤。然后在SDA下降沿之后,主机要再把SCL拽下来,拽下SCL:1、占用总线,2、方便拼接。
终止条件
SCL先放手,回到高电平;SDA再放手,回到高电平,产生一个上升沿。上升沿触发终止条件,同时终止条件之后,SCL和SDA都是高电平。
发送一个字节
SCL低电平期间,主机将数据位依次放到SDA线上 (高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位, 所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,
即可发送一个字节.。
主机如果想发送0,就拉底SDA到低电平;如果想发送1,就放手,SDA回到高电平,在SCL低电平期间,允许改变SDA的电平。当这一位的数据放好之后,主机就松手时钟线,SCL回到高电平。在高电平期间,是从机读取SDA的时候,所以高电平期间,SDA不允许变化。SCL处于高电平之后,从机需要尽快地读取SDA,一般在上升沿这个时刻,从机就已经读取完成了。主机在放手SCL一段时间后,就可以继续拉低SCL,然后传输下一位。
接收一个字节
SCL低电平期间,从机将数据位依次放到SDA线上 (高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,
即可接收一个字节(主机在接收之前,需要释放SDA)
SCL低电平期间,从机将数据位依次到SDA线上(高位先行),然后释放SCL,主机在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化。
发送应答和接收应答
• 发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
• 接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)
I2C时序
• 指定地址写
• 对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)
空闲状态:SCL和SDA都是高电平。
主机给从机写入数据的时候:1、SCL高电平期间,拉低SDA,产生起始条件,紧跟着的时序,必须是发送一个字节的时序,字节的内容,必须是从机地址+读写位。从机地址是7位,读写位是1位。加起来刚好一个字节。发送从机地址,就是确定通信的对象。发送读写位,就是确认我接下来是要写入还是要读出。
I2C的硬件实现
I2C外设简介
• STM32 内部集成了硬件 I2C 收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻 CPU 的负担
• 支持多主机模型
• 支持 7 位 /10 位地址模式
• 支持不同的通讯速度,标准速度 ( 高达 100 kHz) ,快速 ( 高达 400 kHz)
• 支持 DMA
• 兼容 SMBus 协议
• STM32F103C8T6 硬件 I2C 资源: I2C1 、 I2C2
(硬件I2C的资源是有限的,这也是硬件和软件的区别)
I2C框图
I2C基本结构
发送:移位寄存器中的数据由高位到低位先移出去,移8次就可以移一个字节,有高位到低位依次放到SDA线上。
接收:数据从GPIO口从右边依次移进来,最终移8次,一个字节就接收完成了。