本程序主要用于驱动STM32单片机芯片的硬件I2C寄存器,实现通过使用芯片自带的I2C寄存器进行数据的发送与接收.
本例程中采用I2C寄存器查询的方式来实现数据传输,当I2C对应寄存器指定状态时方可执行下一步操作.
/** ****************************************************************************** * @file Hardware_I2C.c * @author Ryan Zhao * @version V1.0.0 * @date 2017-04-27 * @brief STM32硬件I2C底层驱动. ****************************************************************************** * @attention Null * ****************************************************************************** */ /** * @brief I2C引脚与寄存器功能配置. * @param None. * @retval None. */ void I2C_Configuration(void) { /*GPIO与IIC初始化结构体*/ GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; /*GPIO与IIC时钟使能*/ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //GPIOB时钟使能 RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE ); //I2C时钟使能 /*初始化GPIO*/ GPIO_InitStructure.GPIO_Pin = HW_I2C_SDA_PIN | HW_I2C_SCL_PIN; //初始化 IIC GPIO GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //最高输出速度50Hz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //输入输出模式为复用功能开漏输出 GPIO_Init( GPIOB, &GPIO_InitStructure ); //根据GPIO初始化结构体初始化GPIOB /*初始化I2C*/ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //设置为I2C模式 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //设置I2C的占空比,低电平除以高电平值为2 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能ACK信号 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //指定7位地址 I2C_InitStructure.I2C_ClockSpeed = 400000; //时钟频率,必须小于等于400KHz I2C_Cmd( HW_I2C, ENABLE ); //使能I2C I2C_Init( HW_I2C, &I2C_InitStructure ); //根据I2C初始化结构体初始化I2C /*允许一字节一应答模式*/ I2C_AcknowledgeConfig( HW_I2C, ENABLE ); //使能I2C应答状态 } /** * @brief 从I2C指定地址中读取数据; * @param 读取的地址,读取后返回的数据; * @retval 1:读取数据成功,0:读取数据无效; */ unsigned char I2C_ReadByte(unsigned char Read_Address,unsigned char * Read_Data) { unsigned char wait_time_out = wait_time_value;//等待I2C器件响应的延时 * Read_Data = 0; while (I2C_GetFlagStatus(HW_I2C, I2C_FLAG_BUSY)) //判断IIC接口状态.当IIC状态为BUSY时,一直停在这里循环 { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } /*发送START之后要等待,意味着START条件被正确释放,此时IIC总线上没有其它外设*/ I2C_GenerateSTART( HW_I2C, ENABLE ); //产生START条件 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_MODE_SELECT)) //判断开始信号是否已经发送完成 { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } I2C_Send7bitAddress(HW_I2C, ADXL_WRITE, I2C_Direction_Transmitter ); //发送从机地址ADXL_WRITE以选择从机,主机为发送模式 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //如果主机发射模式被选中(死循环等待从机发送ACK信号) { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } I2C_SendData(HW_I2C, Read_Address ); //将write_address,即要读的地址通过IIC2发送出去 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) //如果地址已经从IIC成功发射出去(死循环等待ACK信号 { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } I2C_GenerateSTART(HW_I2C, ENABLE ); //产生START条件 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_MODE_SELECT)) //如果主机被选中(死循环等待ACK信号) { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } /***主机接收数据***/ I2C_Send7bitAddress(HW_I2C, ADXL_READ, I2C_Direction_Receiver ); //主机设置为接收模式 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) //如果主机接收模式被选中(死循环等待ACK信号) { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } I2C_AcknowledgeConfig(HW_I2C, DISABLE ); //失能IIC的应答状态 NACK I2C_GenerateSTOP( HW_I2C, ENABLE ); //产生STOP条件 while (!(I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_RECEIVED))) //判断数据是否接收完成 { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } I2C_AcknowledgeConfig(HW_I2C, ENABLE ); //再一次使能IIC的应答状态 * Read_Data = I2C_ReceiveData(HW_I2C); //返回IIC接收的数据 return 1; } /** * @brief 通过I2C接口将数据写入从机指定地址中. * @param 要写入的数据,接收数据的地址; * @retval 1:数据写入成功 0:数据写入失败 */ unsigned char I2C_Write_Byte(uint8_t Point_Buffer,uint8_t Write_Address) { unsigned char wait_time_out = wait_time_value;//等待I2C器件响应的延时 while (I2C_GetFlagStatus(HW_I2C, I2C_FLAG_BUSY)) //判断当前I2C接口状态是否为Busy { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } I2C_GenerateSTARTHW_I2C, ENABLE ); //产生Start信号 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_MODE_SELECT)) //判断Start信号是否已经发送 { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } I2C_Send7bitAddress(HW_I2C, ADXL_WRITE, I2C_Direction_Transmitter ); //发送从机地址以选择从机,主机为发送模式 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) //判断发送的地址是否与从机匹配,等待从机发送ACK信号 { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } I2C_SendData(HW_I2C, Write_Address ); //将write_address,即要写的寄存器地址通过IIC发送出去 while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) //判断数据是否发送完成 { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } /*往寄存器发送数据data*/ I2C_SendData(HW_I2C, Point_Buffer ); while (!I2C_CheckEvent(HW_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) //判断数据是否发送完成 { if((wait_time_out --) == 0) //延时等待 { return 0; //响应超时,返回无效标志 } } I2C_GenerateSTOP( HW_I2C, ENABLE ); //IIC2产生STOP条件 return 1;//数据写入完成 1 }
/** ****************************************************************************** * @file Hardware_I2C.h * @author Ryan Zhao * @version V1.0.0 * @date 2017-04-27 * @brief STM32硬件I2C底层驱动. ****************************************************************************** * @attention Null * ****************************************************************************** */ /*********************I2C 物理层GPIO定义*******************/ #define HW_I2C I2C1 //第一组I2C接口 #define HW_I2C_SDA_PIN GPIO_Pin_7 #define HW_I2C_SDA_GPIO_PORT GPIOB #define HW_I2C_SCL_PIN GPIO_Pin_6 #define HW_I2C_SCL_GPIO_PORT GPIOB #define wait_time_value 200 //等待I2C器件响应的延时