陀螺仪传感器驱动程序(基于 MPU6050)

陀螺仪传感器驱动程序(基于 MPU6050)

一、系统架构设计

┌─────────────────────────────────────────────────────────────┐
│                    陀螺仪传感器驱动架构                    │
├─────────────────────────────────────────────────────────────┤
│  硬件接口层  │  寄存器配置  │  数据处理层  │  应用接口层   │
│              │              │              │              │
│  • I2C/SPI   │  • 量程配置  │  • 原始数据  │  • 初始化    │
│  • GPIO中断  │  • 滤波设置  │  • 校准补偿  │  • 数据读取  │
│  • 时钟源    │  • 采样率    │  • 单位转换  │  • 姿态解算  │
│  • 电源管理  │  • FIFO配置  │  • 温度补偿  │  • 状态监测  │
└─────────────────────────────────────────────────────────────┘

二、硬件连接设计

2.1 MPU6050 硬件连接(STM32)

MPU6050 引脚    STM32F103 引脚    说明
────────────────────────────────────────
VCC           3.3V              电源输入
GND           GND               电源地
SCL           PB6 (I2C1_SCL)    I2C时钟
SDA           PB7 (I2C1_SDA)    I2C数据
INT           PA0              中断输出
AD0           GND              地址选择(0x68)

2.2 关键参数规格

参数 规格
陀螺仪量程 ±250/500/1000/2000 °/s
加速度计量程 ±2/4/8/16 g
采样率 最高 8kHz
通信接口 I2C (400kHz) / SPI (20MHz)
工作电压 2.375V – 3.46V

三、源码实现

3.1 驱动头文件 (gyro_mpu6050.h)

#ifndef __GYRO_MPU6050_H
#define __GYRO_MPU6050_H

#include "stm32f10x.h"
#include <stdint.h>
#include <stdbool.h>
#include <math.h>

// MPU6050 I2C 地址
#define MPU6050_ADDR_AD0_LOW     0x68    // AD0接地
#define MPU6050_ADDR_AD0_HIGH    0x69    // AD0接VCC
#define MPU6050_ADDR_DEFAULT    MPU6050_ADDR_AD0_LOW

// MPU6050 寄存器地址
#define MPU6050_REG_SMPLRT_DIV   0x19    // 采样率分频
#define MPU6050_REG_CONFIG       0x1A    // 配置寄存器
#define MPU6050_REG_GYRO_CONFIG  0x1B    // 陀螺仪配置
#define MPU6050_REG_ACCEL_CONFIG 0x1C    // 加速度计配置
#define MPU6050_REG_FIFO_EN      0x23    // FIFO使能
#define MPU6050_REG_INT_PIN_CFG  0x37    // 中断引脚配置
#define MPU6050_REG_INT_ENABLE   0x38    // 中断使能
#define MPU6050_REG_INT_STATUS   0x3A    // 中断状态
#define MPU6050_REG_ACCEL_XOUT_H 0x3B    // 加速度X轴高字节
#define MPU6050_REG_ACCEL_XOUT_L 0x3C    // 加速度X轴低字节
#define MPU6050_REG_ACCEL_YOUT_H 0x3D    // 加速度Y轴高字节
#define MPU6050_REG_ACCEL_YOUT_L 0x3E    // 加速度Y轴低字节
#define MPU6050_REG_ACCEL_ZOUT_H 0x3F    // 加速度Z轴高字节
#define MPU6050_REG_ACCEL_ZOUT_L 0x40    // 加速度Z轴低字节
#define MPU6050_REG_TEMP_OUT_H   0x41    // 温度高字节
#define MPU6050_REG_TEMP_OUT_L   0x42    // 温度低字节
#define MPU6050_REG_GYRO_XOUT_H  0x43    // 陀螺仪X轴高字节
#define MPU6050_REG_GYRO_XOUT_L  0x44    // 陀螺仪X轴低字节
#define MPU6050_REG_GYRO_YOUT_H  0x45    // 陀螺仪Y轴高字节
#define MPU6050_REG_GYRO_YOUT_L  0x46    // 陀螺仪Y轴低字节
#define MPU6050_REG_GYRO_ZOUT_H  0x47    // 陀螺仪Z轴高字节
#define MPU6050_REG_GYRO_ZOUT_L  0x48    // 陀螺仪Z轴低字节
#define MPU6050_REG_USER_CTRL    0x6A    // 用户控制
#define MPU6050_REG_PWR_MGMT_1   0x6B    // 电源管理1
#define MPU6050_REG_PWR_MGMT_2   0x6C    // 电源管理2
#define MPU6050_REG_FIFO_COUNTH  0x72    // FIFO计数高字节
#define MPU6050_REG_FIFO_COUNTL  0x73    // FIFO计数低字节
#define MPU6050_REG_FIFO_R_W     0x74    // FIFO读写
#define MPU6050_REG_WHO_AM_I     0x75    // 设备ID

// 陀螺仪量程配置
typedef enum {
    GYRO_FS_250  = 0x00,  // ±250 °/s
    GYRO_FS_500  = 0x08,  // ±500 °/s
    GYRO_FS_1000 = 0x10,  // ±1000 °/s
    GYRO_FS_2000 = 0x18   // ±2000 °/s
} GyroFullScale_t;

// 加速度计量程配置
typedef enum {
    ACCEL_FS_2G  = 0x00,  // ±2 g
    ACCEL_FS_4G  = 0x08,  // ±4 g
    ACCEL_FS_8G  = 0x10,  // ±8 g
    ACCEL_FS_16G = 0x18   // ±16 g
} AccelFullScale_t;

// 数字低通滤波器配置
typedef enum {
    DLPF_BW_260 = 0x00,  // 260Hz带宽,0ms延迟
    DLPF_BW_184 = 0x01,  // 184Hz带宽,2ms延迟
    DLPF_BW_94  = 0x02,  // 94Hz带宽,3ms延迟
    DLPF_BW_44  = 0x03,  // 44Hz带宽,4.9ms延迟
    DLPF_BW_21  = 0x04,  // 21Hz带宽,8.5ms延迟
    DLPF_BW_10  = 0x05,  // 10Hz带宽,13.8ms延迟
    DLPF_BW_5   = 0x06   // 5Hz带宽,19ms延迟
} DLPF_Bandwidth_t;

// 陀螺仪数据结构体
typedef struct {
    float gyro_x;        // X轴角速度 (°/s)
    float gyro_y;        // Y轴角速度 (°/s)
    float gyro_z;        // Z轴角速度 (°/s)
    float accel_x;       // X轴加速度 (g)
    float accel_y;       // Y轴加速度 (g)
    float accel_z;       // Z轴加速度 (g)
    float temperature;   // 温度 (°C)
    uint32_t timestamp;  // 时间戳
    bool valid;          // 数据有效性
} GyroData_t;

// 校准参数结构体
typedef struct {
    float gyro_bias_x;   // 陀螺仪X轴零偏
    float gyro_bias_y;   // 陀螺仪Y轴零偏
    float gyro_bias_z;   // 陀螺仪Z轴零偏
    float accel_bias_x;  // 加速度计X轴零偏
    float accel_scale_x; // 加速度计X轴比例因子
    float accel_scale_y; // 加速度计Y轴比例因子
    float accel_scale_z; // 加速度计Z轴比例因子
    bool calibrated;    // 校准完成标志
} GyroCalibration_t;

// 传感器配置结构体
typedef struct {
    GyroFullScale_t gyro_fs;     // 陀螺仪量程
    AccelFullScale_t accel_fs;   // 加速度计量程
    DLPF_Bandwidth_t dlpf_bw;    // 数字低通滤波器带宽
    uint8_t sample_rate_div;     // 采样率分频
    bool fifo_enabled;           // FIFO使能
    bool int_enabled;            // 中断使能
} GyroConfig_t;

// 函数声明
bool MPU6050_Init(void);
bool MPU6050_Reset(void);
bool MPU6050_Config(GyroConfig_t *config);
bool MPU6050_ReadID(uint8_t *id);
bool MPU6050_ReadSensorData(GyroData_t *data);
bool MPU6050_ReadGyro(float *gx, float *gy, float *gz);
bool MPU6050_ReadAccel(float *ax, float *ay, float *az);
bool MPU6050_ReadTemperature(float *temp);
bool MPU6050_Calibrate(GyroCalibration_t *cal);
void MPU6050_SetCalibration(GyroCalibration_t *cal);
void MPU6050_ApplyCalibration(GyroData_t *data);
bool MPU6050_SetSleepMode(bool sleep);
bool MPU6050_SetCycleMode(bool cycle);
bool MPU6050_InterruptConfig(bool enable);
bool MPU6050_FIFOConfig(uint8_t sensors);
uint16_t MPU6050_GetFIFOCount(void);
bool MPU6050_ReadFIFO(uint8_t *buffer, uint16_t length);
bool MPU6050_ClearFIFO(void);

#endif /* __GYRO_MPU6050_H */

3.2 驱动核心实现 (gyro_mpu6050.c)

#include "gyro_mpu6050.h"
#include "i2c.h"
#include "delay.h"

// 全局变量
static GyroConfig_t gyro_config;
static GyroCalibration_t gyro_calibration = {0};
static bool gyro_initialized = false;

// I2C底层读写函数
static bool I2C_WriteReg(uint8_t reg, uint8_t data) {
    return I2C_WriteByte(MPU6050_ADDR_DEFAULT, reg, data);
}

static bool I2C_ReadReg(uint8_t reg, uint8_t *data) {
    return I2C_ReadByte(MPU6050_ADDR_DEFAULT, reg, data);
}

static bool I2C_ReadRegs(uint8_t reg, uint8_t *data, uint8_t len) {
    return I2C_ReadBytes(MPU6050_ADDR_DEFAULT, reg, data, len);
}

// 初始化MPU6050
bool MPU6050_Init(void) {
    uint8_t id;
    
    // 复位设备
    if (!MPU6050_Reset()) {
        return false;
    }
    Delay_ms(100);
    
    // 读取设备ID
    if (!MPU6050_ReadID(&id)) {
        return false;
    }
    
    if (id != 0x68) {
        return false;  // 设备ID不匹配
    }
    
    // 配置默认参数
    GyroConfig_t default_config = {
        .gyro_fs = GYRO_FS_1000,
        .accel_fs = ACCEL_FS_4G,
        .dlpf_bw = DLPF_BW_44,
        .sample_rate_div = 19,  // 1kHz / (19 + 1) = 50Hz
        .fifo_enabled = false,
        .int_enabled = false
    };
    
    if (!MPU6050_Config(&default_config)) {
        return false;
    }
    
    gyro_initialized = true;
    return true;
}

// 复位MPU6050
bool MPU6050_Reset(void) {
    // 设置复位位
    if (!I2C_WriteReg(MPU6050_REG_PWR_MGMT_1, 0x80)) {
        return false;
    }
    
    Delay_ms(100);
    
    // 清除复位位,选择时钟源为X轴陀螺仪
    if (!I2C_WriteReg(MPU6050_REG_PWR_MGMT_1, 0x01)) {
        return false;
    }
    
    Delay_ms(100);
    return true;
}

// 配置MPU6050参数
bool MPU6050_Config(GyroConfig_t *config) {
    if (config == NULL) {
        return false;
    }
    
    // 设置采样率分频
    if (!I2C_WriteReg(MPU6050_REG_SMPLRT_DIV, config->sample_rate_div)) {
        return false;
    }
    
    // 设置数字低通滤波器
    if (!I2C_WriteReg(MPU6050_REG_CONFIG, config->dlpf_bw)) {
        return false;
    }
    
    // 设置陀螺仪量程
    if (!I2C_WriteReg(MPU6050_REG_GYRO_CONFIG, config->gyro_fs)) {
        return false;
    }
    
    // 设置加速度计量程
    if (!I2C_WriteReg(MPU6050_REG_ACCEL_CONFIG, config->accel_fs)) {
        return false;
    }
    
    // 配置电源管理
    if (!I2C_WriteReg(MPU6050_REG_PWR_MGMT_1, 0x01)) {  // 使用X轴陀螺仪时钟
        return false;
    }
    
    // 配置电源管理2(使能所有轴)
    if (!I2C_WriteReg(MPU6050_REG_PWR_MGMT_2, 0x00)) {
        return false;
    }
    
    gyro_config = *config;
    return true;
}

// 读取设备ID
bool MPU6050_ReadID(uint8_t *id) {
    return I2C_ReadReg(MPU6050_REG_WHO_AM_I, id);
}

// 读取传感器数据
bool MPU6050_ReadSensorData(GyroData_t *data) {
    uint8_t raw_data[14];
    int16_t raw_gyro_x, raw_gyro_y, raw_gyro_z;
    int16_t raw_accel_x, raw_accel_y, raw_accel_z;
    int16_t raw_temp;
    
    if (data == NULL || !gyro_initialized) {
        return false;
    }
    
    // 读取14字节数据(加速度+温度+陀螺仪)
    if (!I2C_ReadRegs(MPU6050_REG_ACCEL_XOUT_H, raw_data, 14)) {
        return false;
    }
    
    // 解析原始数据
    raw_accel_x = (int16_t)((raw_data[0] << 8) | raw_data[1]);
    raw_accel_y = (int16_t)((raw_data[2] << 8) | raw_data[3]);
    raw_accel_z = (int16_t)((raw_data[4] << 8) | raw_data[5]);
    
    raw_temp = (int16_t)((raw_data[6] << 8) | raw_data[7]);
    
    raw_gyro_x = (int16_t)((raw_data[8] << 8) | raw_data[9]);
    raw_gyro_y = (int16_t)((raw_data[10] << 8) | raw_data[11]);
    raw_gyro_z = (int16_t)((raw_data[12] << 8) | raw_data[13]);
    
    // 转换为物理量
    float gyro_scale;
    float accel_scale;
    
    // 陀螺仪比例因子
    switch(gyro_config.gyro_fs) {
        case GYRO_FS_250:  gyro_scale = 250.0f / 32768.0f; break;
        case GYRO_FS_500:  gyro_scale = 500.0f / 32768.0f; break;
        case GYRO_FS_1000: gyro_scale = 1000.0f / 32768.0f; break;
        case GYRO_FS_2000: gyro_scale = 2000.0f / 32768.0f; break;
        default: gyro_scale = 1000.0f / 32768.0f; break;
    }
    
    // 加速度计比例因子
    switch(gyro_config.accel_fs) {
        case ACCEL_FS_2G:  accel_scale = 2.0f / 32768.0f; break;
        case ACCEL_FS_4G:  accel_scale = 4.0f / 32768.0f; break;
        case ACCEL_FS_8G:  accel_scale = 8.0f / 32768.0f; break;
        case ACCEL_FS_16G: accel_scale = 16.0f / 32768.0f; break;
        default: accel_scale = 4.0f / 32768.0f; break;
    }
    
    // 计算物理量
    data->gyro_x = raw_gyro_x * gyro_scale;
    data->gyro_y = raw_gyro_y * gyro_scale;
    data->gyro_z = raw_gyro_z * gyro_scale;
    
    data->accel_x = raw_accel_x * accel_scale;
    data->accel_y = raw_accel_y * accel_scale;
    data->accel_z = raw_accel_z * accel_scale;
    
    // 温度转换:温度(°C) = 36.53 + raw_temp / 340.0
    data->temperature = 36.53f + (float)raw_temp / 340.0f;
    data->timestamp = Get_SystemTime();
    data->valid = true;
    
    // 应用校准参数
    MPU6050_ApplyCalibration(data);
    
    return true;
}

// 读取陀螺仪数据
bool MPU6050_ReadGyro(float *gx, float *gy, float *gz) {
    GyroData_t data;
    
    if (!MPU6050_ReadSensorData(&data)) {
        return false;
    }
    
    if (gx) *gx = data.gyro_x;
    if (gy) *gy = data.gyro_y;
    if (gz) *gz = data.gyro_z;
    
    return true;
}

// 读取加速度计数据
bool MPU6050_ReadAccel(float *ax, float *ay, float *az) {
    GyroData_t data;
    
    if (!MPU6050_ReadSensorData(&data)) {
        return false;
    }
    
    if (ax) *ax = data.accel_x;
    if (ay) *ay = data.accel_y;
    if (az) *az = data.accel_z;
    
    return true;
}

// 读取温度数据
bool MPU6050_ReadTemperature(float *temp) {
    uint8_t raw_data[2];
    int16_t raw_temp;
    
    if (!I2C_ReadRegs(MPU6050_REG_TEMP_OUT_H, raw_data, 2)) {
        return false;
    }
    
    raw_temp = (int16_t)((raw_data[0] << 8) | raw_data[1]);
    *temp = 36.53f + (float)raw_temp / 340.0f;
    
    return true;
}

// 校准陀螺仪
bool MPU6050_Calibrate(GyroCalibration_t *cal) {
    GyroData_t data;
    float gyro_x_sum = 0, gyro_y_sum = 0, gyro_z_sum = 0;
    float accel_x_sum = 0, accel_y_sum = 0, accel_z_sum = 0;
    const uint16_t samples = 1000;
    
    if (cal == NULL) {
        return false;
    }
    
    printf("Starting Gyroscope Calibration...\n");
    printf("Please keep the sensor stationary!\n");
    
    // 采集样本数据
    for (uint16_t i = 0; i < samples; i++) {
        if (MPU6050_ReadSensorData(&data)) {
            gyro_x_sum += data.gyro_x;
            gyro_y_sum += data.gyro_y;
            gyro_z_sum += data.gyro_z;
            accel_x_sum += data.accel_x;
            accel_y_sum += data.accel_y;
            accel_z_sum += data.accel_z;
        }
        Delay_ms(10);
    }
    
    // 计算平均值作为零偏
    cal->gyro_bias_x = gyro_x_sum / samples;
    cal->gyro_bias_y = gyro_y_sum / samples;
    cal->gyro_bias_z = gyro_z_sum / samples;
    
    // 加速度计校准(假设Z轴垂直向上)
    cal->accel_bias_x = accel_x_sum / samples;
    cal->accel_bias_y = accel_y_sum / samples;
    cal->accel_bias_z = (accel_z_sum / samples) - 1.0f;  // 减去重力
    
    // 比例因子(默认1.0)
    cal->accel_scale_x = 1.0f;
    cal->accel_scale_y = 1.0f;
    cal->accel_scale_z = 1.0f;
    cal->calibrated = true;
    
    printf("Calibration Complete!\n");
    printf("Gyro Bias: X=%.4f, Y=%.4f, Z=%.4f °/s\n", 
           cal->gyro_bias_x, cal->gyro_bias_y, cal->gyro_bias_z);
    
    return true;
}

// 设置校准参数
void MPU6050_SetCalibration(GyroCalibration_t *cal) {
    if (cal != NULL) {
        gyro_calibration = *cal;
    }
}

// 应用校准参数
void MPU6050_ApplyCalibration(GyroData_t *data) {
    if (!gyro_calibration.calibrated || data == NULL) {
        return;
    }
    
    // 应用零偏补偿
    data->gyro_x -= gyro_calibration.gyro_bias_x;
    data->gyro_y -= gyro_calibration.gyro_bias_y;
    data->gyro_z -= gyro_calibration.gyro_bias_z;
    
    data->accel_x = (data->accel_x - gyro_calibration.accel_bias_x) * gyro_calibration.accel_scale_x;
    data->accel_y = (data->accel_y - gyro_calibration.accel_bias_y) * gyro_calibration.accel_scale_y;
    data->accel_z = (data->accel_z - gyro_calibration.accel_bias_z) * gyro_calibration.accel_scale_z;
}

// 设置睡眠模式
bool MPU6050_SetSleepMode(bool sleep) {
    uint8_t reg_value;
    
    if (!I2C_ReadReg(MPU6050_REG_PWR_MGMT_1, &reg_value)) {
        return false;
    }
    
    if (sleep) {
        reg_value |= 0x40;  // 设置睡眠位
    } else {
        reg_value &= ~0x40; // 清除睡眠位
    }
    
    return I2C_WriteReg(MPU6050_REG_PWR_MGMT_1, reg_value);
}

// FIFO配置
bool MPU6050_FIFOConfig(uint8_t sensors) {
    return I2C_WriteReg(MPU6050_REG_FIFO_EN, sensors);
}

// 获取FIFO计数
uint16_t MPU6050_GetFIFOCount(void) {
    uint8_t data[2];
    
    if (I2C_ReadRegs(MPU6050_REG_FIFO_COUNTH, data, 2)) {
        return ((uint16_t)data[0] << 8) | data[1];
    }
    
    return 0;
}

3.3 姿态解算模块 (attitude_estimator.c)

#include "gyro_mpu6050.h"
#include "math.h"

// 姿态结构体
typedef struct {
    float roll;        // 横滚角 (°)
    float pitch;       // 俯仰角 (°)
    float yaw;         // 偏航角 (°)
    float roll_rate;   // 横滚角速度 (°/s)
    float pitch_rate;  // 俯仰角速度 (°/s)
    float yaw_rate;    // 偏航角速度 (°/s)
    float quaternion[4]; // 四元数
} Attitude_t;

// 卡尔曼滤波器结构体
typedef struct {
    float q;        // 过程噪声协方差
    float r;        // 测量噪声协方差
    float x;        // 状态估计
    float p;        // 估计误差协方差
    float k;        // 卡尔曼增益
} KalmanFilter_t;

static KalmanFilter_t kalman_roll, kalman_pitch;
static Attitude_t current_attitude = {0};
static uint32_t last_update_time = 0;

// 初始化卡尔曼滤波器
void Kalman_Init(KalmanFilter_t *kalman, float q, float r) {
    kalman->q = q;
    kalman->r = r;
    kalman->x = 0.0f;
    kalman->p = 1.0f;
    kalman->k = 0.0f;
}

// 卡尔曼滤波更新
float Kalman_Update(KalmanFilter_t *kalman, float measurement) {
    // 预测步骤
    kalman->p = kalman->p + kalman->q;
    
    // 更新步骤
    kalman->k = kalman->p / (kalman->p + kalman->r);
    kalman->x = kalman->x + kalman->k * (measurement - kalman->x);
    kalman->p = (1 - kalman->k) * kalman->p;
    
    return kalman->x;
}

// 初始化姿态估计器
void AttitudeEstimator_Init(void) {
    Kalman_Init(&kalman_roll, 0.001f, 0.003f);
    Kalman_Init(&kalman_pitch, 0.001f, 0.003f);
    
    current_attitude.roll = 0.0f;
    current_attitude.pitch = 0.0f;
    current_attitude.yaw = 0.0f;
    
    // 初始化四元数
    current_attitude.quaternion[0] = 1.0f;  // w
    current_attitude.quaternion[1] = 0.0f;  // x
    current_attitude.quaternion[2] = 0.0f;  // y
    current_attitude.quaternion[3] = 0.0f;  // z
    
    last_update_time = Get_SystemTime();
}

// 互补滤波器更新姿态
void AttitudeEstimator_Update(GyroData_t *gyro_data) {
    float dt;
    uint32_t current_time = Get_SystemTime();
    
    if (last_update_time == 0) {
        last_update_time = current_time;
        return;
    }
    
    dt = (float)(current_time - last_update_time) / 1000.0f;  // 转换为秒
    last_update_time = current_time;
    
    if (dt <= 0 || dt > 1.0f) {
        return;  // 时间间隔异常
    }
    
    // 陀螺仪积分(角速度积分得到角度)
    float roll_gyro = current_attitude.roll + gyro_data->gyro_x * dt;
    float pitch_gyro = current_attitude.pitch + gyro_data->gyro_y * dt;
    float yaw_gyro = current_attitude.yaw + gyro_data->gyro_z * dt;
    
    // 加速度计计算姿态(仅用于横滚和俯仰)
    float roll_accel = atan2f(gyro_data->accel_y, gyro_data->accel_z) * 180.0f / M_PI;
    float pitch_accel = atan2f(-gyro_data->accel_x, 
                              sqrtf(gyro_data->accel_y * gyro_data->accel_y + 
                                    gyro_data->accel_z * gyro_data->accel_z)) * 180.0f / M_PI;
    
    // 互补滤波(陀螺仪为主,加速度计为辅)
    float alpha = 0.98f;  // 陀螺仪权重
    current_attitude.roll = alpha * roll_gyro + (1.0f - alpha) * roll_accel;
    current_attitude.pitch = alpha * pitch_gyro + (1.0f - alpha) * pitch_accel;
    current_attitude.yaw = yaw_gyro;  // 偏航角只能用陀螺仪积分
    
    // 卡尔曼滤波平滑
    current_attitude.roll = Kalman_Update(&kalman_roll, current_attitude.roll);
    current_attitude.pitch = Kalman_Update(&kalman_pitch, current_attitude.pitch);
    
    // 更新角速度
    current_attitude.roll_rate = gyro_data->gyro_x;
    current_attitude.pitch_rate = gyro_data->gyro_y;
    current_attitude.yaw_rate = gyro_data->gyro_z;
    
    // 更新四元数(使用陀螺仪数据)
    AttitudeEstimator_UpdateQuaternion(gyro_data, dt);
}

