前言
本篇我們接收對MPU6050的基本使用,獲取ID,通過IIC協議獲取寄存器的值,至于高級濾波算法,比如卡爾曼濾波,或者上面的,后面再更新
基本配置
最好選擇PA0和PA1,5V開漏
然后給上代碼
MPU6050.c
#include "MPU6050.h"
#include "delay.h"// I2C通信相關的靜態函數定義
// 設置 SCL 引腳電平,并添加延時
static void IIC_SCL_(uint8_t state)
{if (state)DL_GPIO_setPins(SOFT_IIC_SCL_PORT, SOFT_IIC_SCL_PIN);elseDL_GPIO_clearPins(SOFT_IIC_SCL_PORT, SOFT_IIC_SCL_PIN);delay_us(5);
}// 設置 SDA 引腳電平,并添加延時
static void IIC_SDA_(uint8_t state)
{DL_GPIO_initDigitalOutput(MPU6050_SDA_IOMUX);if (state)DL_GPIO_setPins(SOFT_IIC_SDA_PORT, SOFT_IIC_SDA_PIN);elseDL_GPIO_clearPins(SOFT_IIC_SDA_PORT, SOFT_IIC_SDA_PIN);delay_us(5);
}// 讀取 SDA 引腳電平
static uint8_t IIC_SDA_Read(void)
{DL_GPIO_initDigitalInputFeatures(MPU6050_SDA_input,DL_GPIO_INVERSION_DISABLE, DL_GPIO_RESISTOR_NONE,DL_GPIO_HYSTERESIS_DISABLE, DL_GPIO_WAKEUP_DISABLE);return DL_GPIO_readPins(SOFT_IIC_SDA_PORT, SOFT_IIC_SDA_PIN);
}// I2C 初始化
static void IIC_Init(void)
{// 初始狀態:SCL 和 SDA 都為高電平IIC_SCL_(1);IIC_SDA_(1);
}// 發送起始信號
static void IIC_Start(void)
{IIC_SDA_(1);IIC_SCL_(1);IIC_SDA_(0);IIC_SCL_(0);
}// 發送停止信號
static void IIC_Stop(void)
{IIC_SCL_(0);IIC_SDA_(0);IIC_SCL_(1);IIC_SDA_(1);
}// 發送一個字節
static void IIC_SendByte(uint8_t data)
{uint8_t i;for (i = 0; i < 8; i++){IIC_SDA_((data & 0x80) >> 7);data <<= 1;IIC_SCL_(1);IIC_SCL_(0);}
}// 接收一個字節
static uint8_t IIC_ReceiveByte(uint8_t ack)
{uint8_t i, data = 0;IIC_SDA_(1); // 釋放 SDA 線for (i = 0; i < 8; i++){IIC_SCL_(1);data <<= 1;if (IIC_SDA_Read())data |= 0x01;IIC_SCL_(0);}if (ack)IIC_SDA_(0); // 發送應答elseIIC_SDA_(1); // 發送非應答IIC_SCL_(1);IIC_SCL_(0);return data;
}// 等待應答信號
static uint8_t IIC_WaitAck(void)
{uint8_t ack;IIC_SDA_(1);IIC_SCL_(1);ack = IIC_SDA_Read();IIC_SCL_(0);return ack;
}// 向 MPU6050 寫入一個字節數據
static void IIC_Write_REG(uint8_t addr, uint8_t reg, uint8_t data)
{IIC_Start();IIC_SendByte((addr << 1) | 0); // 發送寫地址IIC_WaitAck();IIC_SendByte(reg); // 發送寄存器地址IIC_WaitAck();IIC_SendByte(data); // 發送數據IIC_WaitAck();IIC_Stop();
}// 從 MPU6050 讀取一個字節數據
static uint8_t IIC_Read_REG(uint8_t Address, uint8_t regaddress)
{uint8_t data;IIC_Start(); // 發送起始信號IIC_SendByte(Address << 1 | 0); // 發送設備地址和寫操作IIC_WaitAck(); // 等待 ACKIIC_SendByte(regaddress); // 發送寄存器地址IIC_WaitAck(); // 等待 ACKIIC_Start(); // 發送起始信號IIC_SendByte(Address << 1 | 1); // 發送設備地址和讀操作IIC_WaitAck(); // 等待 ACKdata = IIC_ReceiveByte(0); // 讀取數據IIC_Stop(); // 發送停止信號return data; // 返回讀取的數據
}// MPU6050 初始化函數
uint8_t MPU6050_Init(void)
{IIC_Init(); // 初始化 I2C 總線// 喚醒 MPU6050IIC_Write_REG(MPU6050_ADDR_AD0_LOW, PWR_MGMT_1, 0x00);delay_ms(100); // 等待喚醒// 設置采樣率分頻IIC_Write_REG(MPU6050_ADDR_AD0_LOW, SMPLRT_DIV, 0x07);// 設置低通濾波器IIC_Write_REG(MPU6050_ADDR_AD0_LOW, CONFIG, 0x06);// 設置陀螺儀量程 ±250°/sIIC_Write_REG(MPU6050_ADDR_AD0_LOW, GYRO_CONFIG, 0x00);// 設置加速度計量程 ±2gIIC_Write_REG(MPU6050_ADDR_AD0_LOW, ACCEL_CONFIG, 0x00);delay_ms(100); // 等待喚醒return 0;
}// 讀取 MPU6050 的設備 ID
uint8_t MPU6050_GetDeviceID(void)
{uint8_t data;data = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, WHO_AM_I); // 讀取設備 ID 寄存器return data; // 返回設備 ID
}float MPU6050_GET_Tempure(void)
{int16_t temp; // 用于存儲溫度傳感器數據uint8_t H, L; // 用于存儲高字節和低字節的數據H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, TEMP_OUT_H); // 讀取溫度傳感器高字節L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, TEMP_OUT_L); // 讀取溫度傳感器低字節temp = (H << 8) | L; // 將高字節和低字節合并為一個 16 位數據return (float)temp / 340.0 + 36.53 - 200; // 計算溫度值并返回
}float MPU6050_GetAccelX(void)
{int16_t accel; // 用于存儲加速度傳感器數據uint8_t H, L; // 用于存儲高字節和低字節的數據H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_XOUT_H); // 讀取加速度傳感器 X 軸高字節L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_XOUT_L); // 讀取加速度傳感器 X 軸低字節accel = (H << 8) | L; // 將高字節和低字節合并為一個 16 位數據return ((float)accel / 16384.0 + 1) * 90 - 90; // 直接返回角度
}float MPU6050_GetAccelY(void)
{int16_t accel; // 用于存儲加速度傳感器數據uint8_t H, L; // 用于存儲高字節和低字節的數據H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_YOUT_H); // 讀取加速度傳感器 Y 軸高字節L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_YOUT_L); // 讀取加速度傳感器 Y 軸低字節accel = (H << 8) | L; // 將高字節和低字節合并為一個 16 位數據return ((float)accel / 16384.0 + 1) * 90 - 90; // 直接返回角度
}float MPU6050_GetAccelZ(void)
{int16_t accel; // 用于存儲加速度傳感器數據uint8_t H, L; // 用于存儲高字節和低字節的數據H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_ZOUT_H); // 讀取加速度傳感器 Z 軸高字節L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, ACCEL_ZOUT_L); // 讀取加速度傳感器 Z 軸低字節accel = (H << 8) | L; // 將高字節和低字節合并為一個 16 位數據return ((float)accel / 16384.0 + 1) * 90 - 90; // 直接返回角度
}float MPU6050_GetAngleX(void)
{int16_t gyro; // 用于存儲陀螺儀數據uint8_t H, L; // 用于存儲高字節和低字節的數據H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_XOUT_H); // 讀取陀螺儀 X 軸高字節L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_XOUT_L); // 讀取陀螺儀 X 軸低字節gyro = (H << 8) | L; // 將高字節和低字節合并為一個 16 位數據return (float)gyro / 131.0; // 計算角速度值并返回
}float MPU6050_GetAngleY(void)
{int16_t gyro; // 用于存儲陀螺儀數據uint8_t H, L; // 用于存儲高字節和低字節的數據H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_YOUT_H); // 讀取陀螺儀 Y 軸高字節L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_YOUT_L); // 讀取陀螺儀 Y 軸低字節gyro = (H << 8) | L; // 將高字節和低字節合并為一個 16 位數據return (float)gyro / 131.0; // 計算角速度值并返回
}float MPU6050_GetAngleZ(void)
{int16_t gyro; // 用于存儲陀螺儀數據uint8_t H, L; // 用于存儲高字節和低字節的數據H = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_ZOUT_H); // 讀取陀螺儀 Z 軸高字節L = IIC_Read_REG(MPU6050_ADDR_AD0_LOW, GYRO_ZOUT_L); // 讀取陀螺儀 Z 軸低字節gyro = (H << 8) | L; // 將高字節和低字節合并為一個 16 位數據return (float)gyro / 131.0; // 計算角速度值并返回
}
MPU6050.h
#ifndef __MPU6050_H
#define __MPU6050_H#include "ti_msp_dl_config.h"// I2C引腳定義
#define SOFT_IIC_SCL_PORT GPIOA // SCL端口
#define SOFT_IIC_SCL_PIN DL_GPIO_PIN_1 // SCL引腳
#define SOFT_IIC_SDA_PORT GPIOA // SDA端口
#define SOFT_IIC_SDA_PIN DL_GPIO_PIN_0 // SDA引腳
#define MPU6050_SDA_input IOMUX_PINCM1 // SDA引腳IOMUX配置// MPU6050寄存器地址定義
#define M_PI 3.14
#define SMPLRT_DIV 0x19 // 采樣率分頻,典型值:0x07(125Hz) */
#define CONFIG 0x1A // 低通濾波頻率,典型值:0x06(5Hz) */
#define GYRO_CONFIG 0x1B // 陀螺儀自檢及測量范圍,典型值:0x18(不自檢,2000deg/s) */
#define ACCEL_CONFIG 0x1C // 加速計自檢、測量范圍及高通濾波頻率,典型值:0x01(不自檢,2G,5Hz) */#define ACCEL_XOUT_H 0x3B // 存儲最近的X軸、Y軸、Z軸加速度感應器的測量值 */
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40#define TEMP_OUT_H 0x41 // 存儲的最近溫度傳感器的測量值 */
#define TEMP_OUT_L 0x42#define GYRO_XOUT_H 0x43 // 存儲最近的X軸、Y軸、Z軸陀螺儀感應器的測量值 */
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48#define PWR_MGMT_1 0x6B // 電源管理,典型值:0x00(正常啟用) */
#define PWR_MGMT_2 0x6C // 電源管理,典型值:0x00(正常啟用) */
#define WHO_AM_I 0x75 // IIC地址寄存器(默認數值0x68,只讀) */// HAL庫的讀寫只需要使用7位地址
#define MPU6050_ADDR_AD0_LOW 0x68 // AD0低電平時7位地址為0X68 iic寫時時發送0XD0
#define MPU6050_ADDR_AD0_HIGH 0x69// 函數聲明
uint8_t MPU6050_Init(void);
uint8_t MPU6050_GetDeviceID(void);
float MPU6050_GET_Tempure(void);
float MPU6050_GetAccelX(void);
float MPU6050_GetAccelY(void);
float MPU6050_GetAccelZ(void);
float MPU6050_GetAngleX(void);
float MPU6050_GetAngleY(void);
float MPU6050_GetAngleZ(void);#endif /* __MPU6050_H */
主函數測試
uart_init();uart_send_string("=== MPU6050 Test Program ===\r\n");char buf[100];MPU6050_Init();uint8_t id = MPU6050_GetDeviceID();sprintf(buf, "MPU6050 ID: %x\r\n", id);uart_send_string(buf);while (1){//sprintf(buf, "Acc: %.2f, %.2f, %.2f,\r\n", MPU6050_GetAccelX(), MPU6050_GetAccelY(), MPU6050_GetAccelZ());// uart_send_string(buf);sprintf(buf, "Gyro: %.2f, %.2f, %.2f,\r\n",MPU6050_GetAngleX(), MPU6050_GetAngleY(), MPU6050_GetAngleZ());uart_send_string(buf);delay_ms(100);}