5.21 PWR 使用说明
本章说明 N32H49x 标准外设库中 PWR 驱动的文件组成与 30 个公开函数,以及 PVD、SLEEP、STOP、STANDBY 四个示例。电源管理单元负责电压监测、唤醒源使能与低功耗模式切换;进入 SLEEP、STOP、STANDBY 的条件、唤醒后时钟状态与备份域访问规则请配合用户手册的“电源管理(PWR)”章节阅读。
5.21.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32h49x_std_periph_driver/inc/n32h49x_pwr.h |
定义 PVD 阈值、唤醒引脚、标志位等取值,声明 30 个公开函数 |
firmware/n32h49x_std_periph_driver/src/n32h49x_pwr.c |
实现上述 30 个函数:电压检测、唤醒配置、低功耗模式进入、标志与复位、备份域控制 |
projects/n32h49x_EVAL/examples/PWR/ |
PWR 示例根目录,含 PVD、SLEEP、STOP、STANDBY 4 个示例 |
projects/n32h49x_EVAL/examples/PWR/PVD/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32h49x_EVAL/bsp/ |
该示例引用的公共板级文件:串口日志与延时函数 |
5.21.2 API 参考
以下 30 个公开函数按 n32h49x_pwr.h 的声明顺序分为 8 组;每个条目给出功能摘要与 n32h49x_pwr.c 中该函数正上方的注释原文。
基础与备份域
PWR_DeInit、PWR_BackupAccessEnable
PVD 电压监测
PWR_PvdEnable、PWR_PVDLevelConfig、PWR_PVDSourceConfig、PWR_PVDINPinSelect
唤醒引脚与外设
PWR_WakeUpPinEnable、PWR_WakeUpPinPolarity、PWR_WakeUpPeriphEnable
低功耗模式
PWR_EnterSLEEPMode、PWR_EnterSTOPMode、PWR_EnterSTANDBYMode
标志与复位
PWR_GetFlagStatus、PWR_ClearFlag、PWR_EnableIWDGReset
BKR 与备份 SRAM
PWR_ConfigBKROutput、PWR_EnableBKPSRAMRetainInStandbyMode、PWR_EnableBKPSRAMRetainInVbatMode
LSE 时钟安全系统
PWR_EnableLSENoiseMitigation、PWR_EnableLSECSSCrystalInt、PWR_ConfigLSECSSBypassHighLimit、PWR_EnableLSECSSRTCsourceSwitch、PWR_GetLSECSSFlagStatus、PWR_ClearLSECSSFlag
LCO 与 NRST
PWR_ConfigLco、PWR_EnableLCO、PWR_EnableNRSTOut、PWR_ConfigNRSTDigitalFilterWidth、PWR_EnableNRSTDigitalFilter、PWR_EnableNRSTAnalogFilter
void PWR_DeInit(void)将 PWR 外设寄存器恢复为默认复位值。
name PWR_DeInit.
fun Deinitializes the PWR peripheral registers to their default reset values.
param none
return none
void PWR_BackupAccessEnable(FunctionalState Cmd)使能或禁止对 RTC 与备份寄存器的访问。
name PWR_BackupAccessEnable.
fun Enables or disables access to the RTC and backup registers.
param Cmd:
- ENABLE
- DISABLE
return none
void PWR_PvdEnable(FunctionalState Cmd)使能或禁止电源电压检测器(PVD)。
name PWR_PvdEnable.
fun Enables or disables the Power Voltage Detector(PVD).
param Cmd:
- ENABLE
- DISABLE
return none
void PWR_PVDLevelConfig(uint32_t level)配置电源电压检测器(PVD)的电压阈值。
name PWR_PVDLevelConfig.
fun Configures the voltage threshold detected by the Power Voltage Detector(PVD).
param level (The input parameters must be the following values):
- PWR_PVD_LEVEL_2V18 PVD level is 2.18V
- PWR_PVD_LEVEL_2V28 PVD level is 2.28V
- PWR_PVD_LEVEL_2V38 PVD level is 2.38V
- PWR_PVD_LEVEL_2V48 PVD level is 2.48V
- PWR_PVD_LEVEL_2V58 PVD level is 2.58V
- PWR_PVD_LEVEL_2V68 PVD level is 2.68V
- PWR_PVD_LEVEL_2V78 PVD level is 2.78V
- PWR_PVD_LEVEL_2V88 PVD level is 2.88V
- PWR_PVD_LEVEL_1V78 PVD level is 1.78V
- PWR_PVD_LEVEL_1V88 PVD level is 1.88V
- PWR_PVD_LEVEL_1V98 PVD level is 1.98V
- PWR_PVD_LEVEL_2V08 PVD level is 2.08V
- PWR_PVD_LEVEL_3V28 PVD level is 3.28V
- PWR_PVD_LEVEL_3V38 PVD level is 3.38V
- PWR_PVD_LEVEL_3V48 PVD level is 3.48V
- PWR_PVD_LEVEL_3V58 PVD level is 3.58V
return none
void PWR_PVDSourceConfig(uint32_t PVD_source)选择 PVD 的检测来源。
name PWR_PVDSourceConfig.
fun PVD Source selection.
param PVD_source (The input parameters must be the following values):
- PWR_PVD_VDD
- PWR_PVD_PVDIN
return none
note none
void PWR_PVDINPinSelect(PVD_IN_SEL PVD_pin)选择 PVD_IN 引脚。
name PWR_PVDINPinSelect.
fun PVD_IN pin selection.
param PVD_pin (The input parameters must be the following values):
- PVD_IN_PA10
- PVD_IN_PB7
return none
note none
void PWR_WakeUpPinEnable(uint32_t pin, FunctionalState Cmd)使能唤醒引脚功能。
name PWR_WakeUpPinEnable.
fun Enables the Wakeup Pin functionality.
param pin (The input parameters must be the following values):
- WAKEUP_PIN0EN WKUP0(PE6)
- WAKEUP_PIN1EN WKUP1(PA0)
- WAKEUP_PIN2EN WKUP2(PC13)
- WAKEUP_PIN3EN WKUP3(PA2)
- WAKEUP_PIN4EN WKUP4(PC5)
- WAKEUP_PIN5EN WKUP5(PD2)
- WAKEUP_PIN6EN WKUP6(PD3)
param Cmd:
- ENABLE
- DISABLE
return none
void PWR_WakeUpPinPolarity(uint32_t pin, WAKEUP_PIN_POL polarity)设置唤醒引脚的极性。
name PWR_WakeUpPinPolarity.
fun Enables the Wakeup Pin polarity.
param pin (The input parameters must be the following values):
- WAKEUP_PIN0POL WKUP0(PE6)
- WAKEUP_PIN1POL WKUP1(PA0)
- WAKEUP_PIN2POL WKUP2(PC13)
- WAKEUP_PIN3POL WKUP3(PA2)
- WAKEUP_PIN4POL WKUP4(PC5)
- WAKEUP_PIN5POL WKUP5(PD2)
- WAKEUP_PIN6POL WKUP6(PD3)
param polarity (The input parameters must be the following values):
- POL_LOW
- POL_HIGH
return none
void PWR_WakeUpPeriphEnable(uint32_t periph, FunctionalState Cmd)使能唤醒外设功能。
name PWR_WakeUpPeriphEnable.
fun Enables the Wakeup periph functionality.
param periph (The input parameters must be the following values):
- WAKEUP_PERIPH0EN PERIPH0(LPTIM1 and LPTIM2)
- WAKEUP_PERIPH1EN PERIPH1(RTC and LSECSS)
param Cmd:
- ENABLE
- DISABLE
return none
void PWR_EnterSLEEPMode(PWR_SLEEPONEXIT_STATUS SLEEPONEXIT, uint8_t PWR_SLEEPEntry)进入 SLEEP 模式。
name PWR_EnterSLEEPMode.
fun Enters SLEEP mode.
param status (The input parameters must be the following values):
- PWR_SLEEP_ON_EXIT
- PWR_SLEEP_NOW
param enter_mode (The input parameters must be the following values):
- PWR_SLEEPENTRY_WFI enter SLEEP mode with WFI instruction
- PWR_SLEEPENTRY_WFE enter SLEEP mode with WFE instruction
return none
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)进入 STOP 模式。
name PWR_EnterSTOPMode.
fun Enters STOP mode.
param PWR_Regulator (The input parameters must be the following values):
- PWR_REGULATOR_NORMAL STOP mode with regulator in normal mode
- PWR_REGULATOR_LOWPOWER STOP mode with regulator in low power mode
param PWR_STOPEntry (The input parameters must be the following values):
- PWR_STOPENTRY_WFI enter STOP mode with WFI instruction
- PWR_STOPENTRY_WFE enter STOP mode with WFE instruction
return none
void PWR_EnterSTANDBYMode(void)进入 STANDBY 模式。
name PWR_EnterSTANDBYMode.
fun Enters STANDBY mode.
param none
return none
FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG)检查指定的 PWR 标志是否置位。
name PWR_GetFlagStatus.
fun Checks whether the specified PWR flag is set or not.
param PWR_FLAG (specifies the flag to check):
This parameter can be one of the following values:
- PWR_FLAG_WKUP0 PE6 Wake Up flag
- PWR_FLAG_WKUP1 PA0 Wake Up flag
- PWR_FLAG_WKUP2 PC13 Wake Up flag
- PWR_FLAG_WKUP3 PA2 Wake Up flag
- PWR_FLAG_WKUP4 PC5 Wake Up flag
- PWR_FLAG_WKUP5 PD2 Wake Up flag
- PWR_FLAG_WKUP6 PD3 Wake Up flag
- PWR_FLAG_WKUPP RTC or LSECSS or LPTIM1 or LPTIM2 Wake Up flag
- PWR_FLAG_STANDBY StandBy mode flag
- PWR_FLAG_PVDRDF PVD ready flag
- PWR_FLAG_PVDOUT PVD Output
- PWR_FLAG_VBAT VBAT mode flag
return The new state of PWR_FLAG
- SET
- RESET
void PWR_ClearFlag(uint32_t PWR_FLAG)清除 PWR 的挂起标志。
name PWR_ClearFlag.
fun Clears the PWR's pending flags.
param PWR_FLAG (specifies the flag to clear):
This parameter can be one of the following values:
- PWR_CLR_WKUP0 PE6 Wake Up flag
- PWR_CLR_WKUP1 PA0 Wake Up flag
- PWR_CLR_WKUP2 PC13 Wake Up flag
- PWR_CLR_WKUP3 PA2 Wake Up flag
- PWR_CLR_WKUP4 PC5 Wake Up flag
- PWR_CLR_WKUP5 PD2 Wake Up flag
- PWR_CLR_WKUP6 PD3 Wake Up flag
- PWR_CLR_WKUPP RTC or LSECSS or LPTIM1 or LPTIM2 Wake Up flag
- PWR_CLR_STANDBY StandBy mode flag
- PWR_CLR_VBAT VBAT mode flag
return none
void PWR_ConfigBKROutput(uint32_t voltage_output)选择 BKR 稳压器的输出电压档位。
name PWR_ConfigBKROutput.
fun Selects the BKR regulator output level.
param voltage_output (The input parameters must be the following values):
- PWR_BKR_OUTPUT_0_8V output 0.8V
- PWR_BKR_OUTPUT_0_9V output 0.9V
return none
note none
void PWR_EnableIWDGReset(FunctionalState Cmd)配置 IWDG 计数到 0 时是否产生复位请求。
name PWR_EnableIWDGReset.
fun Configure whether to generate a reset request when the IWDG counter reaches 0.
param Cmd:
- ENABLE
- DISABLE
return none.
void PWR_EnableBKPSRAMRetainInStandbyMode(FunctionalState Cmd)使能或禁止 STANDBY 模式下保留备份 SRAM。
name PWR_EnableBKPSRAMRetainInStandbyMode.
fun Enable or disable BKP SRAM retain in standby mode.
param Cmd:
- ENABLE
- DISABLE
return none.
void PWR_EnableBKPSRAMRetainInVbatMode(FunctionalState Cmd)使能或禁止 VBAT 模式下保留备份 SRAM。
name PWR_EnableBKPSRAMRetainInVbatMode.
fun Enable or disable BKP SRAM retain in Vbat mode.
param Cmd:
- ENABLE
- DISABLE
return none.
void PWR_EnableLSENoiseMitigation(FunctionalState Cmd)使能或禁止 LSE 噪声抑制。
name PWR_EnableLSENoiseMitigation.
fun Enable or disable LSE noise mitigation.
param Cmd:
- ENABLE
- DISABLE
return none
note Noise mitigation must be enabled after the RCC_BDCTRL.LSERD set.
void PWR_EnableLSECSSCrystalInt(FunctionalState Cmd)使能或禁止晶振模式下的 LSE 时钟安全系统中断。
name PWR_EnableLSECSSCrystalInt.
fun Enable or disable LSE Clock Safety System Interrupt in Crystal Mode.
param Cmd:
- ENABLE
- DISABLE
return none
note none
void PWR_ConfigLSECSSBypassHighLimit(uint32_t high_limit)配置旁路模式下 LSE 频率上限。
name PWR_ConfigLSECSSBypassHighLimit.
fun Configuring the LSE Frequency High Limit for Bypass Mode.
param high_limit (The input parameters must be the following values):
- PWR_HIGH_LIMIT_1M
- PWR_HIGH_LIMIT_160K
return none
note none
void PWR_EnableLSECSSRTCsourceSwitch(FunctionalState Cmd)使能或禁止 LSE 时钟失效时把 RTC 时钟源从 LSE 切换到 LSI。
name PWR_EnableLSECSSRTCsourceSwitch.
fun Enable or disable switching the RTC clock source
from LSE to LSI when the LSE clock fails.
param Cmd:
- ENABLE
- DISABLE
return none
FlagStatus PWR_GetLSECSSFlagStatus(uint32_t PWR_FLAG)检查指定的 PWR LSECSS 标志是否置位。
name PWR_GetLSECSSFlagStatus.
fun Checks whether the specified PWR LSECSS flag is set or not.
param PWR_FLAG (specifies the flag to check):
This parameter can be one of the following values:
- PWR_FLAG_LSECSSCRYF LSE Clock Security System Failure in Crystal Mode
- PWR_FLAG_LSEFHF LSE Frequency Exceeds High Limit Flag
- PWR_FLAG_LSEFLF LSE frequency below low limit flag
- PWR_FLAG_LSECSSF LSE Clock Security System Failure flag
return The new state of PWR_FLAG
- SET
- RESET
void PWR_ClearLSECSSFlag(void)清除 LSECSS 的全部标志。
name PWR_ClearLSECSSFlag.
fun Clears the LSECSS all flags.
param none
return none
note Clear the following flags:
- PWR_FLAG_LSECSSCRYF LSE Clock Security System Failure in Crystal Mode
- PWR_FLAG_LSEFHF LSE Frequency Exceeds High Limit Flag
- PWR_FLAG_LSEFLF LSE frequency below low limit flag
- PWR_FLAG_LSECSSF LSE Clock Security System Failure flag
void PWR_ConfigLco(uint32_t LCO_source)选择 LCO 低速时钟输出。
name PWR_ConfigLco.
fun LCO low-speed clock output selection.
param LCO_source (The input parameters must be the following values):
- PWR_LCO_LSI
- PWR_LCO_LSE
return none
note none
void PWR_EnableLCO(FunctionalState Cmd)使能或禁止低速时钟输出。
name PWR_EnableLCO.
fun Enable or disable low-speed clock output
param Cmd:
- ENABLE
- DISABLE
return none
void PWR_EnableNRSTOut(FunctionalState Cmd)使能或禁止 NRST 引脚的输出功能。
name PWR_EnableNRSTOut.
fun Enable or disable the output function of NRST Pin.
param Cmd:
- ENABLE
- DISABLE
return none.
void PWR_ConfigNRSTDigitalFilterWidth(uint32_t NRST_dfw)配置 NRST 数字滤波宽度。
name PWR_ConfigNRSTDigitalFilterWidth.
fun Configuring the NRST digital filter width.
param NRST_dfw:
- 0x0 ~ 0xFF
return none.
note digital filter width = sysclk * NRST_dfw.
void PWR_EnableNRSTDigitalFilter(FunctionalState Cmd)使能或禁止 NRST 数字滤波器。
name PWR_EnableNRSTDigitalFilter.
fun Enable or disable NRST digital filter
param Cmd:
- ENABLE
- DISABLE
return none
void PWR_EnableNRSTAnalogFilter(FunctionalState Cmd)使能或禁止 NRST 模拟滤波器。
name PWR_EnableNRSTAnalogFilter.
fun Enable or disable NRST Analog filter
param Cmd:
- ENABLE
- DISABLE
return none
5.21.3 Demo 示例说明
本节说明 PWR 的四个示例:PVD 通过电压检测产生中断,SLEEP、STOP、STANDBY 演示低功耗模式的进入与唤醒。
5.21.3.1 PVD 电压监测
工程目录: projects/n32h49x_EVAL/examples/PWR/PVD/
使能电源管理时钟→配置电压检测的外部中断线→设置检测阈值并使能检测→电压越限时触发中断并打印
| 项目 | 源码解读 |
|---|---|
| 功能 | 通过电源电压检测器监测供电电压; 电压越过 2.58V 阈值时在上升沿或下降沿触发中断,并在中断中打印提示信息 |
| 源码组成 | src/main.c:main、EXTI_Configuration、NVIC_Configuration;src/n32h49x_it.c:PVD_IRQHandler;inc/main.h、inc/n32h49x_it.h:头文件;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程 |
| 关键配置 | 时钟:系统时钟 240MHz; 中断:PVD 输出接到 EXTI 第 16 线,上升沿与下降沿均触发,使能 PVD 中断并配置优先级; 检测:阈值设为 2.58V |
| 程序与数据路径 | main 先使能 PWR 与 BKP 时钟,再依次配置外部中断线与 NVIC;随后设置 PVD 阈值并使能 PVD,等待 PWR_FLAG_PVDRDF 就绪;电压越限时 PVD_IRQHandler 打印信息并清除中断标志 |
| 主要 API | PWR_PVDLevelConfig、PWR_PvdEnable、PWR_GetFlagStatus |
| 验证方法 | 编译烧录后串口打印“This is a PVD demo”与“PVD is enabled!”; 把电压调到 2.58V 附近,程序进入 PVD_IRQHandler 并打印“Enter PVD interrupt” |
| 使用提示 | 硬件平台为全功能板 N32H497ZGL7_EVB V1.0; 开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1; 打印串口为 USART1(TX PA9,RX PA10,115200); PVD 在电压跨越阈值时触发中断,需外部提供可调模拟电压 |
核心代码解读与移植
示例先使能 PWR 与 BKP 时钟,再配置 PVD 输出的外部中断线与中断向量,随后设置检测阈值并使能 PVD,最后等待电压越限触发中断。
数据路径: main 使能 PWR 与 BKP 时钟 → EXTI_Configuration 配置 EXTI 第 16 线 → NVIC_Configuration 使能 PVD 中断 → main 设置阈值并使能 PVD → 电压越限时 PVD_IRQHandler 打印信息
1. 使能时钟并配置中断。 main 使能 PWR 与 BKP 时钟,然后调用中断配置函数,再设置 PVD 阈值并等待检测器就绪。
/* Enable PWR and BKP clock */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_PWR | RCC_APB1_PERIPHEN_BKP, ENABLE);
/* Configure EXTI Line to generate an interrupt on falling edge */
EXTI_Configuration();
/* NVIC configuration */
NVIC_Configuration();
/* Configure the PVD Level to 2.58V */
PWR_PVDLevelConfig(PWR_PVD_LEVEL_2V58);
/* Enable the PVD Output */
PWR_PvdEnable(ENABLE);
/* Wait PVD ready for output */
while(PWR_GetFlagStatus(PWR_FLAG_PVDRDF) == RESET);
log_info("\r\n PVD is enabled!\r\n");
PWR_PVD_LEVEL_2V58 决定触发阈值;PWR_GetFlagStatus(PWR_FLAG_PVDRDF) 就绪后再使用输出,移植时按供电电压范围选择阈值。
2. 配置外部中断线与触发边沿。 EXTI_Configuration 清除挂起位并把 PVD 输出映射到 EXTI 第 16 线,上升沿与下降沿都触发。
EXTI_InitType EXTI_InitStructure;
/* Configure EXTI Line16(PVD Output) to generate an interrupt on rising and
falling edges */
EXTI_ClrITPendBit(EXTI_LINE16);
EXTI_InitStructure.EXTI_Line = EXTI_LINE16;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitPeripheral(&EXTI_InitStructure);
EXTI_Trigger_Rising_Falling 使电压升高和降低时都能进入中断,便于观察越限状态的变化。
3. 中断服务程序打印并清标志。 PVD_IRQHandler 判断第 16 线状态,打印提示后清除挂起位。
void PVD_IRQHandler(void)
{
if (EXTI_GetStatusFlag(EXTI_LINE16) != RESET)
{
log_info("\r\n Enter PVD interrupt \r\n");
/* Clear the Key Button EXTI line pending bit */
EXTI_ClrITPendBit(EXTI_LINE16);
}
}
中断服务程序必须清除挂起位,否则会反复进入中断。
对应源码: src/main.c、src/n32h49x_it.c
5.21.3.2 SLEEP 模式
工程目录: projects/n32h49x_EVAL/examples/PWR/SLEEP/
使能电源管理时钟→配置唤醒按键及其外部中断→进入 SLEEP 模式等待唤醒→按键唤醒后退出并打印
| 项目 | 源码解读 |
|---|---|
| 功能 | 使按键 PA0 的上升沿中断把 MCU 从 SLEEP 模式唤醒; 主循环周期性进入 SLEEP 模式以降低功耗,唤醒后打印提示信息 |
| 源码组成 | src/main.c:main、delay、KeyInputExtiInit;src/n32h49x_it.c:KEY_EXTI_IRQHandler;inc/main.h、inc/n32h49x_it.h:头文件;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程 |
| 关键配置 | 时钟:系统时钟 240MHz; 引脚:唤醒按键接 PA0,配置为浮空输入并映射到 EXTI0,上升沿触发; 唤醒: PWR_EnterSLEEPMode(PWR_SLEEP_NOW, PWR_SLEEPENTRY_WFI) 以 WFI 进入 SLEEP |
| 程序与数据路径 | main 使能 PWR 时钟后调用 KeyInputExtiInit 配置按键中断;主循环延时后调用 PWR_EnterSLEEPMode 进入 SLEEP,等待按键中断唤醒;唤醒后在 KEY_EXTI_IRQHandler 中清除中断标志,主循环继续打印 |
| 主要 API | PWR_EnterSLEEPMode |
| 验证方法 | 编译烧录后串口打印“Entry SLEEP mode”; 按下 PA0 唤醒按键后打印“Exit SLEEP mode”,串接电流表可见电流先变小再变大 |
| 使用提示 | 硬件平台为全功能板 N32H497ZGL7_EVB V1.0; 开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1; 唤醒按键为 PA0; 评估功耗时应关闭打印输出 |
核心代码解读与移植
示例使能 PWR 时钟并把 PA0 配置为上升沿中断,主循环周期性进入 SLEEP 模式,靠按键中断唤醒。
数据路径: main 使能 PWR 时钟 → KeyInputExtiInit 配置 PA0 与 EXTI0 → 主循环延时后 PWR_EnterSLEEPMode 进入 SLEEP → KEY_EXTI_IRQHandler 清除标志并唤醒 → 主循环继续
1. 配置唤醒按键。 KeyInputExtiInit 使能 GPIO 时钟,把 PA0 配置为浮空输入,映射到 EXTI0 并配置上升沿触发与中断优先级。
/* Enable the GPIO Clock */
RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA, ENABLE);
/*Configure the GPIO pin as input floating*/
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);
/*Configure key EXTI Line to key input Pin*/
GPIO_ConfigEXTILine(KEY_EXTI_LINE_SOURCE, GPIOA_PORT_SOURCE, KEY_GPIO_PIN_SOURCE);
/*Configure key EXTI line*/
EXTI_InitStructure.EXTI_Line = KEY_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitPeripheral(&EXTI_InitStructure);
/*Set key input interrupt priority*/
NVIC_InitStructure.NVIC_IRQChannel = KEY_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x05;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
KEY_EXTI_LINE 等宏在 inc/main.h 中定义为 PA0 与 EXTI0,移植到其它引脚时只需修改这些宏。
2. 进入 SLEEP 并等待唤醒。 main 使能 PWR 时钟后清除中断标志,主循环延时后以 WFI 指令进入 SLEEP,唤醒后打印提示并再次进入。
/* Enable PWR Clock */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_PWR, ENABLE);
/* Initialize Key button Interrupt to wake up the low power*/
KeyInputExtiInit(KEY_INPUT_PORT, KEY_INPUT_PIN);
/* Clear the Interrupt flag */
EXTI_ClrITPendBit(KEY_EXTI_LINE);
delay(800);
while (1)
{
/* Insert a long delay */
delay(800);
log_info("Entry SLEEP mode\n");
/* Request to enter SLEEP mode*/
PWR_EnterSLEEPMode(PWR_SLEEP_NOW, PWR_SLEEPENTRY_WFI);
log_info("Exit SLEEP mode\n");
}
PWR_SLEEPENTRY_WFI 表示用 WFI 指令进入 SLEEP,任何中断都能唤醒;进入前应清除无关的挂起标志。
3. 中断服务程序清除挂起位。 KEY_EXTI_IRQHandler 在按键中断到来时判断 EXTI0 状态并清除挂起位,使 MCU 从 SLEEP 唤醒后主循环继续运行。
void KEY_EXTI_IRQHandler(void)
{
if (EXTI_GetStatusFlag(KEY_EXTI_LINE) != RESET)
{
/* Clear the Key Button EXTI line pending bit */
EXTI_ClrITPendBit(KEY_EXTI_LINE);
}
}
唤醒后必须在中断服务程序中清除挂起位,否则会反复进入中断而无法返回主循环。
对应源码: src/main.c
5.21.3.3 STOP 模式
工程目录: projects/n32h49x_EVAL/examples/PWR/STOP/
使能电源管理时钟→配置唤醒按键及其外部中断→进入 STOP 模式等待唤醒→唤醒后重新配置系统时钟→退出并打印
| 项目 | 源码解读 |
|---|---|
| 功能 | 使按键 PA0 的上升沿中断把 MCU 从 STOP 模式唤醒; 唤醒后重新配置系统时钟,主循环打印提示信息并再次进入 STOP |
| 源码组成 | src/main.c:main、delay、KeyInputExtiInit、SetSysClockToPLL;src/n32h49x_it.c:KEY_EXTI_IRQHandler;inc/main.h、inc/n32h49x_it.h:头文件;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程 |
| 关键配置 | 时钟:系统时钟 240MHz,唤醒后以 HSI 重新配置 PLL 到 160MHz; 引脚:唤醒按键接 PA0,映射到 EXTI0,上升沿触发; 唤醒: PWR_EnterSTOPMode(PWR_REGULATOR_NORMAL, PWR_STOPENTRY_WFI) 以 WFI 进入 STOP |
| 程序与数据路径 | main 使能 PWR 时钟后调用 KeyInputExtiInit 配置按键中断;主循环延时后调用 PWR_EnterSTOPMode 进入 STOP 模式;唤醒后调用 SetSysClockToPLL 以 HSI 重新配置时钟,并重新初始化日志 |
| 主要 API | PWR_EnterSTOPMode |
| 验证方法 | 编译烧录后串口打印“Entry STOP mode”; 按下 PA0 唤醒后打印“Exit STOP mode”,串接电流表可见电流先变小再变大 |
| 使用提示 | 硬件平台为全功能板 N32H497ZGL7_EVB V1.0; 开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1; 唤醒按键为 PA0,唤醒后时钟从 HSI 重新起步; 评估功耗时应关闭打印输出 |
核心代码解读与移植
示例在 SLEEP 的基础上增加唤醒后的系统时钟重配置:进入 STOP 时保留寄存器内容,唤醒后由 HSI 重新建立系统时钟。
数据路径: main 使能 PWR 时钟 → KeyInputExtiInit 配置按键中断 → PWR_EnterSTOPMode 进入 STOP → 唤醒后 SetSysClockToPLL 重配时钟 → 重新初始化日志
1. 进入 STOP 并在唤醒后重配时钟。 main 配置按键中断后进入 STOP 模式,唤醒后立即重新配置系统时钟并重新初始化日志。
/* Enable PWR clock */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_PWR,ENABLE);
/* Initialize Key button Interrupt to wakeUp stop */
KeyInputExtiInit(KEY_INPUT_PORT, KEY_INPUT_PIN);
delay(800);
while (1)
{
/* Insert a long delay */
delay(800);
log_info("Entry STOP mode\n");
delay(30);
/* Request to enter STOP mode*/
PWR_EnterSTOPMode(PWR_REGULATOR_NORMAL, PWR_STOPENTRY_WFI);
/* Configures system clock after wake-up from STOP: enable HSI, PLL and select
PLL as system clock source */
SetSysClockToPLL(RCC_PLL_SRC_HSI,160000000);
log_init();
log_info("\nExit STOP mode\n");
}
PWR_REGULATOR_NORMAL 选择稳压器正常模式;唤醒后必须重新配置时钟,否则串口等外设时钟与波特率不匹配。
2. 唤醒后重新建立系统时钟。 SetSysClockToPLL 用 HSI 作为 PLL 源,按目标频率设置 Flash 等待周期与总线分频,再使能并切换到 PLL。
FLASH_SetLatency(latency);
/* HCLK = SYSCLK */
RCC_ConfigHclk(RCC_SYSCLK_DIV1);
/* PCLK2 */
RCC_ConfigPclk2(pclk2div);
/* PCLK1 */
RCC_ConfigPclk1(pclk1div);
if(PLL_src == RCC_PLL_SRC_HSE)
{
RCC_ConfigPll(RCC_PLL_SRC_HSE,pllpre,pllmul, RCC_PLLOUT_DIV_1);
}
else
{
RCC_ConfigPll(RCC_PLL_SRC_HSI,pllpre,pllmul, RCC_PLLOUT_DIV_1);
}
/* Enable PLL */
RCC_EnablePll(ENABLE);
示例在唤醒时以 RCC_PLL_SRC_HSI 为准,因为 STOP 唤醒后 HSE 需要重新起振,用 HSI 起步更稳妥。
3. 配置唤醒按键。 KeyInputExtiInit 把 PA0 配置为浮空输入并映射到 EXTI0 上升沿中断,用于把 MCU 从 STOP 唤醒。
/* Enable the GPIO Clock */
RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA, ENABLE);
/*Configure the GPIO pin as input floating*/
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);
/*Configure key EXTI Line to key input Pin*/
GPIO_ConfigEXTILine(KEY_EXTI_LINE_SOURCE, GPIOA_PORT_SOURCE, KEY_GPIO_PIN_SOURCE);
/*Configure key EXTI line*/
EXTI_InitStructure.EXTI_Line = KEY_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitPeripheral(&EXTI_InitStructure);
/*Set key input interrupt priority*/
NVIC_InitStructure.NVIC_IRQChannel = KEY_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x05;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
GPIO_MODE_INPUT 为浮空输入;按键按下时 PA0 电平变化产生上升沿,从而触发 EXTI0 唤醒。
对应源码: src/main.c
5.21.3.4 STANDBY 模式
工程目录: projects/n32h49x_EVAL/examples/PWR/STANDBY/
使能电源管理时钟→配置唤醒引脚极性并使能→清除唤醒标志→进入 STANDBY 模式等待唤醒
| 项目 | 源码解读 |
|---|---|
| 功能 | 使能 PA0 作为唤醒引脚,MCU 进入 STANDBY 模式; 按下按键产生唤醒事件,芯片复位并从 0 地址重新执行 |
| 源码组成 | src/main.c:main、delay;inc/main.h:定义唤醒引脚相关宏;inc/n32h49x_it.h:头文件;readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程 |
| 关键配置 | 时钟:系统时钟 240MHz; 唤醒引脚: WAKEUP_PIN1(PA0)极性设为高电平有效并使能;模式:调用 PWR_EnterSTANDBYMode() 进入 STANDBY,唤醒后系统复位 |
| 程序与数据路径 | main 使能 PWR 时钟后设置唤醒引脚极性并使能唤醒功能;主循环先清除可能存在的唤醒标志,延时后调用 PWR_EnterSTANDBYMode 进入 STANDBY;按下 PA0 产生唤醒事件,芯片复位并从 0 地址重新执行 |
| 主要 API | PWR_WakeUpPinPolarity、PWR_WakeUpPinEnable、PWR_GetFlagStatus、PWR_ClearFlag、PWR_EnterSTANDBYMode |
| 验证方法 | 编译烧录后串口打印“Entry STANDBY mode”; 按下 PA0 唤醒后打印“--- Reset for STANDBY ---”,说明已复位重启 |
| 使用提示 | 硬件平台为全功能板 N32H497ZGL7_EVB V1.0; 开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1; 唤醒引脚为 PA0(WKUP1); 评估功耗时应关闭打印输出 |
核心代码解读与移植
示例使能唤醒引脚 PA0 并使能唤醒功能,主循环清除唤醒标志后进入 STANDBY 模式;唤醒事件使芯片复位重启。
数据路径: main 使能 PWR 时钟 → PWR_WakeUpPinPolarity 与 PWR_WakeUpPinEnable 配置并使能唤醒引脚 → 主循环清除唤醒标志 → PWR_EnterSTANDBYMode 进入 STANDBY → 唤醒后芯片复位重启
1. 配置并进入 STANDBY 模式。 main 使能 PWR 时钟后设置唤醒引脚极性并使能唤醒,主循环先清除唤醒标志再进入 STANDBY。
/* Enable PWR clock */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_PWR, ENABLE);
/* Enable WKUP pin */
PWR_WakeUpPinPolarity(WAKEUP_PINx_POL, POL_HIGH);
PWR_WakeUpPinEnable(WAKEUP_PINx_EN, ENABLE);
delay(800);
while (1)
{
/* Check if the Wake-Up flag is set */
if (PWR_GetFlagStatus(WAKEUP_PINx_FLAG) != RESET)
{
/* Clear Wake Up flag */
PWR_ClearFlag(WAKEUP_PINx_CLR);
}
/* Delay a long time */
delay(800);
log_info("Entry STANDBY mode\n");
/* Request to enter STANDBY mode */
PWR_EnterSTANDBYMode();
}
POL_HIGH 表示按键按下时 PA0 为高电平产生唤醒事件;进入 STANDBY 前清除唤醒标志可避免上一次的唤起床位导致误判。
2. 唤醒引脚相关宏定义。 inc/main.h 把示例使用的唤醒引脚统一为 WAKEUP_PIN1(PA0)的一组宏,便于替换引脚。
#define WAKEUP_PINx_POL WAKEUP_PIN1POL
#define WAKEUP_PINx_EN WAKEUP_PIN1EN
#define WAKEUP_PINx_FLAG PWR_FLAG_WKUP1
#define WAKEUP_PINx_CLR PWR_CLR_WKUP1
宏的四个值一一对应:极性、使能、标志与清除,移植到其它唤醒引脚时同步替换即可。
3. STANDBY 唤醒后的行为。 STANDBY 唤醒会使芯片复位,程序从 0 地址重新运行,串口最先打印复位提示,说明唤醒事件已生效。
log_init();
log_info("\r\n --- Reset for STANDBY --- \r\n");
/* Enable PWR clock */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPHEN_PWR, ENABLE);
进入 STANDBY 后除备份域外大部分电路断电,唤醒等同复位,因此不能依靠变量在唤醒后继续执行。
对应源码: src/main.c、inc/main.h
5.21.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| 进入 STOP 模式的条件 | 进入 STOP 模式需同时满足 SLEEPDEEP=1 且电源模式位为 0,并确保所有中断与唤醒事件已就绪; 条件不满足时寄存器保持原值且不进入 STOP。 |
用户手册 |
| 切换时钟源前先关闭 HSE | 从 HSE 切换到 HSI 前必须先关闭 HSEEN,并等待 HSE 就绪标志清零; 否则切换不生效。 |
用户手册 |
| STOP 唤醒后的时钟 | STOP 唤醒后系统以 HSI 作为时钟源,需重新配置 PLL 与总线分频; 本示例在唤醒后重新配置系统时钟以恢复所需频率。 |
用户手册 |
| RTC 闹钟唤醒 | 使用 RTC 闹钟从 STOP 唤醒时,需使能 EXTI 第 17 线的 RTC 闹钟中断并清除挂起位; 否则无法唤醒。 |
用户手册 |
| 唤醒引脚配置顺序 | 修改唤醒引脚极性前应先禁止该唤醒引脚,配置完成后再使能; 避免配置过程中产生误唤醒。 |
用户手册 |
| 清除待机标志 | STANDBY 与 VBAT 标志通过写 1 清除; 上电后应先读取并清除这些标志再判断唤醒来源。 |
用户手册 |
| 备份域寄存器解锁 | 写备份域寄存器前需向电源控制寄存器写入解锁口令,随后置位备份域写使能; 完成后应重新上锁。 |
用户手册 |
| 1.8V 外设上电顺序 | 1.8V 域外设应分批上电,每批不超过 4 个外设且相邻批次间隔不小于 1ms; 避免同时上电造成冲击。 |
用户手册 |