CH585M+SX1262+W25Q16 低功耗代码实现的核心函数详细讲解
要想深入理解CH585M精细化PMU+RAM保留实现的核心函数,下面我会从「函数原型、参数解析、底层原理、调用示例、注意事项」五个维度,拆解每个核心函数的作用和落地方式,所有内容均贴合CH58x官方SDK,可直接对应到之前的低功耗工程代码中。
一、核心函数总览
CH585M实现PMU+RAM精细化配置的核心函数共3个(含1个关键辅助属性),它们是低功耗配置的“基石”:
| 函数/属性 | 核心作用 | 所属头文件 |
|---|---|---|
PMU_RAMRetentionConfig | 配置休眠时保留的RAM大小(8K/16K/32K) | CH58x_pmu.h |
PMU_PowerDownModeCfg | 配置PMU下电模式+唤醒源 | CH58x_pmu.h |
RCC_PeriphClockCmd | 禁用/启用外设时钟(配置PMU的前提) | CH58x_rcc.h |
__attribute__((section(".ram_retention"))) | 标记变量放入保留RAM段 | 编译器属性(无头文件) |
二、核心函数1:PMU_RAMRetentionConfig(RAM保留大小配置)
这是实现“精细化RAM保留”的核心函数,决定休眠时哪些RAM区域保持供电(不丢失数据)。
1. 函数原型(CH58x SDK原生定义)
voidPMU_RAMRetentionConfig(PMU_RAM_RETENTION_T size);2. 参数解析
入参size是枚举类型PMU_RAM_RETENTION_T,SDK中定义如下(可直接用):
typedefenum{PMU_RAM_RETENTION_8K=0x00,// 仅保留低8K RAM(0x20000000~0x20001FFF)PMU_RAM_RETENTION_16K=0x01,// 保留低16K RAM(0x20000000~0x20003FFF)PMU_RAM_RETENTION_32K=0x02// 保留全部32K RAM(0x20000000~0x20007FFF)}PMU_RAM_RETENTION_T;3. 底层原理
CH585M的RAM物理地址范围是0x20000000 ~ 0x20007FFF(共32K),该函数通过配置PMU_RAM_RETENTION寄存器,控制不同RAM区块的供电:
- 选8K:仅
0x20000000~0x20001FFF供电,其余24K断电(功耗最低); - 选32K:全部RAM供电(功耗最高,但保留所有数据)。
4. 调用示例(结合低功耗场景)
#include"CH58x_pmu.h"// 配置仅保留8K RAM(最常用的低功耗配置)voidConfig_8K_RAM_Retention(void){// 核心调用:指定8K保留PMU_RAMRetentionConfig(PMU_RAM_RETENTION_8K);}// 配置保留16K RAM(中等数据保留需求)voidConfig_16K_RAM_Retention(void){PMU_RAMRetentionConfig(PMU_RAM_RETENTION_16K);}5. 关键注意事项
- 必须在进入下电模式前调用:该配置需在
PMU_PowerDownModeCfg之前执行,否则不生效; - 保留大小匹配实际需求:非必要不选32K,每多保留8K RAM,休眠功耗增加≈0.15μA;
- 仅Retention模式生效:该函数仅对
PMU_PWR_DOWN_MODE_RETENTION模式有效,Deep模式下无论怎么配置,RAM都会全部断电。
三、核心函数2:PMU_PowerDownModeCfg(PMU下电模式+唤醒源配置)
这是控制CH585M“休眠深度”和“唤醒方式”的核心函数,与RAM保留配置配合使用。
1. 函数原型(CH58x SDK原生定义)
voidPMU_PowerDownModeCfg(PMU_PWR_DOWN_MODE_T mode,uint32_twakeup_src);2. 参数解析
参数1:mode(PMU下电模式,枚举类型)
typedefenum{PMU_PWR_DOWN_MODE_RETENTION=0x00,// 保留模式(配合RAM保留,数据不丢)PMU_PWR_DOWN_MODE_DEEP=0x01// 深度下电模式(无RAM保留,极致功耗)}PMU_PWR_DOWN_MODE_T;- Retention模式:CPU断电,但保留指定大小的RAM+RTC供电,唤醒后直接运行(无需重新初始化);
- Deep模式:CPU+所有RAM断电,仅RTC供电,唤醒后需重新初始化所有外设(功耗最低)。
参数2:wakeup_src(唤醒源,位掩码组合)
SDK定义的唤醒源宏(可多个组合,用|分隔):
| 唤醒源宏 | 作用 | 功耗影响 |
|---|---|---|
PMU_PWR_DOWN_WAKEUP_RTC(0x01) | RTC周期性唤醒 | 无 |
PMU_PWR_DOWN_WAKEUP_GPIO(0x02) | GPIO外部中断唤醒 | +≈0.1μA |
PMU_PWR_DOWN_WAKEUP_UART(0x04) | UART数据唤醒 | +≈0.2μA |
PMU_PWR_DOWN_WAKEUP_TIM(0x08) | 定时器唤醒 | +≈0.15μA |
3. 底层原理
该函数配置PMU_PWR_DOWN_CTRL寄存器:
mode参数控制电源域开关:Retention模式保留RAM/外设电源域,Deep模式关闭所有电源域(仅RTC除外);wakeup_src参数启用对应唤醒源的中断检测电路,只有检测到唤醒信号,才会恢复CPU供电。
4. 调用示例(分场景)
场景1:8K RAM保留 + RTC唤醒(最常用)
#include"CH58x_pmu.h"voidConfig_LowPower_RTC_Wakeup(void){// 第一步:配置8K RAM保留PMU_RAMRetentionConfig(PMU_RAM_RETENTION_8K);// 第二步:配置Retention模式 + 仅RTC唤醒PMU_PowerDownModeCfg(PMU_PWR_DOWN_MODE_RETENTION,PMU_PWR_DOWN_WAKEUP_RTC);}场景2:Deep模式 + RTC+GPIO双唤醒(极致功耗+紧急响应)
voidConfig_DeepSleep_Double_Wakeup(void){// Deep模式无需配置RAM保留(自动断电)PMU_PowerDownModeCfg(PMU_PWR_DOWN_MODE_DEEP,PMU_PWR_DOWN_WAKEUP_RTC|PMU_PWR_DOWN_WAKEUP_GPIO);}5. 关键注意事项
- 唤醒源越少,功耗越低:仅保留必要的唤醒源(如仅RTC),多余唤醒源会增加漏电;
- Deep模式唤醒后需重新初始化:因为RAM全部断电,之前的外设配置、全局变量都会丢失,需重新调用
System_Init(); - 必须先禁用外设时钟:若未禁用SPI/UART等时钟,即使配置了Deep模式,功耗也会比理论值高0.5~1μA。
四、核心函数3:RCC_PeriphClockCmd(时钟管控,前提函数)
该函数看似和PMU无关,但却是低功耗配置“生效”的前提——未禁用的外设时钟会持续消耗电流,让RAM/PMU的优化白费。
1. 函数原型(CH58x SDK原生定义)
voidRCC_PeriphClockCmd(uint32_tperiph,FunctionalState state);2. 参数解析
参数1:periph(外设枚举,可批量指定)
SDK定义的外设宏(常用):
| 外设宏 | 对应外设 | 漏时钟功耗 |
|---|---|---|
RCC_PERIPH_SPI0 | SPI0总线 | ≈0.2μA |
RCC_PERIPH_UART0 | UART0串口 | ≈0.15μA |
RCC_PERIPH_TIM0 | 定时器0 | ≈0.1μA |
RCC_PERIPH_ALL | 所有外设 | 批量禁用 |
RCC_PERIPH_RTC | RTC时钟 | 必须保留 |
参数2:state(使能/禁用)
typedefenum{DISABLE=0,// 禁用外设时钟ENABLE=1// 启用外设时钟}FunctionalState;3. 底层原理
CH585M的每个外设都有独立的时钟门控寄存器,该函数通过配置RCC_PERIPH_CLK_EN寄存器,关闭/打开外设的时钟输入:
- 禁用时钟后,外设停止工作,无电流消耗;
- 仅保留RTC时钟(低功耗核心),其余全部禁用。
4. 调用示例(低功耗必用)
#include"CH58x_rcc.h"voidDisable_All_Useless_Clock(void){// 第一步:禁用所有外设时钟(批量操作,最便捷)RCC_PeriphClockCmd(RCC_PERIPH_ALL,DISABLE);// 第二步:仅重新启用RTC时钟(下电模式依赖RTC)RCC_PeriphClockCmd(RCC_PERIPH_RTC,ENABLE);}5. 关键注意事项
- 批量禁用+精准启用:先用
RCC_PERIPH_ALL禁用所有,再单独启用需要的(如RTC),避免漏禁; - 唤醒后按需启用:唤醒后仅启用当前任务需要的外设时钟(如SPI0),完成任务后立即禁用;
- GPIO时钟无需单独禁:GPIO时钟随
RCC_PERIPH_ALL一起禁用,无需额外操作。
五、关键辅助:保留RAM段属性(attribute((section(“.ram_retention”))))
这不是函数,但却是“RAM保留配置生效”的关键——即使配置了8K RAM保留,若变量未放入指定段,休眠后数据仍会丢失。
1. 作用
告诉编译器:将该变量存储到“RAM保留段”(0x20000000~0x20001FFF),休眠时该区域供电,数据不丢失。
2. 使用方法
// 示例1:保留单个变量(唤醒计数)__attribute__((section(".ram_retention")))uint32_twakeup_count=0;// 示例2:保留数组(LoRa接收缓存)__attribute__((section(".ram_retention")))uint8_tlora_rx_buf[64]={0};3. 底层原理
CH58x SDK的链接脚本(CH585M_FLASH.ld)中定义了.ram_retention段,地址范围恰好是8K保留RAM区:
.ram_retention : { . = ALIGN(4); *(.ram_retention) . = ALIGN(4); } > RAM AT> RAM编译器会将带该属性的变量,优先分配到这个地址段,确保休眠时不丢数据。
4. 注意事项
- 变量大小不超过保留RAM:8K保留时,所有带该属性的变量总大小不能超过8192字节(8K);
- 全局变量才需要加:局部变量存储在栈中,栈区不在保留段,无需加该属性;
- Deep模式下无效:Deep模式RAM全部断电,即使加了该属性,数据也会丢失。
六、核心函数组合使用的完整示例(可直接编译)
#include"CH58x_common.h"#include"CH58x_pmu.h"#include"CH58x_rcc.h"// 保留变量:唤醒计数(放入8K保留RAM段)__attribute__((section(".ram_retention")))uint32_twakeup_count=0;/********************************************************************* * @fn LowPower_Config * @brief 完整的精细化PMU+RAM配置:8K RAM + Retention + RTC唤醒 * @return none ********************************************************************/voidLowPower_Config(void){// 步骤1:禁用所有无用时钟(前提)RCC_PeriphClockCmd(RCC_PERIPH_ALL,DISABLE);RCC_PeriphClockCmd(RCC_PERIPH_RTC,ENABLE);// 步骤2:配置8K RAM保留PMU_RAMRetentionConfig(PMU_RAM_RETENTION_8K);// 步骤3:配置PMU模式+唤醒源PMU_PowerDownModeCfg(PMU_PWR_DOWN_MODE_RETENTION,PMU_PWR_DOWN_WAKEUP_RTC);// 验证:唤醒计数+1wakeup_count++;}// 主函数intmain(void){// 系统初始化System_Init();while(1){// 执行业务逻辑(如LoRa接收)// ...// 进入精细化低功耗LowPower_Config();}}七、核心函数使用总结
| 核心操作 | 对应函数/属性 | 关键目标 |
|---|---|---|
| 选最小RAM保留 | PMU_RAMRetentionConfig(8K) | 降低休眠功耗(0.8μA) |
| 选合适的PMU模式 | PMU_PowerDownModeCfg(Retention/RTC) | 平衡数据保留与功耗 |
| 禁用所有冗余时钟 | RCC_PeriphClockCmd(ALL, DISABLE) | 消除时钟泄漏(≈0.5μA) |
| 标记保留变量 | __attribute__((section(".ram_retention"))) | 确保数据不丢失 |
这些核心函数是CH585M低功耗优化的“骨架”,之前提供的完整工程代码,本质上是这些函数的组合与扩展——掌握了这些函数,你可以根据自己的业务场景(如是否保留数据、是否需要紧急唤醒)灵活调整低功耗配置,而不是照搬现成代码。