4. BMS主控MCU时钟与外设功耗优化

任务定义

本案例完成电池监测芯片(以TI BQ76952为参考对象)休眠模式(Sleep Mode)的寄存器配置,实现以下目标:

  1. 正确配置芯片进入休眠模式所需的寄存器位;
  2. 设置休眠唤醒源(电压比较器/通信接口);
  3. 验证配置是否生效并具备可恢复路径。

BQ76952休眠模式机制

BQ76952在休眠模式下,ADC停止转换,仅保留必要的比较器与通信监听电路。进入休眠前需通过DA_STATUS寄存器组中的SLEEP_EN位使能休眠功能,并通过SLEEP_CFG寄存器配置唤醒条件。芯片在检测到电流超过阈值或通信活动时自动唤醒。

寄存器配置实现

/*
 * bq76952_sleep_cfg.c
 * 目标:配置BQ76952进入休眠模式并设置唤醒源
 * 依赖:I2C读写函数(i2c_write_reg / i2c_read_reg)
 *       已在驱动层实现,本文件仅做寄存器配置
 */

#include <stdint.h>

/* BQ76952寄存器地址定义 */
#define REG_DA_STATUS0       0x0050  /* 休眠使能控制 */
#define REG_SLEEP_CFG        0x0061  /* 休眠配置 */
#define REG_ADCCTRL          0x0090  /* ADC控制 */

/* 寄存器位定义 */
#define SLEEP_EN_MASK        0x01    /* DA_STATUS0 bit0: 休眠使能 */
#define SLEEP_COMP_EN        0x01    /* SLEEP_CFG bit0: 电压比较器唤醒使能 */
#define SLEEP_COMM_EN        0x02    /* SLEEP_CFG bit1: 通信唤醒使能 */
#define ADC_OFF              0x00    /* ADCCTRL: 关闭ADC */

/* I2C读写函数声明(由驱动层提供) */
extern int i2c_write_reg(uint8_t dev_addr, uint16_t reg_addr, uint8_t *data, uint8_t len);
extern int i2c_read_reg(uint8_t dev_addr, uint16_t reg_addr, uint8_t *data, uint8_t len);

#define BQ76952_I2C_ADDR     0x08    /* 7位地址 */

/**
 * @brief 配置BQ76952进入休眠模式
 * @param enable_comp_wake  1: 使能电压比较器唤醒
 * @param enable_comm_wake  1: 使能通信唤醒
 * @return 0成功, -1失败
 */
int bq76952_enter_sleep(uint8_t enable_comp_wake, uint8_t enable_comm_wake)
{
    uint8_t reg_val;
    uint8_t sleep_cfg = 0;

    /* 1. 关闭ADC(进入休眠前必须停止转换) */
    reg_val = ADC_OFF;
    if (i2c_write_reg(BQ76952_I2C_ADDR, REG_ADCCTRL, &reg_val, 1) != 0)
        return -1;

    /* 2. 配置休眠唤醒源 */
    if (enable_comp_wake)
        sleep_cfg |= SLEEP_COMP_EN;
    if (enable_comm_wake)
        sleep_cfg |= SLEEP_COMM_EN;

    if (i2c_write_reg(BQ76952_I2C_ADDR, REG_SLEEP_CFG, &sleep_cfg, 1) != 0)
        return -1;

    /* 3. 使能休眠功能 */
    reg_val = SLEEP_EN_MASK;
    if (i2c_write_reg(BQ76952_I2C_ADDR, REG_DA_STATUS0, &reg_val, 1) != 0)
        return -1;

    return 0;
}

/**
 * @brief 读取当前休眠配置状态
 * @param sleep_en    输出:休眠使能状态
 * @param comp_wake   输出:比较器唤醒使能状态
 * @param comm_wake   输出:通信唤醒使能状态
 * @return 0成功, -1失败
 */
int bq76952_get_sleep_status(uint8_t *sleep_en, uint8_t *comp_wake, uint8_t *comm_wake)
{
    uint8_t status0, sleep_cfg;

    if (i2c_read_reg(BQ76952_I2C_ADDR, REG_DA_STATUS0, &status0, 1) != 0)
        return -1;
    if (i2c_read_reg(BQ76952_I2C_ADDR, REG_SLEEP_CFG, &sleep_cfg, 1) != 0)
        return -1;

    *sleep_en  = (status0 & SLEEP_EN_MASK) ? 1 : 0;
    *comp_wake = (sleep_cfg & SLEEP_COMP_EN) ? 1 : 0;
    *comm_wake = (sleep_cfg & SLEEP_COMM_EN) ? 1 : 0;

    return 0;
}

/* 使用示例 */
void example_usage(void)
{
    uint8_t sleep_en, comp_wake, comm_wake;

    /* 进入休眠:使能比较器唤醒,禁用通信唤醒 */
    if (bq76952_enter_sleep(1, 0) == 0) {
        /* 配置成功 */
    }

    /* 读取配置验证 */
    if (bq76952_get_sleep_status(&sleep_en, &comp_wake, &comm_wake) == 0) {
        /* sleep_en=1, comp_wake=1, comm_wake=0 */
    }
}

配置流程与验证

配置流程分为三步:先关闭ADC确保转换停止,再设置唤醒源(比较器或通信),最后使能休眠位。芯片在使能休眠后,若满足唤醒条件(电压变化超过阈值或收到通信请求)会自动退出休眠。

验证方法:
  1. 调用bq76952_enter_sleep(1, 0)后,读取DA_STATUS0寄存器,bit0应为1;
  2. 读取SLEEP_CFG寄存器,bit0应为1(比较器唤醒),bit1应为0(通信唤醒禁用);
  3. 测量芯片电流,休眠态电流应低于正常工作态(典型值<10μA,以数据手册为准);
  4. 施加超过阈值的电压变化,芯片应能自动唤醒并恢复ADC转换。

关键设计说明

本配置将ADC完全关闭以降低功耗,这是休眠模式的核心功耗优化手段。唤醒源配置为电压比较器时,芯片内部仅保留低功耗比较器工作,适合静态电压监测场景;若需通过I2C唤醒,则需保留通信监听电路,功耗略高。实际应用中应根据系统需求选择唤醒源,在响应速度与功耗间取得平衡。

BQ76952 休眠模式配置流程 步骤1: 关闭ADC REG_ADCCTRL = 0x00 步骤2: 配置唤醒源 REG_SLEEP_CFG 步骤3: 使能休眠 REG_DA_STATUS0 bit0=1 SLEEP_CFG 寄存器 (0x0061) bit0: COMP_EN bit1: COMM_EN COMP_EN=1: 电压比较器唤醒 | COMM_EN=1: 通信唤醒 状态转换 正常工作 休眠模式 自动唤醒 配置完成 电压变化/通信

判定标准

  • 寄存器回读值与配置值一致,即DA_STATUS0 bit0=1,SLEEP_CFG对应唤醒位正确;
  • 芯片进入休眠后电流显著下降(参考数据手册典型值);
  • 触发唤醒条件后,芯片能恢复正常通信与ADC转换。