STM32 HAL 庫硬體 I2C 驅動 MPU6050

笨蛋队长要变强發表於2024-11-20

MPU6050簡介

驅動檔案

mpu6050.h

#ifndef INC_MPU6050_H_
#define INC_MPU6050_H_

#include "i2c.h"

// I2C通道配置
#define hI2C &hi2c2

// 裝置地址配置
#define MPU6050_ADDRESS_Write	0xD0 // 0x68左移一位補0
#define MPU6050_ADDRESS_Read    0xD1 // 0x68左移一位補1

// 基本暫存器地址
#define	MPU6050_PWR_MGMT_1		0x6B
#define	MPU6050_PWR_MGMT_2		0x6C
#define	MPU6050_WHO_AM_I		0x75

// 初始化配置暫存器地址
#define	MPU6050_SMPLRT_DIV		0x19
#define	MPU6050_CONFIG			0x1A
#define	MPU6050_GYRO_CONFIG		0x1B
#define	MPU6050_ACCEL_CONFIG	0x1C

// 原始資料暫存器地址
#define	MPU6050_ACCEL_XOUT_H	0x3B
#define	MPU6050_ACCEL_XOUT_L	0x3C
#define	MPU6050_ACCEL_YOUT_H	0x3D
#define	MPU6050_ACCEL_YOUT_L	0x3E
#define	MPU6050_ACCEL_ZOUT_H	0x3F
#define	MPU6050_ACCEL_ZOUT_L	0x40
#define	MPU6050_TEMP_OUT_H		0x41
#define	MPU6050_TEMP_OUT_L		0x42
#define	MPU6050_GYRO_XOUT_H		0x43
#define	MPU6050_GYRO_XOUT_L		0x44
#define	MPU6050_GYRO_YOUT_H		0x45
#define	MPU6050_GYRO_YOUT_L		0x46
#define	MPU6050_GYRO_ZOUT_H		0x47
#define	MPU6050_GYRO_ZOUT_L		0x48

// 共享原始資料變數
extern int16_t tempData;
extern int16_t accelDataX;
extern int16_t accelDataY;
extern int16_t accelDataZ;
extern int16_t gyroDataX;
extern int16_t gyroDataY;
extern int16_t gyroDataZ;

// 共享解析資料變數
extern float Temp;
extern float AccelX;
extern float AccelY;
extern float AccelZ;
extern float GyroX;
extern float GyroY;
extern float GyroZ;

void MPU6050_Init(void); // 初始化MPU6050
uint8_t MPU6050_GetID(void); // 獲取裝置ID

void MPU6050_Send_CMD(uint8_t cmd); // 傳送指令
void MPU6050_Set_Register(uint8_t Register_ADDRESS, uint8_t Set_Value); // 配置暫存器
uint8_t MPU6050_Read_Register(uint8_t Register_ADDRESS); // 讀取暫存器資料
uint16_t MPU6050_read_data(uint8_t addressH, uint8_t addressL); // 讀取原始資料

void MPU6050_get_tempData(int16_t *tempData); // 獲取溫度原始資料
void MPU6050_get_accelData(int16_t *accXData, int16_t *accYData, int16_t *accZData); // 獲取加速度原始資料
void MPU6050_get_gyroData(int16_t *gyroXData, int16_t *gyroYData, int16_t *gyroZData); // 獲取角速度原始資料

void MPU6050_get_temp(float *Temp); // 獲取溫度解析資料
void MPU6050_get_accel(float *AccelX, float *AccelY, float *AccelZ); // 獲取加速度解析資料
void MPU6050_get_gyro(float *GyroX, float *GyroY, float *GyroZ); // 獲取角速度解析資料

#endif /* INC_MPU6050_H_ */

mpu6050.c

#include "mpu6050.h"

// 初始化原始資料變數
int16_t tempData    = 0;
int16_t accelDataX  = 0;
int16_t accelDataY  = 0;
int16_t accelDataZ  = 0;
int16_t gyroDataX   = 0;
int16_t gyroDataY   = 0;
int16_t gyroDataZ   = 0;

// 初始化解析資料變數
float Temp   = 0;
float AccelX = 0;
float AccelY = 0;
float AccelZ = 0;
float GyroX  = 0;
float GyroY  = 0;
float GyroZ  = 0;

void MPU6050_Init(void)
{
	MX_I2C2_Init(); // 初始化I2C(使用者初始化程式碼區在自動初始化區域的前面,所有得在這裡面先初始化一遍)
	HAL_Delay(100);

	// 初始化配置暫存器
	MPU6050_Set_Register(MPU6050_PWR_MGMT_1, 0x00);
	MPU6050_Set_Register(MPU6050_SMPLRT_DIV, 0x07);
	MPU6050_Set_Register(MPU6050_CONFIG, 0x00);
	MPU6050_Set_Register(MPU6050_GYRO_CONFIG, 0x00);
	MPU6050_Set_Register(MPU6050_ACCEL_CONFIG, 0x00);
}

