ESP32-P4 备用电池供电方案

[English]

ESP32-P4 集成 RTC (Real-Time Clock,实时时钟) 功能,包含备用电源输入端 (VBAT),32.768KHz 外部晶振输入,电源切换控制等,可在主电源断开后保持计时准确。

警告

ESP-IDF 尚未完全支持 VBAT 方案,当前方案仅供测试。请按照如下过程在 master 分支上修改 ESP-IDF 驱动。

支持以下特性

  • 支持主电源掉电保持计时功能,掉电后由备用电池(VBAT)供电

  • 支持睡眠/唤醒时 PMU (Power management unit,电源管理单元)自动切换电源

  • 支持备用电池电压检测,阈值报警

  • 支持备用电池充电,当 VDDA 存在时,可通过内部电阻为 VBAT 上的备用电池充电

../_images/p4_vbat_frame.png

ESP32-P4 备用电池连接示意图

电池连接与电路保护

ESP32-P4 备用电池的连接非常简单。VBAT 引脚内置充电保护电路,因此无需外部电阻与二极管,有效降低了在备用电池通路上增加元件带来的有害风险。

../_images/p4_power_switch.png

ESP32-P4 电池切换控制框图

备用电池的选择

  • 低自放电率: 电池应具有出色的抗漏电性

  • 充放电性能: 较高充放电次数的电池可以提升产品使用寿命

  • 放电电流: VBAT 供电功耗较低(几uA),因此大部分电池放电能力均可满足

  • 充电电流: 支持 VDDA 给 VBAT 上备用电池充电。软件可配置充电限流电阻 1KΩ ~ 9KΩ

警告

严禁接入 3.6V 的可充电电池,由于 3.6V 的可充电电池在满电情况下的电压能够达到 4V 左右,而 VBAT 引脚的输入电压范围为 2.3V ~ 3.6V,可能会导致 VBAT 引脚损坏。

电池上的去耦电容

在电路设计中,用户通常会为每一个供电引脚添加一个去耦电容。但当 VBAT 作为备用电源输入时,电容上的泄露将导致电池寿命明显缩短,此外,电池具有良好的电容特性,因此无需外部去耦电容。

备注

D1 与 R1 为 ESD 保护器件,Rx 为充电保护电阻,使充电电流限制在 1 mA 以下,保护电路满足 UL 认证测试要求。

电源切换

VBAT 与 VDDA 的电源选择由 PMU 在睡眠与唤醒时自动控制或手动选择。用户需要提前配置寄存器。当芯片处于 sleep 状态时可配置 VDDA 或 VBAT 作为电源输入。

  • PMU_HP_SLEEP_VDDBAT_MODE: 选择 HP_SLEEP 状态时的供电电源。0:VDDA 供电、1:VBAT 供电、2:自动选择

  • PMU_VDDBAT_SW_UPDATE: 置为1 使 PMU_VDDBAT_CFG_REG 寄存器配置生效

  • PMU_LP_ANA_WAIT_TARGET: 设置唤醒过程中的 delay 时间。时间长度应该大于 VDDA 外部电源的上电稳定时间

备注

当前 ESP-IDF 尚未完整支持 PMU 驱动。若您需要测试 VBAT 功能,请按照下述测试过程在 ESP-IDF 中添加必要的代码。

测试过程如下:

  1. components/esp_hw_support/port/esp32p4/pmu_sleep.c 中添加必要的头文件

#include "soc/pmu_reg.h"
#include "soc/lp_analog_peri_reg.h"
#include "soc/lp_gpio_struct.h"
#include "esp_private/regi2c_ctrl.h"
#include "soc/lp_analog_peri_reg.h"
#include "soc/lp_analog_peri_struct.h"
#include "esp_private/regi2c_ctrl.h"
#include "soc/regi2c_bias.h"
  1. components/esp_hw_support/port/esp32p4/pmu_sleep.cpmu_sleep_start 函数中的 pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev); 上方添加如下代码:

方式1:VDDA 与 VBAT 自动切换方式:

