【记录】自己动手使用HAL库对MPU6050进行编程

有关于I2C的知识看这篇文章:

【记录】嵌入式经典通信I2C理解

有关于MPU6050的基础知识和手册去看这篇文章:

【记录】MPU6050原理快速入门(附手册)

此篇记录代码编写过程:

直接看汇总: 代码汇总

一、完成CubeMX的配置。

首先分析自身需求:MPU6050需要用到I2C或者是模拟I2C,因为stm32自身具备I2C,故选择使用物理I2C。此外,通过串口来将数据传给电脑,实现在电脑上查看吗,因此需要配置串口,并完成串口的重定向。

使用的控制板是正点原子的探索者,主控芯片是STM32F407ZGT6。

CubeMX的配置请参考其它文章,这里只给出I2C的配置图和最终的引脚配置图。

I2C的配置如图:

最终的引脚配置如图:

 二、完成实物接线。

只需要四个引脚,其名称和对应接线为:VCC接3~5V,GND接GND,SDA接PB6,SCL接PB7(这里PB6和PB7根据自己的板子配置)。 

三、阅读MPU6050的数据手册,查阅相关寄存器地址。

首先,要知道MPU6050的地址,可以通过数据手册也可以通过代码来查阅。接下来用代码进行查看。

#include <stdio.h>// 包含标准输入输出头文件
int fputc(int ch,FILE *f)
{
//采用轮询方式发送1字节数据,超时时间设置为无限等待
	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);
	return ch;
}
int fgetc(FILE *f)
{
	uint8_t ch;
// 采用轮询方式接收 1字节数据,超时时间设置为无限等待
	HAL_UART_Receive( &huart1,(uint8_t*)&ch,1, HAL_MAX_DELAY );
	return ch;
}

int main()
{
    for(uint8_t i=0;i<255;i++)
    {
        if(HAL_I2C_IsDeviceReady(&hi2c,i,1,1000)==HAL_OK)
        {
            printf("%d\n",i);
            break;
        }
    }
}

通过代码或查阅手册知道MPU6050的设备地址为0xD0。进行宏定义方便使用。

#define mpu_addr 0xD0

 为了方便对MPU6050进行读写操作,编写函数。因为MPU6050的使用需要访问寄存器,因此选择能进行读写设备地址和寄存器的地址的语句。

//HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,  uint8_t *pData, uint16_t Size, uint32_t Timeout);//只有设备地址
//HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);//有设备地址和寄存器地址

通过上面封装函数的对比,可以完成读写函数的编写。 

void mpu_w(uint8_t addr,uint8_t data)//写
{
    HAL_I2C_Mem_Write(&hi2c1, mpu_addr, addr, 1, &data, 1, HAL_MAX_DELAY);
}
uint8_t mpu_r(uint8_t addr)//读
{
    uint8_t data;
    HAL_I2C_Mem_Read(&hi2c1, mpu_addr,addr, 1, &data, 1, HAL_MAX_DELAY);
    return data;
}

 其次,完成MPU6050的初始化函数。

void mpu_begin(void)//初始化
{
	if(mpu_r(0x75)==0x68)//检测
	{
		mpu_w(0x1B,0x18);//改角速度速率
		mpu_w(0x1C,0x10);//改加速度
		mpu_w(0x6B,0x01);//关睡眠,改时钟到G
	}
}

最后,完成各个函数的编写,重力感应,温度,角速度。

 

//X,Y,Z读数据时需要组合
int16_t mpu_acc_x(void) //x重力感应
{
	int16_t x=0;
	x=mpu_r(0x3B)<<8;
	x=x|mpu_r(0x3C);
	return x;
}
int16_t mpu_acc_y(void) //y重力感应
{
	int16_t y=0;
	y=mpu_r(0x3D)<<8;
	y=y|mpu_r(0x3E);
	return y;
}
int16_t mpu_acc_z(void) //z重力感应
{
	int16_t z=0;
	z=mpu_r(0x3F)<<8;
	z=z|mpu_r(0x40);
	return z;
}
int16_t mpu_temp(void) //温度
{
	int16_t t=0;
	t=mpu_r(0x41)<<8;
	t=t|mpu_r(0x42);
	return t;
}
int16_t mpu_gy_x(void) //x角速度
{
	int16_t x=0;
	x=mpu_r(0x43)<<8;
	x=x|mpu_r(0x44);
	return x;
}
int16_t mpu_gy_y(void) //y角速度
{
	int16_t y=0;
	y=mpu_r(0x45)<<8;
	y=y|mpu_r(0x46);
	return y;
}
int16_t mpu_gy_z(void) //z角速度
{
	int16_t z=0;
	z=mpu_r(0x47)<<8;
	z=z|mpu_r(0x48);
	return z;
}

 代码汇总:

