I2C代码部分
I2C一. 常用库函数void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);二. 初始化硬件I2C适配MPU6050voidMPU6050_Init(void){/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);//开启I2C2的时钟硬件I2C外设时钟APB1总线RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB的时钟I2C引脚时钟/*GPIO初始化I2C引脚SCLPB11SDAPB10*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_OD;//模式复用开漏输出I2C专用模式GPIO_InitStructure.GPIO_PinGPIO_Pin_10|GPIO_Pin_11;//引脚PB10SDA、PB11SCLGPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStructure);//初始化GPIOB对应引脚/*硬件I2C初始化*/I2C_InitTypeDef I2C_InitStructure;//定义I2C初始化结构体变量I2C_InitStructure.I2C_ModeI2C_Mode_I2C;//模式标准I2C模式I2C_InitStructure.I2C_ClockSpeed50000;//时钟速度50KHzMPU6050适配速率I2C_InitStructure.I2C_DutyCycleI2C_DutyCycle_2;//时钟占空比Tlow/Thigh 2I2C_InitStructure.I2C_AckI2C_Ack_Enable;//应答使能开启I2C通信必备I2C_InitStructure.I2C_AcknowledgedAddressI2C_AcknowledgedAddress_7bit;//应答地址7位地址模式I2C_InitStructure.I2C_OwnAddress10x00;//自身地址主机模式下无效设为0x00即可I2C_Init(I2C2,I2C_InitStructure);//将结构体配置应用到I2C2外设/*I2C使能*/I2C_Cmd(I2C2,ENABLE);//使能I2C2硬件I2C开始工作}初始化关键说明时钟配置硬件I2C2挂载在APB1总线时钟需通过RCC_APB1PeriphClockCmd开启GPIO引脚PB10、PB11挂载在APB2总线需单独开启时钟。GPIO配置I2C引脚必须配置为GPIO_Mode_AF_OD复用开漏输出开漏输出可实现I2C总线的线与逻辑无需额外上拉电阻硬件内部已集成。I2C核心参数时钟速度50KHzMPU6050支持100KHz和50KHz50KHz稳定性更高应答使能必须开启否则无法完成I2C通信的应答交互。注意事项硬件I2C引脚固定I2C2的SCL对应PB11、SDA对应PB10不可随意更改硬件外设与引脚固定映射若需使用其他I2C外设如I2C1需对应修改引脚和时钟配置。事件等待超时MPU6050_WaitEvent函数设置了超时保护10000次计数若超时未检测到指定事件会跳出循环可在超时处添加错误处理代码如指示灯提示。应答配置读取单字节数据时需提前失能应答、申请停止条件读取完成后恢复应答使能避免影响后续多字节读取操作。从机地址MPU6050的默认I2C从机地址为0xD07位地址为0x68左移1位加写方向位0即0x6810xD0若传感器AD0引脚接高电平地址变为0xD2。数据拼接MPU6050的加速度计、陀螺仪数据为16位需读取高8位H和低8位L通过“(DataH 8) | DataL”拼接为完整的16位数据注意数据为有符号数最高位为符号位。时钟速度I2C时钟速度建议设为50KHz或100KHz过高会导致通信不稳定MPU6050最大支持400KHz但实际使用中50KHz稳定性最优。三. 读写示例#defineMPU6050_ADDRESS0xD0//MPU6050的I2C从机地址/** * 函 数MPU6050等待事件 * 参 数同I2C_CheckEvent * 返 回 值无 */voidMPU6050_WaitEvent(I2C_TypeDef*I2Cx,uint32_tI2C_EVENT){uint32_tTimeout;Timeout10000;//给定超时计数时间while(I2C_CheckEvent(I2Cx,I2C_EVENT)!SUCCESS)//循环等待指定事件{Timeout--;//等待时计数值自减if(Timeout0)//自减到0后等待超时{/*超时的错误处理代码可以添加到此处*/break;//跳出等待不等了}}}/** * 函 数MPU6050写寄存器 * 参 数RegAddress 寄存器地址范围参考MPU6050手册的寄存器描述 * 参 数Data 要写入寄存器的数据范围0x00~0xFF * 返 回 值无 */voidMPU6050_WriteReg(uint8_tRegAddress,uint8_tData){I2C_GenerateSTART(I2C2,ENABLE);//硬件I2C生成起始条件MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT);//等待EV5I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Transmitter);//硬件I2C发送从机地址方向为发送MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);//等待EV6I2C_SendData(I2C2,RegAddress);//硬件I2C发送寄存器地址MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING);//等待EV8I2C_SendData(I2C2,Data);//硬件I2C发送数据MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED);//等待EV8_2I2C_GenerateSTOP(I2C2,ENABLE);//硬件I2C生成终止条件}/** * 函 数MPU6050读寄存器 * 参 数RegAddress 寄存器地址范围参考MPU6050手册的寄存器描述 * 返 回 值读取寄存器的数据范围0x00~0xFF */uint8_tMPU6050_ReadReg(uint8_tRegAddress){uint8_tData;I2C_GenerateSTART(I2C2,ENABLE);//硬件I2C生成起始条件MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT);//等待EV5I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Transmitter);//硬件I2C发送从机地址方向为发送MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);//等待EV6I2C_SendData(I2C2,RegAddress);//硬件I2C发送寄存器地址MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED);//等待EV8_2I2C_GenerateSTART(I2C2,ENABLE);//硬件I2C生成重复起始条件MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT);//等待EV5I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Receiver);//硬件I2C发送从机地址方向为接收MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);//等待EV6I2C_AcknowledgeConfig(I2C2,DISABLE);//在接收最后一个字节之前提前将应答失能I2C_GenerateSTOP(I2C2,ENABLE);//在接收最后一个字节之前提前申请停止条件MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED);//等待EV7DataI2C_ReceiveData(I2C2);//接收数据寄存器I2C_AcknowledgeConfig(I2C2,ENABLE);//将应答恢复为使能为了不影响后续可能产生的读取多字节操作returnData;}