#define VBAT_MODE_VDDA 0
#define VBAT_MODE_VBAT 1
#define VBAT_MODE_AUTO 2

REG_SET_FIELD(PMU_HP_SLEEP_LP_DIG_POWER_REG, PMU_HP_SLEEP_VDDBAT_MODE, VBAT_MODE_AUTO);
REG_SET_BIT(PMU_VDDBAT_CFG_REG, PMU_VDDBAT_SW_UPDATE);
while(VBAT_MODE_AUTO != REG_GET_FIELD(PMU_VDDBAT_CFG_REG, PMU_ANA_VDDBAT_MODE));

方式2:VDDA 与 VBAT 手动设置:

#define VBAT_MODE_VDDA 0
#define VBAT_MODE_VBAT 1
#define VBAT_MODE_AUTO 2

REG_SET_FIELD(PMU_HP_SLEEP_LP_DIG_POWER_REG, PMU_HP_SLEEP_VDDBAT_MODE, VBAT_MODE_VDDA);
REG_SET_BIT(PMU_VDDBAT_CFG_REG, PMU_VDDBAT_SW_UPDATE);
while(VBAT_MODE_VDDA != REG_GET_FIELD(PMU_VDDBAT_CFG_REG, PMU_ANA_VDDBAT_MODE));
REG_SET_FIELD(PMU_LP_SLEEP_LP_DIG_POWER_REG, PMU_LP_SLEEP_VDDBAT_MODE, VBAT_MODE_VBAT);
REG_SET_FIELD(PMU_SLP_WAKEUP_CNTL5_REG, PMU_LP_ANA_WAIT_TARGET, 0xFF);

备注

经过测试,deep sleep 下的 VBAT 平均电流为 7 uA,light sleep 下的 VBAT 平均电流为 21 uA

备用电池运行时间

以 CR2032 电池 (225 mAh)为例,在 deep sleep 下的理论待机时间为 3.669 年。

欠压检测器 & BOD filter

ESP32-P4 的欠压检测器支持检测 VDDA 与 VBAT 的电压,在电压快速下落至预设阈值以下触发信号,并进行相应的处理。

阈值配置与电压关系:

阈值配置

电压

0

2.52v

1

2.57v

2

2.63v

3

2.68v

4

2.74v

5

2.78v

6

2.83v

7

2.89v

新建测试工程,并添加如下代码检测欠压标志位:

REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFL_VDDA, 6);                                                                        // Vdda 比较器电压阈值设置 2.83
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFH_VDDA, 7);                                                                        // Vdda 比较器电压阈值设置 2.89
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFL_VBAT, 6);                                                                        // Vbat 比较器电压阈值设置 2.83
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFH_VBAT, 7);                                                                        // Vbat 比较器电压阈值设置 2.89

REG_SET_FIELD(LP_ANALOG_PERI_VDDBAT_CHARGE_CNTL_REG, LP_ANALOG_PERI_VDDBAT_CHARGE_UNDERVOLTAGE_TARGET, 20);                    // 设置bod filter的时间阈值,单位20MHz cycle
REG_SET_FIELD(LP_ANALOG_PERI_VDDBAT_CHARGE_CNTL_REG, LP_ANALOG_PERI_VDDBAT_CHARGE_UPVOLTAGE_TARGET, 10);                       // 设置bod filter的时间阈值,单位20MHz cycle
REG_SET_BIT(LP_ANALOG_PERI_VDDBAT_CHARGE_CNTL_REG, LP_ANALOG_PERI_VDDBAT_CHARGE_CNT_CLR);
esp_rom_delay_us(30);
REG_CLR_BIT(LP_ANALOG_PERI_VDDBAT_CHARGE_CNTL_REG, LP_ANALOG_PERI_VDDBAT_CHARGE_CNT_CLR);

while (1)
{
    printf("value:%lx\n", REG_READ(LP_ANALOG_PERI_VDD_SOURCE_CNTL_REG));
    REG_WRITE(LP_ANALOG_PERI_VDD_SOURCE_CNTL_REG, 0X30020000);                                                                 // 清空VBAT欠压标志位
    REG_WRITE(LP_ANALOG_PERI_VDD_SOURCE_CNTL_REG, 0X30040000);                                                                 // 清空VDDA欠压标志位
    vTaskDelay(500 / portTICK_PERIOD_MS);
}

