I2C初始化
cpp
#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-要发送的数据
返回值:无
cpp
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);//直到总线空闲为止
}
I2C接收数据
参数:Add-从机地址、Size-需要接收的数据数量、pData-接收的数据
返回值:0-接收失败、1-接收成功
cpp
uint16_t MyI2C_Receive(uint8_t Add,uint16_t Size,uint8_t *pData)
{
//#1.等待总线空闲
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)==SET);
//#2.发送起始位
I2C_GenerateSTART(I2C1,ENABLE);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_SB)==RESET);
//#3.发送从机地址
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
I2C_SendData(I2C1, Add|0x01);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR)==RESET){
if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF)==SET){//如果从机接收数据失败
I2C_GenerateSTOP(I2C1,ENABLE);//发送停止位
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)==SET);//等待总线空闲
return 0;//表示数据接收失败
}
}
//#4.接收数据
if(Size==1){
//清除ADDR标志位
I2C_ReadRegister(I2C1, I2C_Register_SR1);
I2C_ReadRegister(I2C1, I2C_Register_SR2);
//ack=0,stop=1
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1,ENABLE);
//等待RXNE,把数据读出来
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE)==RESET);
pData[0]=I2C_ReceiveData(I2C1);
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)==SET);
return 1;//成功
}
else if(Size==2){
//清除ADDR标志位
I2C_ReadRegister(I2C1, I2C_Register_SR1);
I2C_ReadRegister(I2C1, I2C_Register_SR2);
//等待RXNE=1
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE)==RESET);
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1,ENABLE);
pData[0]=I2C_ReceiveData(I2C1);
//接收第二个字节
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE)==RESET);
pData[1]=I2C_ReceiveData(I2C1);
//等待总线空闲
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)==SET);
return 1;
}
else if(Size>2){
//ack=1
I2C_AcknowledgeConfig(I2C1, ENABLE);
//清除ADDR标志位
I2C_ReadRegister(I2C1, I2C_Register_SR1);
I2C_ReadRegister(I2C1, I2C_Register_SR2);
//
uint32_t i;
for(i=0;i<Size-3;i++){
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE)==RESET);
pData[i]=I2C_ReceiveData(I2C1);
}
//等待BTF标志位为1
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF)==RESET);
pData[Size-3]=I2C_ReceiveData(I2C1);
pData[Size-2]=I2C_ReceiveData(I2C1);
//ACK=0,stop=1
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_AcknowledgeConfig(I2C1, ENABLE);
//等待RXEN=1
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF)==RESET);
pData[Size-1]=I2C_ReceiveData(I2C1);
//等待总线空闲
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)==SET);
return 1;
}
else{
return 0;
}
}