uint8_t MPU6050_GetID(void)
{
	return MPU6050_Read_Register(MPU6050_WHO_AM_I); // 返回0x68
}

void MPU6050_Send_CMD(uint8_t cmd)
{
	uint8_t CMD = cmd;

	HAL_I2C_Master_Transmit(hI2C, MPU6050_ADDRESS_Write, &CMD, 1, HAL_MAX_DELAY);
}

void MPU6050_Set_Register(uint8_t Register_ADDRESS, uint8_t Set_Value)
{
	uint8_t sendBuffer[2] = {Register_ADDRESS, Set_Value};

	HAL_I2C_Master_Transmit(hI2C, MPU6050_ADDRESS_Write, sendBuffer, 2, HAL_MAX_DELAY);
}

uint8_t MPU6050_Read_Register(uint8_t Register_ADDRESS)
{
	uint8_t readBuffer;

	MPU6050_Send_CMD(Register_ADDRESS);
	HAL_I2C_Master_Receive(hI2C, MPU6050_ADDRESS_Read, &readBuffer, 1, HAL_MAX_DELAY);

	return readBuffer;
}

uint16_t MPU6050_read_data(uint8_t addressH, uint8_t addressL)
{
	uint8_t highData = MPU6050_Read_Register(addressH);
	uint8_t lowData  = MPU6050_Read_Register(addressL);

	uint16_t rawData = ((int16_t) highData << 8) | (int16_t) lowData; // 拼接資料

    return rawData;
}

void MPU6050_get_tempData(int16_t *tempData)
{
	*tempData = MPU6050_read_data(MPU6050_TEMP_OUT_H, MPU6050_TEMP_OUT_L);
}

void MPU6050_get_accelData(int16_t *accelDataX, int16_t *accelDataY, int16_t *accelDataZ)
{
	*accelDataX = MPU6050_read_data(MPU6050_ACCEL_XOUT_H, MPU6050_ACCEL_XOUT_L);
	*accelDataY = MPU6050_read_data(MPU6050_ACCEL_YOUT_H, MPU6050_ACCEL_YOUT_L);
	*accelDataZ = MPU6050_read_data(MPU6050_ACCEL_ZOUT_H, MPU6050_ACCEL_ZOUT_L);
}

void MPU6050_get_gyroData(int16_t *gyroDataX, int16_t *gyroDataY, int16_t *gyroDataZ)
{
	*gyroDataX = MPU6050_read_data(MPU6050_GYRO_XOUT_H, MPU6050_GYRO_XOUT_L);
	*gyroDataY = MPU6050_read_data(MPU6050_GYRO_YOUT_H, MPU6050_GYRO_YOUT_L);
	*gyroDataZ = MPU6050_read_data(MPU6050_GYRO_ZOUT_H, MPU6050_GYRO_ZOUT_L);
}

void MPU6050_get_temp(float *Temp)
{
	MPU6050_get_tempData(&tempData);

	*Temp = tempData / 340.0 + 36.53;
}

void MPU6050_get_accel(float *AccelX, float *AccelY, float *AccelZ)
{
	MPU6050_get_accelData(&accelDataX, &accelDataY, &accelDataZ);

	*AccelX = accelDataX / 16384.0 * 9.8;
	*AccelY = accelDataY / 16384.0 * 9.8;
	*AccelZ = accelDataZ / 16384.0 * 9.8;
}

void MPU6050_get_gyro(float *GyroX, float *GyroY, float *GyroZ)
{
	MPU6050_get_gyroData(&gyroDataX, &gyroDataY, &gyroDataZ);

	*GyroX = gyroDataX / 131.0;
	*GyroY = gyroDataY / 131.0;
	*GyroZ = gyroDataZ / 131.0;
}

main.c

/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "mpu6050.h"
/* USER CODE END Includes */

/* USER CODE BEGIN 0 */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
 HAL_UART_Transmit(&huart4,(uint8_t*)&ch, 1, HAL_MAX_DELAY);
 return ch;
 }
/* USER CODE END 0 */

  /* USER CODE BEGIN Init */
  MPU6050_Init();
  /* USER CODE END Init */

  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  MPU6050_get_temp(&Temp);
	  MPU6050_get_accel(&AccelX, &AccelY, &AccelZ);
	  MPU6050_get_gyro(&GyroX, &GyroY, &GyroZ);

	  printf("%.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", Temp, AccelX, AccelY, AccelZ, GyroX, GyroY, GyroZ);

	  HAL_Delay(100);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

相關文章