STM32 HAL驅動MPU6050傳感器
項目概述
本項目實現了基于STM32 HAL庫的MPU6050傳感器驅動,可以讀取加速度計和陀螺儀數據。項目使用I2C接口與MPU6050通信,并通過UART接口輸出數據。
項目倉庫地址:STM32_Sensor_Drives
硬件連接
MPU6050 I2C接口
PB10 ------> I2C2_SCL
PB11 ------> I2C2_SDA
UART調試接口
PA2 ------> USART2_TX
PA3 ------> USART2_RX
代碼結構
項目主要包含以下文件:
main.c
: 主程序入口,初始化外設并循環讀取MPU6050數據i2c.c/h
: I2C配置和MPU6050驅動函數usart.c/h
: UART配置和printf重定向gpio.c/h
: GPIO配置
MPU6050驅動實現
數據結構定義
在i2c.h
中定義了MPU6050數據結構:
typedef struct _mpu6050_data{double ACCEL_X ,ACCEL_Y ,ACCEL_Z;double GYRO_X ,GYRO_Y ,GYRO_Z;
}mpu6050_data;
初始化函數
在i2c.c
中實現了MPU6050初始化函數:
void MPU6050_start(void)
{uint8_t SendAddress = 0x6b;uint8_t SendData = 0x00; //解除休眠狀態HAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);SendAddress = 0x19;//采樣率分頻器SendData = 0x07;HAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);SendAddress = 0x1A;//低通濾波器SendData = 0x06;HAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);SendAddress = 0x1B;//陀螺儀SendData = 0x08; //± 500 °/sHAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);SendAddress = 0x1C;//加速度計SendData = 0x00; //± 2gHAL_I2C_Mem_Write(&hi2c2,0xD1,SendAddress,1,&SendData,1,0xff);
}
初始化步驟:
- 解除MPU6050休眠狀態(寄存器0x6B)
- 設置采樣率分頻器(寄存器0x19)
- 配置低通濾波器(寄存器0x1A)
- 配置陀螺儀量程為±500°/s(寄存器0x1B)
- 配置加速度計量程為±2g(寄存器0x1C)
數據讀取函數
在i2c.c
中實現了MPU6050數據讀取函數:
void get_i2c_mpu6050(mpu6050_data *data){uint8_t MPU_Data[] = {0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00};uint8_t preg1_Data = 0x3B;HAL_I2C_Mem_Read(&hi2c2, 0xD1,preg1_Data,I2C_MEMADD_SIZE_8BIT,MPU_Data,14,50);float Temp = (MPU_Data[6]<<8)|MPU_Data[7];if(Temp>32768) Temp-=65536;Temp=(36.53+Temp/340);short int ACCEL_XOUT1 = ((MPU_Data[0]<<8)|MPU_Data[1]);data->ACCEL_X = (double)ACCEL_XOUT1/16384;short int ACCEL_YOUT1 = ((MPU_Data[2]<<8)|MPU_Data[3]);data->ACCEL_Y = (double)ACCEL_YOUT1/16384;short int ACCEL_ZOUT1 = ((MPU_Data[4]<<8)|MPU_Data[5]);data->ACCEL_Z = (double)ACCEL_ZOUT1/16384;short int GYRO_XOUT1 = ((MPU_Data[8]<<8)|MPU_Data[9]);data->GYRO_X = (double)GYRO_XOUT1/65.5;short int GYRO_YOUT1 = ((MPU_Data[10]<<8)|MPU_Data[11]);data->GYRO_Y = (double)GYRO_YOUT1/65.5;short int GYRO_ZOUT1 = ((MPU_Data[12]<<8)|MPU_Data[13]);data->GYRO_Z = (double)GYRO_ZOUT1/65.5;
}
數據讀取步驟:
- 從寄存器0x3B開始,連續讀取14個字節的數據
- 處理溫度數據(雖然在本例中未使用)
- 處理加速度數據(前6個字節)
- X軸加速度:字節0-1
- Y軸加速度:字節2-3
- Z軸加速度:字節4-5
- 除以16384轉換為g單位(±2g量程下)
- 處理陀螺儀數據(后6個字節)
- X軸角速度:字節8-9
- Y軸角速度:字節10-11
- Z軸角速度:字節12-13
- 除以65.5轉換為°/s單位(±500°/s量程下)
I2C配置
I2C配置在i2c.c
中實現:
void MX_I2C2_Init(void)
{hi2c2.Instance = I2C2;hi2c2.Init.ClockSpeed = 100000;hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;hi2c2.Init.OwnAddress1 = 0;hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;hi2c2.Init.OwnAddress2 = 0;hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;if (HAL_I2C_Init(&hi2c2) != HAL_OK){Error_Handler();}
}
主要配置:
- 時鐘速度:100kHz
- 7位地址模式
- 禁用時鐘拉伸
UART配置與printf重定向
UART配置在usart.c
中實現:
void MX_USART2_UART_Init(void)
{huart2.Instance = USART2;huart2.Init.BaudRate = 115200;huart2.Init.WordLength = UART_WORDLENGTH_8B;huart2.Init.StopBits = UART_STOPBITS_1;huart2.Init.Parity = UART_PARITY_NONE;huart2.Init.Mode = UART_MODE_TX_RX;huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart2.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart2) != HAL_OK){Error_Handler();}
}
為了支持printf函數,重定向了fputc函數:
int fputc(int ch, FILE *f)
{if (f == stdout) // 僅處理標準輸出{HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 100); // 阻塞發送if (ch == '\n') // 發送\n時自動補充\rHAL_UART_Transmit(&huart2, (uint8_t *)"\r", 1, 100);}return ch;
}
主程序
主程序在main.c
中實現:
int main(void)
{/* 初始化代碼省略 */MX_GPIO_Init();MX_USART2_UART_Init();MX_I2C2_Init();/* USER CODE BEGIN 2 */MPU6050_start();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */printf("System will start while\n");while (1){mpu6050_data data = {0};get_i2c_mpu6050(&data);printf("ax: %.3f--ay: %.3f--az: %.3f--gx: %.3f--gy: %.3f--gz: %.3f\n", data.ACCEL_X, data.ACCEL_Y, data.ACCEL_Z, data.GYRO_X, data.GYRO_Y, data.GYRO_Z);HAL_Delay(200);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
主程序流程:
- 初始化GPIO、UART和I2C外設
- 初始化MPU6050傳感器
- 進入主循環
- 讀取MPU6050數據
- 通過UART打印數據
- 延時200ms
MPU6050寄存器說明
寄存器地址 | 名稱 | 功能 |
---|---|---|
0x6B | PWR_MGMT_1 | 電源管理1,用于設備復位、睡眠模式、時鐘源等 |
0x19 | SMPLRT_DIV | 采樣率分頻器 |
0x1A | CONFIG | 配置寄存器,主要用于配置DLPF(數字低通濾波器) |
0x1B | GYRO_CONFIG | 陀螺儀配置,設置量程等 |
0x1C | ACCEL_CONFIG | 加速度計配置,設置量程等 |
0x3B-0x40 | ACCEL_XOUT_H至ACCEL_ZOUT_L | 加速度計輸出數據 |
0x41-0x42 | TEMP_OUT_H和TEMP_OUT_L | 溫度傳感器輸出數據 |
0x43-0x48 | GYRO_XOUT_H至GYRO_ZOUT_L | 陀螺儀輸出數據 |
注意事項
-
MPU6050的I2C地址為0x68(二進制:1101000),但在代碼中使用的是0xD1(二進制:11010001)。這是因為HAL庫的I2C函數需要在7位地址后添加讀/寫位(0表示寫,1表示讀)。
-
加速度計和陀螺儀的原始數據都是16位有符號整數,需要進行轉換才能得到實際的物理量:
- 加速度計:在±2g量程下,除以16384得到以g為單位的加速度
- 陀螺儀:在±500°/s量程下,除以65.5得到以°/s為單位的角速度
-
溫度傳感器的數據轉換公式為:溫度(°C) = 36.53 + (原始數據/340)