电池充电电路

当选择可充电电池作为 VBAT 电源输入时,芯片支持检测电池电压,并在低于设定阈值通过 VDDA 反向给 VBAT 端电池充电。

充电检测阈值与电压关系:

阈值配置

电压

0

2.52v

1

2.57v

2

2.63v

3

2.68v

4

2.74v

5

2.78v

6

2.83v

7

2.89v

新建测试工程,并添加如下代码检测欠压标志位:

REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFL_VDDA, 6);                                                                        // Vdda 比较器电压阈值设置 2.83
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFH_VDDA, 7);                                                                        // Vdda 比较器电压阈值设置 2.89
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFL_VBAT, 6);                                                                        // Vbat 比较器电压阈值设置 2.83
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFH_VBAT, 7);                                                                        // Vbat 比较器电压阈值设置 2.89

REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFL_VBAT_CHARGER, 6);                                                                // 充电检测比较器的阈值设置,应高于 brownout 报警电压 2.83
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_DREFH_VBAT_CHARGER, 7);                                                                // 充电检测比较器的阈值设置,应高于 brownout 报警电压
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_OR_FORCE_PU_VBAT_CHARGER, 1);                                                             // vbat_charger 比较器强制上电

REG_SET_FIELD(LP_ANALOG_PERI_VDDBAT_CHARGE_CNTL_REG, LP_ANALOG_PERI_VDDBAT_CHARGE_UNDERVOLTAGE_TARGET, 20);                    // 设置bod filter的时间阈值,单位20MHz cycle
REG_SET_FIELD(LP_ANALOG_PERI_VDDBAT_CHARGE_CNTL_REG, LP_ANALOG_PERI_VDDBAT_CHARGE_UPVOLTAGE_TARGET,    10);                    // 设置bod filter的时间阈值,单位20MHz cycle
REG_SET_BIT(LP_ANALOG_PERI_VDDBAT_CHARGE_CNTL_REG, LP_ANALOG_PERI_VDDBAT_CHARGE_CNT_CLR);
esp_rom_delay_us(30);
REG_CLR_BIT(LP_ANALOG_PERI_VDDBAT_CHARGE_CNTL_REG, LP_ANALOG_PERI_VDDBAT_CHARGE_CNT_CLR);

while(1)
{
    printf("value:%lx\n", REG_GET_BIT(LP_ANALOG_PERI_VDDBAT_CHARGE_CNTL_REG, LP_ANALOG_PERI_VDDBAT_CHARGE_UNDERVOLTAGE_FLAG)); // 获取 VBAT 管脚充电标志信号
    vTaskDelay(500 / portTICK_PERIOD_MS);
}

VBAT 供电场景下的外设支持功能

RTC TIMER

在进入休眠状态切换 VBAT 供电后,VDDA 下电后 RTC TIMER 正常计数,再次重启后时间显示正常。测试代码如下:

time_t now;
char strftime_buf[64];
struct tm timeinfo;
time(&now);
localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
printf( "The current date/time is: %s\n", strftime_buf);

const gpio_config_t config = {
    .pin_bit_mask = BIT(GPIO_NUM_0),
    .mode = GPIO_MODE_INPUT,
};

ESP_ERROR_CHECK(gpio_config(&config));
esp_deep_sleep_enable_gpio_wakeup(BIT(GPIO_NUM_0), 0);

esp_deep_sleep_start();

备注

您需要按照上述 电源切换章节 在 ESP-IDF 中添加电源切换代码,同时,测试过程在 VDDA 下电后等待了一段时间后重新上电,并使用 GPIO0 唤醒 ESP32-P4,对比休眠前后时间变化。

LP GPIO/ADC/UART 外设

请参考 ESP-IDF 中 examples/system/ulp/lp_core 的测试驱动进行测试,当前 GPIO/ADC/UART 的测试已支持 ESP32-P4。