由于STM32的硬件IIC有点问题,且模拟IIC能够更好的帮助我们理解IIC的通信协议,所以下面给出了以STM32F103RCT6为硬件的模拟IIC基本代码(基于HAL库)。
目录
一、IIC通信的基本介绍
IIC(Inter-Integrated Circuit)其实是IICBus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上(接线图如下)。所以IIC工作模式是一种半双工通信。
通信过程如下图(其中起始、终止、数据、应答等会在下面结合代码与时序图一起分析):
主机发送和接收数据流程如下图:
二、模拟IIC的基本代码及其分析
1、基本us延时程序
由于STM32HAL库最小只提供了ms级的延时,所以需要自己创建一个us级延时的子程序以满足IIC时序要求。
void RCCdelay_us(uint32_t udelay)
{
__IO uint32_t Delay = udelay * 72 / 8; //72M主频
do
{
__NOP(); //空语句
}
while (Delay --);
}
2、切换SDA口的输入和输出状态
由于IIC是半双工通信,SDA数据线对于主机来说有时候需要输出数据,有时候需要接受数据,故此处创建一个子函数方便调用切换SDA口状态。
void I2C_SDA_Mode(uint8_t addr) //输入参数:1表示配置SDA为输出模式,0表示配置SDA为输入模式
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(addr) //1 表示 out
{
GPIO_InitStruct.Pin = IIC_SDA_Pin; //IIC的SDA引脚
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; //开漏输出模式
GPIO_InitStruct.Pull = GPIO_PULLUP; //上拉
GPIO_InitStruct.Speed = GPIO_SPE