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

STM32F030与BQ25713 I²C寄存器读写异常问题求助

问题:BQ25713 与 STM32F030 I2C通信时寄存器读写异常

硬件与现象

  • 主控:STM32F030,开发环境STM32CubeIDE(HAL库初始化完成,编译调试无报错)
  • 外设:TI BQ25713充电芯片,I2C 8位写地址0xD6(对应7位地址0x6B)
  • 异常现象:
    • 读取ManufacturerID寄存器(地址0x2E)时,预期值为0x0040,实际得到0x2E41
    • DeviceID、ChargeCurrent等寄存器读写结果均错误
    • 仅AC_STAT寄存器的CHRG_OK位可正常识别输入状态

原代码

#define BQ25713_REG_I2C_ADDRESS 0xD6 // I2C 8位写地址(由7位地址0x6B转换)
#define BQ25713_REG_MANUFACTURER_ID 0x2E // MANUFACTURER ID寄存器地址

checkBitsAndControlLEDs(BQ25713_REG_MANUFACTURER_ID);

uint16_t SetI2CData(uint16_t regAddress, uint16_t regValue) {
    HAL_StatusTypeDef status;
    uint8_t regValSet8[2];

    // 拆分LSB和MSB
    regValSet8[0] = regValue & 0xFF;          // LSB
    regValSet8[1] = (regValue >> 8) & 0xFF;   // MSB

    // 检查设备是否就绪
    status = HAL_I2C_IsDeviceReady(&hi2c1, BQ25713_REG_I2C_ADDRESS, 3, HAL_MAX_DELAY);
    if (status != HAL_OK) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
        HAL_Delay(300);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
    }

    // 写入LSB
    status = HAL_I2C_Mem_Write(&hi2c1, BQ25713_REG_I2C_ADDRESS, regAddress, I2C_MEMADD_SIZE_16BIT, &regValSet8[0], 1, HAL_MAX_DELAY);
    if (status != HAL_OK) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
        HAL_Delay(300);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
    }

    // 写入MSB
    status = HAL_I2C_Mem_Write(&hi2c1, BQ25713_REG_I2C_ADDRESS, regAddress + 1, I2C_MEMADD_SIZE_16BIT, &regValSet8[1], 1, HAL_MAX_DELAY);
    if (status != HAL_OK) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
        HAL_Delay(300);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
    }

    return 0;
}

uint16_t ReadI2CData(uint16_t regAddress) {

    uint8_t readData[2];
    HAL_StatusTypeDef status;

    // 检查设备是否就绪
    status = HAL_I2C_IsDeviceReady(&hi2c1, BQ25713_REG_I2C_ADDRESS, 3, HAL_MAX_DELAY);
    if (status != HAL_OK) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
        HAL_Delay(300);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    }

    // 读取寄存器数据
    status = HAL_I2C_Mem_Read(&hi2c1, BQ25713_REG_I2C_ADDRESS | 0x01, regAddress, I2C_MEMADD_SIZE_16BIT, readData, 2, HAL_MAX_DELAY);
    if (status != HAL_OK) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
        HAL_Delay(10000);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
        HAL_Delay(10000);
    }

    // 组合LSB和MSB
    uint16_t readI2CData = (readData[0] << 8) | readData[1];
    return readI2CData;
}

// 通过LED显示寄存器位状态
void checkBitsAndControlLEDs(uint16_t check_register) {
    uint16_t regData = ReadI2CData(check_register);

    for (int i = 15; i >= 0; i--) {
        if ((regData >> i) & 1) {
            // 位为1时点亮绿色LED(PA2)
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
            HAL_Delay(2500);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
        } else {
            // 位为0时点亮红色LED(PA1)
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
            HAL_Delay(2500);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
        }
        HAL_Delay(1000);  // 间隔1秒
    }
}

问题分析与修复方案

1. 寄存器地址长度错误(核心问题)

BQ25713的寄存器地址为8位宽度,但代码中使用I2C_MEMADD_SIZE_16BIT,导致STM32向芯片发送16位地址(如把0x2E当成0x002E发送),完全偏离目标寄存器。

  • 修复:将所有HAL_I2C_Mem_Read/HAL_I2C_Mem_Write中的地址长度参数改为I2C_MEMADD_SIZE_8BIT。

2. I2C读地址手动修改错误

HAL_I2C_Mem_Read函数会自动根据传入的8位写地址生成对应的读地址(写地址+1),无需手动对地址执行|0x01操作,否则会发送错误的设备地址。

  • 修复:HAL_I2C_Mem_Read的设备地址参数直接用BQ25713_REG_I2C_ADDRESS,去掉|0x01。

3. 数据字节序处理错误

BQ25713采用小端格式存储16位寄存器数据:LSB(低字节)在前,MSB(高字节)在后。原代码中组合数据时将LSB左移8位,导致字节序反转。

  • 修复:读取后的数据组合逻辑改为:
    uint16_t readI2CData = (readData[1] << 8) | readData[0];
    

4. 字写入方式错误

BQ25713支持单次字写入(2字节连续传输),无需分两次写入LSB和MSB,原代码中手动偏移寄存器地址regAddress +1会导致写入错误的寄存器位置。

  • 修复:合并两次HAL_I2C_Mem_Write为一次,直接写入2字节数据:
    status = HAL_I2C_Mem_Write(&hi2c1, BQ25713_REG_I2C_ADDRESS, regAddress, I2C_MEMADD_SIZE_8BIT, regValSet8, 2, HAL_MAX_DELAY);
    

修正后的关键代码片段

修正后的ReadI2CData函数

uint16_t ReadI2CData(uint16_t regAddress) {
    uint8_t readData[2];
    HAL_StatusTypeDef status;

    status = HAL_I2C_IsDeviceReady(&hi2c1, BQ25713_REG_I2C_ADDRESS, 3, HAL_MAX_DELAY);
    if (status != HAL_OK) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
        HAL_Delay(300);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    }

    // 修正地址长度为8位,移除手动修改的读地址
    status = HAL_I2C_Mem_Read(&hi2c1, BQ25713_REG_I2C_ADDRESS, regAddress, I2C_MEMADD_SIZE_8BIT, readData, 2, HAL_MAX_DELAY);
    if (status != HAL_OK) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
        HAL_Delay(10000);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
        HAL_Delay(10000);
    }

    // 修正字节序组合逻辑
    uint16_t readI2CData = (readData[1] << 8) | readData[0];
    return readI2CData;
}

修正后的SetI2CData函数

uint16_t SetI2CData(uint16_t regAddress, uint16_t regValue) {
    HAL_StatusTypeDef status;
    uint8_t regValSet8[2];

    regValSet8[0] = regValue & 0xFF;          // LSB
    regValSet8[1] = (regValue >> 8) & 0xFF;   // MSB

    status = HAL_I2C_IsDeviceReady(&hi2c1, BQ25713_REG_I2C_ADDRESS, 3, HAL_MAX_DELAY);
    if (status != HAL_OK) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
        HAL_Delay(300);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
    }

    // 修正地址长度为8位,单次写入2字节数据
    status = HAL_I2C_Mem_Write(&hi2c1, BQ25713_REG_I2C_ADDRESS, regAddress, I2C_MEMADD_SIZE_8BIT, regValSet8, 2, HAL_MAX_DELAY);
    if (status != HAL_OK) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
        HAL_Delay(300);
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 19:19:49