今天学习了使用硬件I2C的方式成功读取MPU6050的ID号,特此记录一下过程:
首先需要学习的是MPU6050的初始化:
第一步:打开GPIOB的时钟(因为I2C2的引脚10,11在GPIOB上)
第二步:打开I2C2的时钟
第三步:初始化GPIO。
第四步:初始化I2C2。
第五步:开启I2C2。
下面学习的就是指定MPU6050的寄存器地址写数据的函数:
第一步:行成起始条件
第二步:等待EV5事件
第三步:发送7位地址(方向:发送者)
第四步:等待EV6事件(发送完成)
第五步:发送寄存器地址
第六步:等待EV8事件(正在发送)
第七步:发送数据
第八步:等待EV8_2事件(发送完成)
第九步:行成停止条件。
再下面学习的就是指定MPU6050的寄存器地址读数据的函数:
第一步:行成起始条件
第二步:等待EV5事件
第三步:发送7位地址(方向:发送者)
第四步:等待EV6事件(发送完成)
第五步:发送寄存器地址
第六步:等待EV8事件(发送完成)
第七步:再次行成起始条件
第八步:等待EV5事件
第九步:发送7位地址(方向:接收模式)最后一位是接收模式
第十步:等待EV6事件(接收完成标志)
第十一步:应答位给非应答
第十二步:行成终止条件
第十三步: 等待EV7事件(接收完成)
第十四步:提取接收到的数据
第十五步:应答位给应答(回复默认值)
最后就是读取MPU6050的ID号了,MPU6050的ID号存在MPU650的寄存器地址为0x75,读取这个地址中的值就是ID号了。
下面把整个文件展示一下:
- #include "stm32f10x.h" // Device header
- #include "MPU6050.h"
-
- #define MPU6050_ADDRESS 0xD0
- #define GPIO_POART GPIOB
- #define SCL GPIO_Pin_10
- #define SDA GPIO_Pin_11
- #define GPIO_CLOCK RCC_APB2Periph_GPIOB
- #define I2C_CLOCK RCC_APB1Periph_I2C2
-
- void MPU6050_WriteReg(uint8_t Address, uint8_t Data)
- {
- I2C_GenerateSTART(I2C2, ENABLE); // 行成起始条件
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) !=SUCCESS );// 等待EV5事件
-
- I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter); // 发送7位地址(方向:发送者)
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) !=SUCCESS );// 等待EV6事件(发送完成)
-
- I2C_SendData(I2C2, Address); //发送寄存器地址
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) !=SUCCESS );// 等待EV8事件(正在发送)
-
- I2C_SendData(I2C2, Data); //发送数据
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) !=SUCCESS );// 等待EV8_2事件(发送完成)
-
- I2C_GenerateSTOP(I2C2, ENABLE); //行成停止条件
- }
-
-
- uint8_t MPU6050_ReadReg(uint8_t Address)
- {
- uint8_t Data;
-
- I2C_GenerateSTART(I2C2, ENABLE); // 行成起始条件
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) !=SUCCESS );// 等待EV5事件
-
- I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter); // 发送7位地址(方向:发送者)
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) !=SUCCESS );// 等待EV6事件(发送完成)
-
- I2C_SendData(I2C2, Address); //发送寄存器地址
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) !=SUCCESS );// 等待EV8事件(发送完成)
-
- I2C_GenerateSTART(I2C2, ENABLE); // 行成起始条件
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) !=SUCCESS );// 等待EV5事件
-
- I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver); // 发送7位地址(方向:接收模式)
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) !=SUCCESS );// 等待EV6事件(接收完成标志)
-
- I2C_AcknowledgeConfig(I2C2, DISABLE); // 应答位给非应答
- I2C_GenerateSTOP(I2C2, ENABLE); // 行成终止条件
-
- while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED) !=SUCCESS );// 等待EV7事件(接收完成)
- Data = I2C_ReceiveData(I2C2); //提取接收到的数据
-
- I2C_AcknowledgeConfig(I2C2, ENABLE); // 应答位给应答
-
- return Data; //返回接收到的数据
- }
-
-
-
- void MPU6050_Init(void)
- {
- RCC_APB2PeriphClockCmd(GPIO_CLOCK, ENABLE); //第一步:打开GPIOB的时钟(因为I2C2的引脚10,11在GPIOB上)
- RCC_APB1PeriphClockCmd(I2C_CLOCK, ENABLE); //第二步:打开I2C2的时钟
-
- GPIO_InitTypeDef GPIO_InitStruct;
- GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;
- GPIO_InitStruct.GPIO_Pin = SCL | SDA;
- GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIO_POART, &GPIO_InitStruct); // 第三步:初始化GPIO。
-
- I2C_InitTypeDef I2C_InitStruct;
- I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
- I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
- I2C_InitStruct.I2C_ClockSpeed = 100000;
- I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_16_9;
- I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
- I2C_InitStruct.I2C_OwnAddress1 = 0x00;
- I2C_Init(I2C2, &I2C_InitStruct); // 第四步:初始化I2C2。
-
- I2C_Cmd(I2C2, ENABLE); //第五步:开启I2C2。
- }
-
- uint8_t MPU6050_GetID(void)
- {
- return MPU6050_ReadReg(0x75);
- }
这样就形成了最终的结果: