IIC(Inter—Integrated Circuit)总线是一种由PHILIPS公司开发的两线式串行总线,用于连接微
控制器及其外围设备。在CPU与被控IC之间、IC与IC之间进行双向数据传送,高速IIC总线一般可
达400kbps以上。
I2C通讯设备之间的常用连接方式:
STM32的 I2C 外设可用作通讯的主机及从机,支持 7位、10位设备地址,支持 DMA数据传输,并
具有数据校验功能。它的 I2C外设还支持 SMBus2.0协议,SMBus 协议与 I2C类似,主要应用于笔
记本电脑的电池管理中,本手册不展开,感兴趣的读者可参《SMBus20》文档了解。
硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的,因而效
率要远高于软件模拟的I2C;一般也较为稳定,但是程序较为繁琐。硬件(固件)I2C是直接调用内
部寄存器进行配置;而软件I2C是没有寄存器这个概念的。
软件I2C一般是使用GPIO管脚,用软件控制SCL,SDA线输出高低电平,模拟i2c协议的时序。
例如下面这段I2C的开始和结束信号,我们使用GPIOB模拟:
GPIO引脚 | 模拟I2C引脚 |
GPIOB11 | SDA |
GPIOB12 | SCL |
代码如下:
同样,我们可以按照波形完成读/写一个字节的函数,再进一步封装完成更为复杂的功能(发送指令等等)
硬件i2c程序员只要调用i2c的控制函数即可,不用直接的去控制SCL,SDA高低电平的输出。
但是有些单片机的硬件i2c不太稳定,调试问题较多。例如网上很多人吐槽的STM32…
void I2C_START(void)
{
GPIOB11 = High;
GPIOB12 = High;
Delay();
GPIOB11 = Low;
Delay();
GPIOB12 = Low;
}
void I2C_STOP(void)
{
GPIOB11 = Low;
GPIOB12 = High;
Delay();
GPIOB11 = High;
}
主要对比:
1.硬件IIC用法比较复杂,模拟IIC的流程更清楚一些。
2.硬件IIC速度比模拟快,并且可以用DMA
3.模拟IIC可以在任何管脚上,而硬件只能在固定管脚上。
①I2C通讯引脚
I2C 的所有硬件架构都是根据图中右侧 SCL 线和 SDA 线展开的。STM32 芯片有多个 I2C 外设,它们的 I2C 通讯信号引出到不同的 GPIO 引脚上,使用时必须配置到这些指定的引脚。
②数据控制逻辑
I2C 的 SDA信号主要连接到数据移位寄存器上。当向外发送数据的时候,数据移位寄存器以“数据寄存器”为数据源,把数据一位一位地通过 SDA 信号线发送出去;当从外部接收数据的时候,数据移位寄存器把 SDA信号线采样到的数据一位一位地存储到“数据寄存器”中。若使能了数据校验,接收到的数据会经过 PCE计算器运算,运算结果存储在“PEC寄存器”中。当 STM32 的 I2C工作在从机模式的时候,接收到设备地址信号时,数据移位寄存器会把接收到的地址与 STM32的自身的“I2C 地址寄存器”的值作比较,以便响应主机的寻址。STM32 的自身 I2C地址可通过修改“自身地址寄存器”修改,支持同时使用两个 I2C设备地址,两个地址分别存储在 OAR1和 OAR2中。
③时钟控制逻辑
I2C由一个独立的时钟源进行计时,该时钟源允许I2C独立于PCLK频率工作。这个独立的时钟可以选为SYSCLK系统时钟。I2C的IO口支持20毫安输出电流驱动器快速模式操作,这是通过SCL和SDA引脚的驱动来实现的。在启用外设之前,必须在I2C_TIMINGR寄存器中配置SCLH和SCLL的I2C主时钟。
SDA和SCL时钟配置公式如下:
I2C分频后的时钟周期:tPRESC = (PRESC+1) * tI2CCLK
传输模式下,当SDA数据准备好,SCL上升沿到来的延时时间:tSCLDEL = (SCLDEL+1) * tPRESC
传输模式下,SCL下降沿到来之后,SDA数据发生改变的延时时间:tSDADEL = SDADEL x tPRESC
SCL高电平持续时间:tSCLH = (SCLH+1) x tPRESC
SCL低电平持续时间:tSCLL = (SCLL+1) x tPRESC
tI2CCLK为I2C的时钟周期,PRESC、SCLDEL、SDADEL、SCLH、SCLL可以通过I2C_TIMINGR寄存器进行配置。
使用 I2C外设通讯时,在通讯的不同阶段它会对“状态寄存器(ISR)”的不同数据位写入参数,我们通过读取这些寄存器标志来了解通讯状态。
I2C主机发送数据流程图如下(以发送两个字节数据为例):
I2C主机发送数据流程:
控制产生起始信号(S),发送设备地址并等待应答信号(A)。
若设备地址发送成功,则产生事件“EV1”,这时I2C_ISR寄存器的“TXIS”位被置1表示设备地址发送成功。
紧接着往I2C的“数据寄存器TXDR”写入要发送的数据data1,等待应答信号(A)。
当数据发送完成后,产生事件“EV2”,这时I2C_ISR寄存器的“TXIS”位被置1表示数据发送成功。
当数据1发送完成后,以同样的方法发送数据data2,重复这个过程就可以发送多个字节了。
当我们发送数据完成后,在自动停止模式下,I2C设备产生一个停止信号,表示通讯结束。在软件停止模式下,数据发送完成后,产生事件“EV3”,这时I2C_ISR寄存器的“TC”位被置1表示数据传输完成,此时可以选择重新开始发送或者软件结束通讯。
I2C主机接收数据流程图如下(以接收两个字节数据为例):
I2C主机接收数据步骤:
主机产生起始信号(S),发送设备地址并等待应答信号(A)。
从机接收到地址后,开始向主机发送数据。当主机接收到数据data1后,会产生“EV1”事件,I2C_ISR寄存器的“RXNE”位被置1,表示接收数据寄存器非空,此时我们可以读取寄存器中数据,读取后我们控制I2C发送应答信号(A),继续接收数据。
以同样的方法接收数据data2,重复这个过程就可以接收多个字节了。数据接收完成后,控制I2C发送非应答信号(NA),表示停止传输。
当我们接收数据完成后,在自动停止模式下,I2C设备产生一个停止信号,表示通讯结束。在软件停止模式下,数据接收完成后,产生事件“EV3”,这时I2C_ISR寄存器的“TC”位被置1表示数据传输完成,此时可以选择重新开始发送或者软件结束通讯。