/* USER CODE BEGIN 0 */
#define mpu_addr 0xD0
//完成串口重定向
#include <stdio.h>// 包含标准输入输出头文件
int fputc(int ch,FILE *f)
{
//采用轮询方式发送1字节数据,超时时间设置为无限等待
	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);
	return ch;
}
int fgetc(FILE *f)
{
	uint8_t ch;
// 采用轮询方式接收 1字节数据,超时时间设置为无限等待
	HAL_UART_Receive( &huart1,(uint8_t*)&ch,1, HAL_MAX_DELAY );
	return ch;
}
//完成MPU6050相关函数编写
void mpu_w(uint8_t addr,uint8_t data)//写
{
	HAL_I2C_Mem_Write(&hi2c1, mpu_addr, addr, 1, &data, 1, HAL_MAX_DELAY);
}
uint8_t mpu_r(uint8_t addr)//读
{
	uint8_t data;
	HAL_I2C_Mem_Read(&hi2c1, mpu_addr,addr, 1, &data, 1, HAL_MAX_DELAY);
	return data;
}
void mpu_begin(void)//初始化
{
	if(mpu_r(0x75)==0x68)//检测
	{
		mpu_w(0x1B,0x18);//改角速度速率
		mpu_w(0x1C,0x10);//改加速度
		mpu_w(0x6B,0x01);//关睡眠,改时钟到G
	}
}
//X,Y,Z读数据时需要组合
int16_t mpu_acc_x(void) //x重力感应
{
	int16_t x=0;
	x=mpu_r(0x3B)<<8;
	x=x|mpu_r(0x3C);
	return x;
}
int16_t mpu_acc_y(void) //y重力感应
{
	int16_t y=0;
	y=mpu_r(0x3D)<<8;
	y=y|mpu_r(0x3E);
	return y;
}
int16_t mpu_acc_z(void) //z重力感应
{
	int16_t z=0;
	z=mpu_r(0x3F)<<8;
	z=z|mpu_r(0x40);
	return z;
}
int16_t mpu_temp(void) //温度
{
	int16_t t=0;
	t=mpu_r(0x41)<<8;
	t=t|mpu_r(0x42);
	return t;
}
int16_t mpu_gy_x(void) //x角速度
{
	int16_t x=0;
	x=mpu_r(0x43)<<8;
	x=x|mpu_r(0x44);
	return x;
}
int16_t mpu_gy_y(void) //y角速度
{
	int16_t y=0;
	y=mpu_r(0x45)<<8;
	y=y|mpu_r(0x46);
	return y;
}
int16_t mpu_gy_z(void) //z角速度
{
	int16_t z=0;
	z=mpu_r(0x47)<<8;
	z=z|mpu_r(0x48);
	return z;
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
	
  /* USER CODE BEGIN 2 */
	mpu_begin();
  //读取数据通过串口传给电脑
	int acc_x,acc_y,acc_z,temp,gy_x,gy_y,gy_z;
	/* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		acc_x=mpu_acc_x();
		acc_y=mpu_acc_y();
		acc_z=mpu_acc_z();
		temp=mpu_temp();
		gy_x=mpu_gy_x();
		gy_y=mpu_gy_y();
		gy_z=mpu_gy_z();
		printf("%d,%d,%d,%d,%d,%d\n",acc_x,acc_y,acc_z,temp,gy_x,gy_y,gy_z);
		HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

猜你喜欢

转载自blog.csdn.net/weixin_45015121/article/details/130996761
今日推荐