### **一、I2C在STM32中的作用**1. **高效外设控制**- 仅需两根线SDA数据线 SCL时钟线连接多个低速设备如EEPROM、温湿度传感器、RTC时钟等节省引脚资源。(半双工通信)- 硬件自动处理协议时序起始/停止条件、应答位、时钟同步释放CPU算力对比软件模拟I2C可提升效率30%以上。2. **多主机支持**- 支持**可变多主机模型**任何设备可在总线空闲时成为主机需总线仲裁符合分布式系统设计思想。3. **速率灵活**- 标准模式100kHz、快速模式400kHz满足不同外设需求。I2C使用的设备的应答是由主机个从机发送一个开始信号(A)-然后发送设备的地址(大部分是8位,其中最后一位是读或者写就是下文D的解释)-有没有响应(C)-然后发送一个停止信号(B)-后面就是读取或者写入数据(后面揭晓)ErrorStatus IIC_Verification(uint8_t Address) { ErrorStatus tempERROR; IIC_START(); temp IIC_VALUE(Address,WRITE); if(temp ! SUCCESS) { return temp; } IIC_STOP(); return SUCCESS; } //函数实现在下文A.开始信号过程(在此之前SCL,SAD配置开漏输出,开漏出需要设备有上拉电阻不然容易误判,没有设备也判定成功因为返回SDA一直是低电频,所以要测试时候要给一个错误地址判定是否有一个错误):SCL,SDA开始都要是高电频SDA先拉低,等待稳定后SCL拉低//#define INSTATUA_SCL(value) if(value) GPIO_SetBits(IIC_GPIOx_SCL,IIC_GPIO_Pin_SCL);\ // else GPIO_ResetBits(IIC_GPIOx_SCL,IIC_GPIO_Pin_SCL); //#define INSTATUA_SDA(value) if(value) GPIO_SetBits(IIC_GPIOx_SDA,IIC_GPIO_Pin_SDA);\ // else GPIO_ResetBits(IIC_GPIOx_SDA,IIC_GPIO_Pin_SDA); //发送开始信号(value0?低电频:高电频) void IIC_START(void) { INSTATUA_SDA(1); INSTATUA_SCL(1); stopover_IIC(); //阻塞延迟1us,等待电频变化(等待时间可以更长) INSTATUA_SDA(0); stopover_IIC(); INSTATUA_SCL(0); stopover_IIC(); }B.停止信号过程:开始SCL是高电频,SDA是低电频要把SDA拉高//#define INSTATUA_SCL(value) if(value) GPIO_SetBits(IIC_GPIOx_SCL,IIC_GPIO_Pin_SCL);\ // else GPIO_ResetBits(IIC_GPIOx_SCL,IIC_GPIO_Pin_SCL); //#define INSTATUA_SDA(value) if(value) GPIO_SetBits(IIC_GPIOx_SDA,IIC_GPIO_Pin_SDA);\ // else GPIO_ResetBits(IIC_GPIOx_SDA,IIC_GPIO_Pin_SDA); //发送停止信号(value0?低电频:高电频) void IIC_STOP(void) { INSTATUA_SDA(0); INSTATUA_SCL(1); stopover_IIC(); //阻塞延迟1us INSTATUA_SDA(1); stopover_IIC(); //阻塞延迟1us }开始后注意SCL是高电频时候SAD不可以乱动C.应答信号1.读取SDA电频如果是高电频无应答,可能以上发送信号有问题,或者配置没好,读取SDA电频如果是低电频就是应答就通信成功后面可以发送数据;(是因为结束信号放开之后,SDA会立马拉低电频)//#define INSTATUA_SCL(value) if(value) GPIO_SetBits(IIC_GPIOx_SCL,IIC_GPIO_Pin_SCL);\ // else GPIO_ResetBits(IIC_GPIOx_SCL,IIC_GPIO_Pin_SCL); //#define INSTATUA_SDA(value) if(value) GPIO_SetBits(IIC_GPIOx_SDA,IIC_GPIO_Pin_SDA);\ // else GPIO_ResetBits(IIC_GPIOx_SDA,IIC_GPIO_Pin_SDA); //接受应答信号(value0?低电频:高电频) uint8_t Answer_back(void) { //NOACK是非应答(是1)ACK是应答(是0) uint8_t ret NOACK; INSTATUA_SDA(1); stopover_IIC(); INSTATUA_SCL(1); IIC_STOP(); if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)0)//这个是查看SDA电频 { ret ACK; } else { ret NOACK; } INSTATUA_SCL(0); stopover_IIC(); return ret; }D.数据有效性(有8位和11的,最后一位是设备地址,后一位是读(1):主机在从机上读取数据,写(0):主机在从机上写入数据)1.如果SCL是高电频时候读取SAL数据SAL高电频为 ’1’为低电频时候为’0’,当SCL为低电频时候读取数据是无效的,这个时候SAL发送数据;//#define INSTATUA_SCL(value) if(value) GPIO_SetBits(IIC_GPIOx_SCL,IIC_GPIO_Pin_SCL);\ // else GPIO_ResetBits(IIC_GPIOx_SCL,IIC_GPIO_Pin_SCL); //#define INSTATUA_SDA(value) if(value) GPIO_SetBits(IIC_GPIOx_SDA,IIC_GPIO_Pin_SDA);\ // else GPIO_ResetBits(IIC_GPIOx_SDA,IIC_GPIO_Pin_SDA); //接受应答信号(value0?低电频:高电频) ErrorStatus IIC_DATA(uint8_t Address) { for(uint8_t i0;i8;i) { INSTATUA_SDA((0x80i)Address); stopover_IIC(); INSTATUA_SCL(1); stopover_IIC(); INSTATUA_SCL(0); } if(Answer_back()) { IIC_STOP(); return ERROR; } return SUCCESS; } ErrorStatus IIC_VALUE(uint8_t Address,uint8_t Mode) { return IIC_DATA(((Address1)|Mode));//Mode是读和写选择 }如果有错误请多多指教!