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

STM32驱动MPU6050时I2C可读但无法写入的故障排查

MPU6050 I2C可读但无法写入寄存器问题分析与解决

问题概述

基于STM32F767ZI开发MPU6050驱动时,出现读写异常:读取WHO_AM_I寄存器能正常返回设备地址,但写入SAMPLE_RATE_DIVIDER寄存器后,读取返回值始终为0x00。所有HAL库调用均返回HAL_OK,设备应答正常。

现有代码

I2C写入函数

static IOStatus_t Stm32f767zi_I2C_Write(uint8_t Address,uint32_t Size,uint8_t* DataPtr)
{
    IOStatus_t Status = IO_SUCCESS;
    HAL_StatusTypeDef HAL_Status;

    uint8_t* WritePointer = (uint8_t*) malloc(Size+1);
    memcpy(WritePointer,&Address,1);
    memcpy(WritePointer+1,DataPtr,Size);

    HAL_Status = HAL_I2C_Master_Transmit(&hi2c2, MPU6050_I2C_ADDRESS<<1, WritePointer, Size+1, 100);

    free(WritePointer);

    if (HAL_Status != HAL_OK)
    {
        Status = IO_FAILURE;
    }
    return Status;
}

I2C读取函数

static IOStatus_t Stm32f767zi_I2C_Read(uint8_t Address,uint32_t Size,uint8_t* DataPtr)
{
    IOStatus_t Status = IO_SUCCESS;
    HAL_StatusTypeDef HAL_Status;

    HAL_Status = HAL_I2C_Master_Transmit(&hi2c2, MPU6050_I2C_ADDRESS<<1, &Address, 1, 100);
    HAL_Delay(1);
    if (HAL_Status == HAL_OK)
    {
        HAL_Status = HAL_I2C_Master_Receive(&hi2c2, MPU6050_I2C_ADDRESS<<1, DataPtr, Size, 100);
        if (HAL_Status != HAL_OK)
        {
            Status = IO_FAILURE;
        }
    }
    return Status;
}

测试代码

uint8_t RxData;
uint8_t ID;

Stm32f767zi_I2C_Read(REG_WHO_AM_I,1,&ID);
Stm32f767zi_I2C_Write(REG_SAMPLE_RATE_DIVIDER,1,&ID);
Stm32f767zi_I2C_Read(REG_SAMPLE_RATE_DIVIDER,1,&RxData);

已排查项

  • 确认SAMPLE_RATE_DIVIDER寄存器为读写属性
  • 拆分HAL_I2C_Master_Transmit为两次单字节传输,无效
  • UART验证写入数据指针正常
  • 所有HAL调用返回HAL_OK,设备应答正常

核心疑问

为何I2C读功能正常,但无法写入寄存器?是否设备被锁定写入?

参考单字节写入时序

MPU6050单字节写入时序1
MPU6050单字节写入时序2


解决建议

1. 检查MPU6050是否处于休眠状态

MPU6050上电默认进入休眠模式,此时大部分寄存器无法正常写入。必须先写入PWR_MGMT_1寄存器(地址0x6B),将SLEEP位(第0位)置0唤醒设备:

uint8_t wakeup_cmd = 0x00;
Stm32f767zi_I2C_Write(0x6B, 1, &wakeup_cmd);
HAL_Delay(100); // 等待设备完成唤醒

2. 替换写入函数为HAL_I2C_Mem_Write

手动拼接地址和数据的方式容易出现时序匹配问题,HAL库提供的HAL_I2C_Mem_Write专门针对“设备地址+寄存器地址+数据”的I2C写入场景,更贴合MPU6050的时序要求:

static IOStatus_t Stm32f767zi_I2C_Write(uint8_t Address,uint32_t Size,uint8_t* DataPtr)
{
    IOStatus_t Status = IO_SUCCESS;
    HAL_StatusTypeDef HAL_Status;

    // 使用HAL专用内存写入函数,指定寄存器地址为8位
    HAL_Status = HAL_I2C_Mem_Write(&hi2c2, MPU6050_I2C_ADDRESS<<1, Address, I2C_MEMADD_SIZE_8BIT, DataPtr, Size, 100);

    if (HAL_Status != HAL_OK)
    {
        Status = IO_FAILURE;
    }
    return Status;
}

3. 确认I2C地址与硬件匹配

MPU6050的I2C地址由AD0引脚电平决定:

  • AD0接GND:7位地址为0x68,左移1位后为0xD0
  • AD0接VCC:7位地址为0x69,左移1位后为0xD2
    确保代码中MPU6050_I2C_ADDRESS的定义与硬件连接一致。

4. 排查硬件问题

  • 检查SDA/SCL引脚的上拉电阻(推荐4.7kΩ)是否存在、焊接正常
  • 确认MPU6050供电电压为3.3V,电源纹波是否过大
  • 排查SDA/SCL引脚是否有虚焊、短路情况

内容的提问来源于stack exchange,提问作者Hugo Pontes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 17:34:56