硬件I2C
所谓硬件I2C,就是使用STM32芯片内部的I2C片上外设(模块)来进行I2C通信。此时需要将引脚设置成复用开漏输出模式。
对于硬件I2C可分为3种:基本状态监控、高级状态监控和标志位监控。本章主要研究基本状态监控和标志位监控。
标志位监控
I2C初始化
#include "stm32f10x.h" // Device header
void MyI2C_Init()
{
//初始化SCL、SDA引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStruct);
//开启I2C时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); //使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); //复位,首次使用时进行复位,硬件bug
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, DISABLE);
//配置I2C参数
I2C_InitTypeDef I2C_InitStruct;
I2C_InitStruct.I2C_ClockSpeed=400000
I2C_InitStruct.I2C_Mode=I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle=I2C_DutyCycle_2;
I2C_Init(I2C1, &I2C_InitStruct);
//使能I2C (闭合总开关)
I2C_Cmd(I2C1, ENABLE);
}
I2C发送数据
参数:Add-地址、Size-要发送的数据个数、pData-要发送的数据
返回值:无
void MyI2C_SendData(uint8_t Add,uint16_t Size,uint8_t *pData)
{
//等待总线空闲
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)==SET);
//发送起始位
I2C_GenerateSTART(I2C1, ENABLE);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_SB)==RESET);//查询SB标志位
//发送地址
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
I2C_SendData(I2C1,Add);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR)==RESET)
{
if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF)==SET)
{
goto STOP;
}
}
//发送数据
I2C_ReadRegister(I2C1, I2C_Register_SR1);
I2C_ReadRegister(I2C1, I2C_Register_SR2);//清除ADDR
uint32_t i;
for(i=0;i<Size;i++) //连续发送数据(1个或多个)
{
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE)==RESET)
{
if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF)==SET){
goto STOP;
}
}
I2C_SendData(I2C1,pData[i]);
}
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF)==RESET){
if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF)==SET){
goto STOP;
}
}
//发送停止位
STOP:
I2C_GenerateSTOP(I2C1, ENABLE);//发送停止位
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)==SET);//直到总线空闲为止
}
</