STM32实现硬件I2C通讯,读取MPU6050的ID号

发布于:2024-04-19 ⋅ 阅读:(31) ⋅ 点赞:(0)

今天学习了使用硬件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);
}

这样就形成了最终的结果: