You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32读取MPU6050陀螺仪数据始终固定不变的问题求助

问题:MPU6050陀螺仪X轴数据固定为60254,无法随设备转动变化

我正在使用STM32F050 MCU,尝试通过MPU6050获取陀螺仪和加速度计数据。已通过以下代码完成MPU6050初始化(初始化成功时LD2会闪烁20次,确认设备连接正常):

HAL_StatusTypeDef initMPU6050(void) {
  uint8_t check;
  HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, MPU6050_WHO_AM_I_REG, 1, &check, 1, 1000);
  if (check == 0x68) {
    for (int i = 0; i < 20; i++) {
      HAL_GPIO_TogglePin(GPIOA, LD2_Pin);
      HAL_Delay(200);
    }
    // 设置陀螺仪量程为500deg/s,加速度计量程为4g
    uint8_t gyroRegSet = 0x08;
    uint8_t accelRegSet = 0x08;
    uint8_t pwrMgmtSet = 0;
    HAL_StatusTypeDef ret;
    ret = HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, MPU6050_GYRO_REG, 1, &gyroRegSet, 1, 100);
    if (ret != HAL_OK) {return HAL_ERROR;}
    HAL_Delay(50);
    ret = HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, MPU6050_ACCEL_REG, 1, &accelRegSet, 1, 100);
    if (ret != HAL_OK) {return HAL_ERROR;}
    HAL_Delay(50);
    ret = HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, MPU6050_PWE_MGMT_REG, 1, &pwrMgmtSet, 1, 100);
    if (ret != HAL_OK) {return HAL_ERROR;}
    return HAL_OK;
  }
  return HAL_ERROR;
}

初始化完成后,我尝试通过以下代码读取陀螺仪X轴数据:

HAL_StatusTypeDef readGyroGx(uint16_t* Gx, HAL_StatusTypeDef init) {
  if (init != HAL_OK) {return HAL_ERROR;}
  uint8_t gxh;
  uint8_t gxl;
  HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, 0x43, 1, &gxh, 1, 1000);
  HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, 0x44, 1, &gxl, 1, 1000);
  Gx = (gxh<<8) | gxl;
}

并通过主循环将数据输出到串口:

uint16_t buf[20];
HAL_StatusTypeDef init = initMPU6050();
uint16_t gx;
while (1)
{
  readGyroGx(&gx, init);
  sprintf((char*)buf, "%u \r\n", gx);
  HAL_UART_Transmit(&huart2, buf, strlen((char*)buf), 1000);
  HAL_GPIO_TogglePin(GPIOA, LD2_Pin);
  HAL_Delay(100);
}

无论旋转或移动MPU6050,Gx值始终固定为60254,求解决建议。


解决建议

  • 修正指针赋值错误:readGyroGx函数中,Gx = (gxh<<8) | gxl;是给指针变量本身赋值,而非修改指针指向的内存空间,导致主函数中的gx变量从未被更新。正确写法应为:

    *Gx = (int16_t)((gxh << 8) | gxl);
    

    同时注意,MPU6050的陀螺仪数据是有符号16位整数,60254是-512的无符号表示,这正是未正确赋值导致的初始值或错误读取结果。

  • 更换连续读取方式:避免分两次读取高低字节,MPU6050支持连续读取多个寄存器,一次读取2个字节能减少I2C通信次数,避免时序问题:

    HAL_StatusTypeDef readGyroGx(int16_t* Gx, HAL_StatusTypeDef init) {
      if (init != HAL_OK) {return HAL_ERROR;}
      // 从0x43开始连续读取2个字节
      if(HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, 0x43, 1, (uint8_t*)Gx, 2, 1000) != HAL_OK) {
          return HAL_ERROR;
      }
      return HAL_OK;
    }
    
  • 修正变量类型与打印格式:将存储陀螺仪数据的变量类型改为int16_t,串口打印时使用%d格式符,避免负数被解析为超大无符号数:

    int16_t gx;
    // ...
    sprintf((char*)buf, "%d \r\n", gx);
    
  • 检查I2C读取返回值:在读取数据时添加返回值检查,确认每次I2C通信是否成功,避免读取失败却未处理的情况:

    if(HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, 0x43, 1, &gxh, 1, 1000) != HAL_OK) {
        return HAL_ERROR;
    }
    if(HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, 0x44, 1, &gxl, 1, 1000) != HAL_OK) {
        return HAL_ERROR;
    }
    
  • 确认寄存器地址与设备地址:虽然WHO_AM_I读取正常,但仍需确认MPU6050_ADDR定义正确(0x68或0x69,取决于AD0引脚电平),以及陀螺仪寄存器地址0x43、0x44未写错。

内容的提问来源于stack exchange,提问作者Allan Liu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:15:55