电源管理与低功耗控制
电源管理与低功耗控制是 AD23N 平台 SDK 中负责电池电压监测、低电告警以及系统低功耗模式(pdown/soff/poff)配置与管理的子系统。它由应用层电源管理模块(app_power_mg)与电源库配置模块(lib_power_config)协同构成,为整机提供从"电量感知"到"深度休眠"的完整电源策略支撑。
Purpose and Scope
本文档覆盖 AD23N SDK 中电源管理与低功耗控制相关的完整能力:
- 应用层电源管理:低电检测(LVD 警告电压 / 固定阈值)、电池电压采样(
ADC_CH_PMU_VBAT)、低电告警消息上报(MSG_LOW_POWER)。 - 电源库配置:pdown(浅睡)/ soff(软关断)/ poff(深度断电)三大低功耗模块的使能开关,以及配套的调试与 PMU 功能开关。
- 与系统其他模块的交互:升级流程中对低功耗进入的抑制、串口调试在低功耗模式下的保持等。
以下内容属于其他页面范畴,不在本文展开:按键/触摸唤醒的外设驱动细节(见外设驱动相关页面)、ADC 采样底层实现(见 ADC 章节)、具体业务对 MSG_LOW_POWER 消息的业务响应(见应用框架章节)。
Overview
在嵌入式音频/蓝牙 SoC 方案中,电源管理通常分为两个层次:
- 电量感知层——通过 ADC 周期性采样电池电压(VBAT),结合 PMU 的 LVD(低压检测)硬件阈值,判断电池是否接近欠压点,并在连续多次采样确认后向系统投递低电告警消息,驱动上层进入省电或关机流程。
- 低功耗执行层——由电源库(power_interface)提供 pdown / soff / poff 三种降功耗模式,
lib_power_config.c中的control_*开关决定各模式是否被编译/运行进系统,同时提供大量pdebug_*调试开关用于定位低功耗进不去、唤醒异常等问题。
app_power_mg.c 是应用层唯一的电源管理入口,对外暴露三个 API:初始化(app_power_init)、周期扫描(app_power_scan)、电压读取(app_power_get_vbat);lib_power_config.c 则是电源库的行为配置中心,所有 control_* / pdebug_* / config_* 常量都以 const 变量形式存在,便于链接期裁剪与运行期调试。
Architecture
flowchart TD
subgraph sg_App["应用层 (app)"]
APP["App 主循环 / 任务"]
APM["app_power_mg<br/>(app_power_init / scan / get_vbat)"]
end
subgraph sg_Config["电源库配置 (lib_power_config)"]
LPC["lib_power_config.c<br/>control_pdown / control_soff / control_poff"]
DBG["pdebug_* 调试开关"]
PMU_SW["PMU 功能开关<br/>(reset / wakeup / rtc)"]
end
subgraph sg_Drv["底层驱动 / 硬件"]
ADC["gpadc<br/>ADC_CH_PMU_VBAT"]
LVD["PMU LVD 低压检测"]
PI["asm/power_interface.h<br/>pdown / soff / poff 执行"]
end
subgraph sg_Sys["系统服务"]
MSG["消息队列<br/>post_msg"]
UP["update 升级流程<br/>(抑制 powerdown)"]
end
APP -->|"周期调用"| APM
APM -->|"adc_get_voltage"| ADC
APM -->|"读 LVD 阈值"| LVD
APM -->|"连续 10 次低电"| MSG
MSG -->|"MSG_LOW_POWER"| APP
LPC -->|"control_* 决定"| PI
DBG -->|"打印/保持串口"| PI
PI -->|"进入/退出"| APP
UP -->|"防止升级中休眠"| PI
架构解读:app_power_mg 是电量感知的前端——它不直接操作 PMU 寄存器,而是复用 ADC 采样通道与 LVD 阈值读取接口;lib_power_config 是低功耗执行的后端开关——它以 const 变量向电源库注入各模式使能状态。两者通过消息(MSG_LOW_POWER)与电源库调用间接耦合,使得应用层无需了解 pdown/soff/poff 的寄存器细节,电源库也无需关心业务何时需要省电。升级模块则通过 REGISTER_LP_TARGET(当前被注释)声明自身在 OTA 期间禁止进入 powerdown,避免升级过程被休眠打断。
低电检测与告警机制
低电检测是电源管理的第一道防线,实现在 sdk/app/bsp/common/power_manage/app_power_mg.c 与 app_power_mg.h 中。其设计目标是在电池电压接近 LVD 欠压点之前提前告警,给应用层留出保存状态、提示用户、主动关机的窗口。
阈值策略:LVD 警告电压 vs 固定阈值
头文件通过编译期宏 LVD_WARNING_FOR_LOW_POWER 选择阈值来源:
#define LVD_WARNING_FOR_LOW_POWER 1//1:使用LVD警告电压作低电提醒 0:使用固定值作低电提醒
#if LVD_WARNING_FOR_LOW_POWER
#define LOW_POWER_VOL lvd_warning_voltage
#define LOW_POWER_LOG "Warning!!! Vbat is near to lvd!\n"
#define low_power_warning_init() lvd_warning_init()
#else
#define LOW_POWER_VOL 3300//3.3v
#define LOW_POWER_LOG "low power\n"
#define low_power_warning_init()
#endif
Source: app_power_mg.h
设计意图:固定阈值(默认 3300mV)简单直接,但不同批次电池、不同 LVD 配置下误差大;LVD 警告电压方案以 PMU 硬件 LVD 阈值为基准,自动跟随硬件配置(软件阈值 = 硬件 LVD 阈值 + 200mV),保证"先于硬件欠压触发告警",避免硬件直接断电导致数据丢失。宏化设计让开发者无需改动逻辑代码即可切换策略。
LVD 阈值读取
get_lvd_vol() 从 PMU 寄存器 P3_VLVD_CON1 的低 3 位读取电压档位,按 1800mV + sel × 100mV 计算:
#define LVD_VOL_MIN 1800
#define LVD_VOL_STEP 100
#define GET_VLVD_VOL_SEL(sel) (P33_CON_GET(P3_VLVD_CON1) & 0x7)
u32 get_lvd_vol(void)
{
return (LVD_VOL_MIN + GET_VLVD_VOL_SEL() * LVD_VOL_STEP);
}
Source: app_power_mg.c
注意代码中的 TODO: 后续移回 PMU 注释表明,该函数按规划属于 PMU 驱动层,目前临时放在应用层,属于可重构点(见"扩展点"一节)。lvd_warning_init() 将告警阈值设置为硬件 LVD 电压 + 200mV,并打印实际值与告警值,便于产线/开发调试校准。
周期扫描与去抖
app_power_scan() 采用"连续计数去抖"策略:仅当连续 10 次采样均低于阈值时才上报告警,任何一次高于阈值都会清零计数,有效滤除 ADC 噪声与负载瞬态跌落造成的误报:
void app_power_scan(void)
{
static u16 low_power_cnt = 0;
u32 vol = adc_get_voltage(ADC_CH_PMU_VBAT);
if (-1 != vol) {
vol = vol * 4;
if (vol <= LOW_POWER_VOL) {
low_power_cnt++;
if (low_power_cnt == 10) {
log_error(LOW_POWER_LOG);
post_msg(1, MSG_LOW_POWER);
}
} else {
low_power_cnt = 0;
}
}
}
Source: app_power_mg.c
关键细节:
- 电压换算:ADC 原始电压 ×4 得到真实 VBAT(分压采样比 1:4),与
app_power_get_vbat()的换算一致。 - 采样失败保护:
adc_get_voltage返回-1时跳过本次判断,避免异常采样值直接触发告警。 - 消息投递:使用
post_msg(1, MSG_LOW_POWER)将告警异步投递给系统消息队列,而非同步回调,避免在扫描上下文(通常是被动定时器/轮询)中执行重量级业务逻辑,符合 SDK 的事件驱动架构。 - 计数上限:
low_power_cnt == 10之后不再继续增长(恒等于 10),因此消息不会重复投递,除非电压回升后计数被清零再下降——这是一个隐式的"迟滞"保护。
初始化与电压读取
void app_power_init(void)
{
low_power_warning_init();
adc_add_sample_ch(ADC_CH_PMU_VBAT);
}
u32 app_power_get_vbat(void)
{
u32 vol = adc_get_voltage(ADC_CH_PMU_VBAT);
if (-1 != vol) {
vol *= 4;
}
return vol;
}
Source: app_power_mg.c
app_power_init() 在开机早期完成两件事:初始化告警阈值、把 VBAT 通道注册进 ADC 采样轮询表(adc_add_sample_ch),此后 adc_get_voltage 才有有效数据可读。app_power_get_vbat() 供上层随时查询当前电池电压(如电量显示、充电管理)。
核心流程:从采样到告警
sequenceDiagram
participant APP as App 任务
participant APM as app_power_mg
participant ADC as gpadc
participant PMU as PMU/LVD
participant MSG as 消息队列
participant BIZ as 业务模块
APP->>APM: app_power_init()
APM->>PMU: get_lvd_vol() 读 P3_VLVD_CON1
APM->>ADC: adc_add_sample_ch(ADC_CH_PMU_VBAT)
loop 周期扫描
APP->>APM: app_power_scan()
APM->>ADC: adc_get_voltage(ADC_CH_PMU_VBAT)
ADC-->>APM: 原始电压 (mV/4)
APM->>APM: vol *= 4, 与 LOW_POWER_VOL 比较
alt 连续 10 次低于阈值
APM->>MSG: post_msg(1, MSG_LOW_POWER)
MSG-->>BIZ: 低电告警事件
BIZ->>BIZ: 省电/提示/关机策略
else 电压恢复
APM->>APM: low_power_cnt = 0 (重新计数)
end
end
流程要点:整个低电检测是无阻塞的轮询式设计,不占用独立线程;采样依赖 ADC 后台轮询结果(adc_add_sample_ch 注册后由 ADC 驱动周期性刷新),app_power_scan 只需读取最近一次缓存值,因此可以安全地在任何非关键上下文中调用。告警采用 10 次连续确认 + 消息异步投递的双重保护,兼顾抗噪与解耦。
低功耗模式与电源库配置
低功耗执行层由电源库(asm/power_interface.h 定义接口,SDK 库实现)承担,sdk/app/bsp/common/config/lib_power_config.c 则通过一组 const 变量向电源库注入行为配置。这些变量不是宏,而是真正的全局常量,意味着可以在链接期裁剪(编译器优化掉未引用的分支),也便于在调试器中直接查看/修改。
三大低功耗模式
| 模式 | 使能开关 | 触发条件 | 功耗等级 | 典型用途 |
|---|---|---|---|---|
| pdown(浅睡) | control_pdown | 由 TCFG_LOWPOWER_LOWPOWER_SEL 非 0 时置 1 | 中 | 系统空闲时进入,保留 RAM,可被按键/定时器快速唤醒 |
| soff(软关断) | control_soff | 恒为 1(注释 //TCFG_LOWPOWER_SOFF) | 低 | 软件关断大部分外设电源,保留唤醒源 |
| poff(深度断电) | control_poff | 仅当 TCFG_LOWPOWER_LOWPOWER_SEL == DEEP_SLEEP_EN 时置 1 | 极低 | 深度休眠,掉电 RAM,唤醒延迟最大 |
//使能pdown模块
#if (TCFG_LOWPOWER_LOWPOWER_SEL)
const bool control_pdown = 1;
#else
const bool control_pdown = 0;
#endif
//使能soff模块
const bool control_soff = 1;//TCFG_LOWPOWER_SOFF;
//使能poff模块
#if (TCFG_LOWPOWER_LOWPOWER_SEL==DEEP_SLEEP_EN)
const bool control_poff = 1;
#else
const bool control_poff = 0;
#endif
Source: lib_power_config.c
设计意图:control_soff 恒为 1 且原宏 TCFG_LOWPOWER_SOFF 被注释,说明该平台将 soff 作为默认可用的关断手段;而 pdown/poff 的启用与项目级宏 TCFG_LOWPOWER_LOWPOWER_SEL(定义于 app_config.h 等板级配置)联动——这正是"配置驱动能力"的体现:同一份电源库代码,通过板级配置即可裁剪出不同的低功耗形态。
PMU 功能开关
配置文件还集中管理 PMU 的复位与唤醒模块开关:
//使能复位模块
const bool control_power_reset_mark = 1;
const bool control_power_soft_reset = 1;
const bool control_power_pinr_reset = 1;
const bool control_power_latch_reset = 1;
const bool control_power_reset = 1;
const bool control_power_keep_vcm_reset = 0;
//使能唤醒模块
const bool control_power_wakeup_mark = 1;
const bool control_power_wakeup = 1;
//使能低功耗寄存器检查
const bool control_power_p33_reg_check = 0;
//使能rtc模块
const bool config_rtc_enable = 0;
Source: lib_power_config.c
这些开关决定了电源库在进出低功耗时是否执行对应的寄存器操作(软件复位、引脚复位、锁存复位、唤醒标记、P33 寄存器自检等)。control_power_keep_vcm_reset 与 control_power_p33_reg_check 默认关闭,属于需要明确了解硬件特性后才开启的高级选项——默认关的开关通常意味着"打开会改变复位/检查行为,需硬件配合"。
低功耗调试开关
lib_power_config.c 顶部集中提供了低功耗调试开关,全部默认关闭以避免影响正常功耗:
//调试pdown进不去的场景,影响低功耗流程
const char debug_is_idle = 0;
//出pdown打印信息,不影响低功耗流程
const bool pdebug_pdown_info = 0;
//使能串口调试低功耗,在pdown、soff模式保持串口
const u32 pdebug_uart_lowpower = 0;
//使能串口putbyte调试pdown流程
const bool pdebug_putbyte_pdown = 0;
//使能串口putbyte调试soff流程
const bool pdebug_putbyte_soff = 0;
//使能串口pdown/poff/soff打印所有的寄存器
const bool pdebug_lp_dump_ram = 0;
//使能低功耗耗时检查:1打印执行时间 2执行时间有问题报错
const bool pdebug_reserve_time = 0;
Source: lib_power_config.c
调试开关按影响面分为三类:① 打印信息类(pdebug_pdown_info、pdebug_lp_dump_ram)——不影响流程,可常开;② 保持串口类(pdebug_uart_lowpower、pdebug_putbyte_pdown/soff)——在低功耗模式下维持 UART 输出,会显著增加功耗,仅限开发期;③ 行为影响类(debug_is_idle、pdebug_reserve_time)——会改变低功耗进入判断或耗时检查,用于排查"进不去低功耗"和"进出耗时异常"两类经典问题。文件头注释还提示 debug_is_idle 可打印蓝牙与系统的可进入低功耗时间以及处于 busy 的模块(含 usr_timer 的回调函数地址),是定位"蓝牙已进 sniff 但系统无法休眠"问题的关键工具。
与升级流程的交互
//防止升级过程进入powerdown
/* REGISTER_LP_TARGET(ota_lp_target) = { */
Source: update.c
升级模块通过 REGISTER_LP_TARGET 注册低功耗抑制目标,防止 OTA 过程中系统进入 powerdown 导致升级中断。当前该注册被注释,意味着该平台的升级流程可能依赖其他机制(如升级期间禁止空闲)来保证连续性——这是电源管理与系统服务协作的典型示例:低功耗进入不是单一模块的自治行为,而是多方协商的结果。
配置选项总览
以下表格汇总 lib_power_config.c 与 app_power_mg.h 中的可配置项(均为编译期常量或链接期 const 变量):
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
TCFG_LOWPOWER_LOWPOWER_SEL | 宏(板级) | 项目定义 | 低功耗选择:非 0 使能 pdown;DEEP_SLEEP_EN 时使能 poff |
LVD_WARNING_FOR_LOW_POWER | 宏 | 1 | 1=LVD 警告电压作低电阈值;0=固定 3300mV |
LOW_POWER_VOL | 宏 | 由策略决定 | 低电告警阈值(LVD 电压+200mV 或 3300mV) |
control_pdown | const bool | 随宏 | 使能 pdown 浅睡模式 |
control_soff | const bool | 1 | 使能 soff 软关断模式 |
control_poff | const bool | 随宏 | 使能 poff 深度断电模式 |
control_power_reset* | const bool | 1(keep_vcm 为 0) | 各类复位模块开关 |
control_power_wakeup* | const bool | 1 | 唤醒模块开关 |
control_power_p33_reg_check | const bool | 0 | 低功耗进出时 P33 寄存器自检 |
config_rtc_enable | const bool | 0 | RTC 模块使能 |
debug_is_idle | const char | 0 | 打印各模块可休眠时间与 busy 状态 |
pdebug_uart_lowpower | const u32 | 0 | 低功耗模式下保持 UART(耗电) |
pdebug_pdown_info / pdebug_putbyte_pdown/soff / pdebug_lp_dump_ram / pdebug_reserve_time | const bool | 0 | 各阶段低功耗调试打印/耗时检查 |
API 参考
电源管理模块对外暴露的接口集中在 app_power_mg.h,共 3 个函数与若干配置宏。
void app_power_init(void)
系统启动早期调用,完成电源管理模块初始化。
行为: 初始化低电告警阈值(LVD 警告电压方案下读取 PMU 档位并 +200mV),并将 VBAT 采样通道 ADC_CH_PMU_VBAT 注册到 ADC 后台采样列表。
参数: 无。
返回: 无。
调用时机: 必须在首次调用 app_power_scan() / app_power_get_vbat() 之前调用;建议放在系统初始化阶段(如 app 初始化流程中)。
Source: app_power_mg.h、app_power_mg.c
void app_power_scan(void)
周期扫描电池电压并检测低电状态。应在定时任务或主循环中周期调用(建议周期不超过 100ms 量级,保证 10 次确认延迟可接受)。
行为: 读取 VBAT 采样值(原始值 ×4 换算),若连续 10 次低于 LOW_POWER_VOL 则 post_msg(1, MSG_LOW_POWER) 投递低电告警;电压回升即清零计数。采样失败(返回 -1)时跳过本次。
参数: 无。
返回: 无。
注意事项: 函数内部使用 static u16 low_power_cnt 保存去抖计数,因此只能存在一个调用者实例,多任务并发调用会破坏去抖逻辑。
Source: app_power_mg.c
u32 app_power_get_vbat(void)
查询当前电池电压(mV)。
行为: 返回 adc_get_voltage(ADC_CH_PMU_VBAT) * 4;采样无效时返回 -1(即 0xFFFFFFFF,调用方需判负)。
参数: 无。
返回: 电池电压(单位 mV);无效采样返回 (u32)-1。
Source: app_power_mg.c
辅助函数与宏
| 名称 | 类型 | 说明 |
|---|---|---|
get_lvd_vol(void) | u32 | 读 PMU 硬件 LVD 阈值:1800 + sel*100 mV,sel 取自 P3_VLVD_CON1 低 3 位 |
lvd_warning_init(void) | static void | 初始化告警阈值 = 硬件 LVD + 200mV 并打印 |
LOW_POWER_VOL | 宏 | 低电告警阈值(策略相关,见上文) |
LOW_POWER_LOG | 宏 | 低电触发时的日志字符串 |
MSG_LOW_POWER | 系统消息 | 低电告警消息,由 post_msg(1, ...) 投递 |
使用示例
示例 1:电源管理初始化与周期扫描(标准接入方式)
以下代码展示了 app_power_mg 的标准接入模式——初始化注册采样通道,随后在系统定时扫描流程中周期调用 app_power_scan():
void app_power_init(void)
{
low_power_warning_init();
adc_add_sample_ch(ADC_CH_PMU_VBAT);
}
void app_power_scan(void)
{
static u16 low_power_cnt = 0;
u32 vol = adc_get_voltage(ADC_CH_PMU_VBAT);
if (-1 != vol) {
vol = vol * 4;
if (vol <= LOW_POWER_VOL) {
low_power_cnt++;
if (low_power_cnt == 10) {
log_error(LOW_POWER_LOG);
post_msg(1, MSG_LOW_POWER);
}
} else {
low_power_cnt = 0;
}
}
}
Source: app_power_mg.c
示例 2:读取当前电池电压
业务模块(如电量显示、充电管理)可通过 app_power_get_vbat() 获取实时电压:
u32 app_power_get_vbat(void)
{
u32 vol = adc_get_voltage(ADC_CH_PMU_VBAT);
if (-1 != vol) {
vol *= 4;
}
return vol;
}
Source: app_power_mg.c
调用方需要注意返回值 -1 的判负处理(ADC 尚未就绪或采样异常),避免将异常值当作真实电压显示。
示例 3:低功耗使能的板级配置联动
项目板级配置通过 TCFG_LOWPOWER_LOWPOWER_SEL 决定哪些低功耗模式生效,电源库配置据此生成对应的 control_* 常量:
//使能pdown模块
#if (TCFG_LOWPOWER_LOWPOWER_SEL)
const bool control_pdown = 1;
#else
const bool control_pdown = 0;
#endif
//使能poff模块
#if (TCFG_LOWPOWER_LOWPOWER_SEL==DEEP_SLEEP_EN)
const bool control_poff = 1;
#else
const bool control_poff = 0;
#endif
Source: lib_power_config.c
这是一种"零代码改动"的功耗形态裁剪方式:同一 SDK 二进制工程,仅调整板级宏即可在"仅 soff""pdown+soff""pdown+soff+poff"等形态间切换。
失败模式、边界情况与并发
低电误报与漏报
- ADC 噪声 / 负载瞬态:
app_power_scan的"连续 10 次低于阈值才告警"去抖机制是主要防线。任何一次采样高于阈值都会清零low_power_cnt,因此瞬时跌落(如射频发射瞬间、电机启动)不会触发告警。若实际产品仍存在误报,应优先检查 ADC 采样周期是否过慢导致 10 次确认时间过长,或阈值余量(+200mV)是否不足。 - 漏报风险:告警只在
low_power_cnt == 10时投递一次,之后计数恒为 10 不再重复投递。若电压在临界值附近反复震荡(低于阈值→高于阈值→低于阈值),每次回升都会清零计数,可能长时间不触发告警——这是"迟滞"设计的有意取舍:宁可少报一次,也不在临界区反复轰炸业务层。对必须保证告警的场景,业务层应在收到MSG_LOW_POWER后主动进入省电状态而非等待再次告警。
采样无效值处理
adc_get_voltage 返回 -1 表示采样无效(通道未注册、ADC 忙、首次采样未完成等)。app_power_scan 与 app_power_get_vbat 均做了判负保护,但返回值语义不同:
app_power_scan:跳过本次判断,不改变去抖计数(既不 ++ 也不清零),静默容忍偶发失败。app_power_get_vbat:将-1原样返回(以u32形式即0xFFFFFFFF),调用方必须判负,否则会把一个极大的电压值当作真实电量。这是该 API 最容易踩的坑。
并发与重入
app_power_scan使用函数级static去抖计数器,隐式要求单实例、单调用者。若多个任务同时调用,计数互相干扰会导致去抖逻辑失效。建议固定由一个定时任务/扫描循环调用。- 消息投递
post_msg(1, MSG_LOW_POWER)本身是异步的,可安全地在中断/任务上下文调用,但业务对消息的处理应放在消息循环中,避免在低优先级上下文阻塞。 lib_power_config.c中的control_*/pdebug_*为 const 全局变量,运行期不可变;修改需重新编译。若需在运行时动态切换低功耗模式,应通过电源库提供的运行时接口(power_interface),而非改动这些常量。
低功耗进不去 / 唤醒异常的典型排查
配置文件头部注释给出了官方调试路径:debug_is_idle = 1 可打印蓝牙与系统各自可进入低功耗的时间(msec),并打印当前处于 busy 的模块——若蓝牙已进入 sniff 而系统仍无法休眠,通常是 usr_timer 等模块 busy,打印会给出对应回调函数地址。pdebug_reserve_time 可检查进出低功耗耗时,定位"唤醒慢/休眠慢"。pdebug_uart_lowpower 在 pdown/soff 下保持串口,配合 pdebug_lp_dump_ram 可在休眠现场 dump 寄存器,但这些开关会显著增加功耗,严禁在量产固件中开启。
升级与休眠互斥
OTA 升级期间若系统进入 powerdown 会导致升级中断、固件损坏。update.c 中 REGISTER_LP_TARGET(ota_lp_target) 被注释,表明当前版本未通过该机制显式抑制休眠——因此升级流程必须依赖其他保证(如升级期间禁止系统进入 idle 或升级任务占用电源锁)。若在升级场景出现"升级中断/失败"问题,应优先核查升级流程是否持有电源管理锁或等效机制。
性能与运维注意事项
- 功耗:低电检测本身几乎零功耗(复用 ADC 后台采样 + 周期读取),但调试开关(
pdebug_uart_lowpower等)会在休眠态保持 UART,量产固件必须全部置 0。 - 时序:去抖的 10 次确认 × 扫描周期 = 告警最迟延迟。若扫描周期为 100ms,最迟约 1s 后告警;需更快响应(如避免硬件 LVD 直接断电)时应缩短扫描周期或降低确认次数(改动需评估抗噪)。
- 启动顺序:
app_power_init必须在扫描前调用,否则adc_get_voltage返回 -1,告警永远不触发(静默失效)。建议把初始化放在系统电源/外设初始化阶段,把扫描放在与按键扫描同级的周期任务中。 - ADC 换算一致性:
×4的换算因子隐含了硬件分压比(1:4),若硬件改版更换分压电阻,必须同步修改app_power_scan与app_power_get_vbat两处,避免"显示电压与告警电压不一致"的隐蔽 bug。
扩展点
- 阈值策略扩展:
app_power_mg.h中的LVD_WARNING_FOR_LOW_POWER宏提供两档策略(LVD 跟随 / 固定值)。若需更复杂的策略(如温度补偿、倍率曲线),可仿照现有宏体系扩展,核心改动集中在lvd_warning_init()与LOW_POWER_VOL的定义处。 get_lvd_vol()回归 PMU 驱动:源码注释TODO: 后续移回 PMU表明该函数应归属 PMU 驱动层;重构时将其迁入 PMU 模块并在应用层保持调用接口不变,即可隔离硬件细节。- 低功耗模式裁剪:通过板级宏
TCFG_LOWPOWER_LOWPOWER_SEL即可启用/禁用 pdown、poff;新增低功耗形态(如 retention 模式)只需在lib_power_config.c增加对应的control_*常量并接入电源库。 - 低电告警的业务响应:
MSG_LOW_POWER是标准消息事件,业务层可自由注册处理:音量提示、LED 指示、自动保存、限时关机等,无需改动电源管理模块本身——事件驱动设计保证了电源层与业务层的解耦。 - 低功耗抑制目标:
REGISTER_LP_TARGET机制(见update.c注释示例)可用于注册"禁止进入低功耗"的模块,适合 OTA、校准等不可中断流程。
测试情况
源码中未发现针对电源管理模块的独立单元测试文件;现有验证手段以编译期配置检查和运行时日志为主:
- 配置有效性通过条件编译保证(
TCFG_LOWPOWER_LOWPOWER_SEL与control_pdown/poff联动)。 - 运行时通过
log_error(LOW_POWER_LOG)输出低电告警,lvd_warning_init打印告警阈值与硬件 LVD 实际值,便于产线与开发校准。 - 低功耗进出时序问题依赖
pdebug_reserve_time、debug_is_idle等调试开关人工验证。
建议新增测试方向:① 阈值边界(恰好等于/略高于/略低于 LOW_POWER_VOL);② 去抖逻辑(连续 9 次低电 + 1 次回升不应告警,连续 10 次应告警且不重复);③ 采样失败(返回 -1)时的行为;④ app_power_get_vbat 判负处理。
Related Links
- app_power_mg.c — 应用层电源管理实现
- app_power_mg.h — 电源管理 API 与阈值策略定义
- lib_power_config.c — 电源库配置与低功耗调试开关
- update.c — 升级流程与低功耗抑制的交互示例
- 相关目录项:低功耗模式(pdown/soff/poff)的底层寄存器实现见"PMU 驱动"页面;
MSG_LOW_POWER消息的业务处理见"应用框架与消息机制"页面;ADC 采样实现见"ADC 采样"页面。