// 使用陀螺仪数据更新四元数
void AttitudeEstimator_UpdateQuaternion(GyroData_t *gyro_data, float dt) {
    float wx = gyro_data->gyro_x * M_PI / 180.0f;  // 转换为rad/s
    float wy = gyro_data->gyro_y * M_PI / 180.0f;
    float wz = gyro_data->gyro_z * M_PI / 180.0f;
    
    float q0 = current_attitude.quaternion[0];
    float q1 = current_attitude.quaternion[1];
    float q2 = current_attitude.quaternion[2];
    float q3 = current_attitude.quaternion[3];
    
    // 四元数微分方程
    float dq0 = 0.5f * (-q1 * wx - q2 * wy - q3 * wz);
    float dq1 = 0.5f * (q0 * wx + q2 * wz - q3 * wy);
    float dq2 = 0.5f * (q0 * wy + q3 * wx - q1 * wz);
    float dq3 = 0.5f * (q0 * wz + q1 * wy - q2 * wx);
    
    // 积分更新
    q0 += dq0 * dt;
    q1 += dq1 * dt;
    q2 += dq2 * dt;
    q3 += dq3 * dt;
    
    // 归一化
    float norm = sqrtf(q0*q0 + q1*q1 + q2*q2 + q3*q3);
    if (norm > 0) {
        q0 /= norm;
        q1 /= norm;
        q2 /= norm;
        q3 /= norm;
    }
    
    current_attitude.quaternion[0] = q0;
    current_attitude.quaternion[1] = q1;
    current_attitude.quaternion[2] = q2;
    current_attitude.quaternion[3] = q3;
}

// 获取当前姿态
Attitude_t* AttitudeEstimator_GetAttitude(void) {
    return &current_attitude;
}

// 四元数转欧拉角
void QuaternionToEuler(float *quaternion, float *roll, float *pitch, float *yaw) {
    float q0 = quaternion[0];
    float q1 = quaternion[1];
    float q2 = quaternion[2];
    float q3 = quaternion[3];
    
    // 横滚角 (roll)
    *roll = atan2f(2.0f * (q0*q1 + q2*q3), 1.0f - 2.0f * (q1*q1 + q2*q2)) * 180.0f / M_PI;
    
    // 俯仰角 (pitch)
    float sin_pitch = 2.0f * (q0*q2 - q3*q1);
    if (fabsf(sin_pitch) >= 1.0f) {
        *pitch = copysignf(M_PI / 2.0f, sin_pitch) * 180.0f / M_PI;  // 使用90度
    } else {
        *pitch = asinf(sin_pitch) * 180.0f / M_PI;
    }
    
    // 偏航角 (yaw)
    *yaw = atan2f(2.0f * (q0*q3 + q1*q2), 1.0f - 2.0f * (q2*q2 + q3*q3)) * 180.0f / M_PI;
}

3.4 主程序示例 (main.c)

#include "stm32f10x.h"
#include "gyro_mpu6050.h"
#include "attitude_estimator.h"
#include "usart.h"
#include "delay.h"
#include "led.h"

// 系统状态
typedef enum {
    SYS_INIT = 0,
    SYS_CALIBRATING,
    SYS_RUNNING,
    SYS_ERROR
} SystemState_t;

