[Record] Program the MPU6050 by yourself using the HAL library

If you have knowledge about I2C, read this article:

[Record] Embedded classic communication I2C understanding

For basic knowledge and manuals about MPU6050, go to this article:

[Record] Quick Start of MPU6050 Principle (with manual)

This article records the code writing process:

Look directly at the summary:  code summary

1. Complete the configuration of CubeMX.

First analyze your own needs: MPU6050 needs to use I2C or simulate I2C, because stm32 itself has I2C, so choose to use physical I2C. In addition, the data is transmitted to the computer through the serial port to realize viewing on the computer, so the serial port needs to be configured and the redirection of the serial port should be completed.

The control board used is the explorer of punctual atom, and the main control chip is STM32F407ZGT6.

For the configuration of CubeMX, please refer to other articles. Only the I2C configuration diagram and the final pin configuration diagram are given here.

The configuration of I2C is shown in the figure:

The final pin configuration is shown in the figure:

 2. Complete the physical wiring.

Only four pins are needed, and their names and corresponding wiring are: VCC is connected to 3~5V, GND is connected to GND, SDA is connected to PB6, SCL is connected to PB7 (here PB6 and PB7 are configured according to your own board). 

3. Read the data sheet of MPU6050 and check the relevant register address.

First of all, to know the address of MPU6050, you can check it through the data sheet or through the code. Check out the code next.

#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;
        }
    }
}

Know that the device address of MPU6050 is 0xD0 through the code or refer to the manual. It is convenient to use macro definition.

#define mpu_addr 0xD0

 In order to facilitate the read and write operations on the MPU6050, write functions. Because the use of MPU6050 needs to visit the register, so select the statement that can read and write the device address and the address of the register.

//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);//有设备地址和寄存器地址

Through the comparison of the above encapsulation functions, the writing of the read and write functions can be completed. 

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;
}

 Secondly, complete the initialization function of MPU6050.

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

Finally, complete the writing of each function, gravity sensing, temperature, and angular velocity.

 

//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;
}

 Code summary:

/* 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 */
}

Guess you like

Origin blog.csdn.net/weixin_45015121/article/details/130996761