static SystemState_t system_state = SYS_INIT;
static GyroData_t gyro_data;
static uint32_t data_counter = 0;

// 系统初始化
void System_Init(void) {
    SystemClock_Init();
    Delay_Init();
    USART_Init(115200);
    LED_Init();
    I2C_Init();
    
    printf("MPU6050 Gyroscope Driver Test\r\n");
    printf("==============================\r\n");
}

// 显示姿态数据
void Display_AttitudeData(void) {
    Attitude_t *attitude = AttitudeEstimator_GetAttitude();
    
    printf("Roll: %.2f°, Pitch: %.2f°, Yaw: %.2f°\r\n", 
           attitude->roll, attitude->pitch, attitude->yaw);
    printf("Gyro: X=%.2f, Y=%.2f, Z=%.2f °/s\r\n", 
           attitude->roll_rate, attitude->pitch_rate, attitude->yaw_rate);
    printf("Accel: X=%.3f, Y=%.3f, Z=%.3f g\r\n", 
           gyro_data.accel_x, gyro_data.accel_y, gyro_data.accel_z);
    printf("Temp: %.2f°C\r\n", gyro_data.temperature);
    printf("----------------------------------------\r\n");
}

int main(void) {
    GyroCalibration_t calibration;
    
    // 系统初始化
    System_Init();
    
    // 初始化MPU6050
    if (!MPU6050_Init()) {
        printf("MPU6050 Initialization Failed!\r\n");
        system_state = SYS_ERROR;
        while(1);
    }
    
    printf("MPU6050 Initialized Successfully!\r\n");
    
    // 校准传感器
    system_state = SYS_CALIBRATING;
    LED_On(LED0);
    
    if (MPU6050_Calibrate(&calibration)) {
        MPU6050_SetCalibration(&calibration);
        printf("Calibration Successful!\r\n");
    } else {
        printf("Calibration Failed! Using default values.\r\n");
    }
    
    // 初始化姿态估计器
    AttitudeEstimator_Init();
    
    system_state = SYS_RUNNING;
    LED_Off(LED0);
    
    printf("System Running...\r\n");
    printf("Press any key to stop display\r\n");
    
    while(1) {
        // 读取传感器数据
        if (MPU6050_ReadSensorData(&gyro_data)) {
            data_counter++;
            
            // 更新姿态估计
            AttitudeEstimator_Update(&gyro_data);
            
            // 每秒显示一次数据
            if (data_counter % 50 == 0) {  // 50Hz采样,每秒显示一次
                Display_AttitudeData();
                
                // LED指示系统运行状态
                LED_Toggle(LED1);
            }
        } else {
            printf("Sensor Read Error!\r\n");
            LED_Blink(LED0, 100);  // 快速闪烁表示错误
        }
        
        Delay_ms(20);  // 50Hz采样率
    }
}

参考代码 陀螺仪传感器驱动程序 www.youwenfan.com/contentcsu/60586.html

四、工程配置与优化

4.1 编译配置

# 编译选项
CFLAGS = -O2 -Wall -Wextra -std=c99
INCLUDES = -I./Inc -I./Drivers

# 源文件
SOURCES = main.c \
          gyro_mpu6050.c \
          attitude_estimator.c \
          i2c.c \
          delay.c \
          usart.c \
          led.c

# 链接选项
LDFLAGS = -Tlinker.ld -nostdlib

4.2 性能优化建议

优化项目 建议方案
采样率优化 根据应用需求设置合适的采样率(50-200Hz)
滤波优化 使用互补滤波或卡尔曼滤波减少噪声
校准优化 定期重新校准,考虑温度影响
功耗优化 不使用时进入睡眠模式
数据融合 结合磁力计进行更好的姿态估计

4.3 常见问题解决

问题 原因 解决方案
传感器无响应 I2C地址错误或通信失败 检查硬件连接和I2C时序
数据漂移严重 未进行校准或校准不准确 重新进行静态校准
姿态解算不稳定 滤波参数不合适 调整互补滤波系数
温度影响大 未考虑温度补偿 添加温度补偿算法
振动干扰 机械振动影响 增加物理减震,软件滤波

专注于matlab/simulink,电子电路,编程