芯片低功耗模式概述
极海APM32F402微控制器提供了四种按功耗从高到低排列的工作模式:运行、睡眠、停止和待机。系统上电复位后处于运行状态,当内核无需持续工作时,开发者可根据应用需求选择合适的低功耗模式以降低能耗。这三种低功耗模式在功耗水平、唤醒时间和唤醒源上各有不同,具体特性如下表所示。


睡眠模式(SLEEP Mode)
睡眠模式通过关闭内核时钟使内核停止运行,但片上外设和内核外设仍保持工作。该模式可通过WFI(等待中断)或WFE(等待事件)两种方式进入,相应的唤醒方式也由进入方式决定。
在APM32F402中,调用PMU_EnterSleepMode函数并传入参数PMU_SLEEPENTRY_WFI或PMU_SLEEPENTRY_WFE即可进入睡眠模式,分别对应中断和事件唤醒机制。

停止模式(STOP Mode)
停止模式在睡眠模式的基础上进一步关闭了所有外设时钟,使所有外设停止工作。但由于1.2V区域电源未断开,内核寄存器和内存信息得以保留,因此唤醒后系统可从停止处继续执行代码。停止模式可通过任意外部中断(EINT)唤醒,并支持选择电压调节器的工作模式(正常或低功耗)。
通过调用PMU_EnterSTOPMode函数,传入PMU_REGULATOR_ON或PMU_REGULATOR_LOWPOWER以及PMU_STOP_ENTRY_WFI或PMU_STOP_ENTRY_WFE参数,即可配置并进入停止模式。


待机模式(STANDBY Mode)
待机模式彻底关闭了所有时钟及1.2V区域的电源,唤醒后系统无先前运行记录,需复位并重新检测boot条件后从头开始执行程序。其唤醒方式包括:
WKUP(PA0)引脚上升沿
RTC闹钟事件
NRST引脚复位
IWDG(独立看门狗)复位

RTC定时唤醒停止模式实现
由于停止模式可由任意中断唤醒,且RTC Alarm事件映射到EINT的17号线,因此可通过配置RTC闹钟来实现定时唤醒停止模式的功能。
RTC闹钟配置
本例中使用内部低速RC振荡器(LSI)作为RTC时钟源,设置5秒后触发闹钟,并将RTC Alarm与EINT 17线关联。
void RTC_Config_Init(void)
{
EINT_Config_T EINT_Configure;
// 使能BKP和PWR时钟
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU | RCM_APB1_PERIPH_BAKR);
// 允许访问备份域
PMU_EnableBackupAccess();
// 备份域复位
BAKPR_Reset();
// 使能LSI
RCM_EnableLSI();
// 等待直到LSI就绪
while(RCM_ReadStatusFlag(RCM_FLAG_LSIRDY) == RESET);
// 选择LSI作为RTC时钟源
RCM_ConfigRTCCLK(RCM_RTCCLK_LSI);
// 使能RTC时钟
RCM_EnableRTCCLK();
// 等待RTC寄存器同步及上一次写操作完成
RTC_WaitForSynchro();
RTC_WaitForLastTask();
// 使能RTC闹钟中断
RTC_EnableInterrupt(RTC_INT_ALR);
RTC_WaitForLastTask();
// 设置RTC分频值,周期为1s
RTC_ConfigPrescaler(40000);
RTC_WaitForLastTask();
// 设置RTC计数器值为0
RTC_ConfigCounter(0U);
RTC_WaitForLastTask();
// 设置RTC闹钟值为5s
RTC_ConfigAlarm(ALARM_TIME_INTERVAL);
RTC_WaitForLastTask();
// 配置EXTI 17线为中断模式,上升沿触发
EINT_Reset();
EINT_Configure.line = EINT_LINE_17;
EINT_Configure.lineCmd = ENABLE;
EINT_Configure.mode = EINT_MODE_INTERRUPT;
EINT_Configure.trigger = EINT_TRIGGER_RISING;
EINT_Config(&EINT_Configure);
// 清除标志
RTC_ClearStatusFlag(RTC_FLAG_ALR);
EINT_ClearIntFlag(EINT_LINE_17);
// 配置NVIC
NVIC_EnableIRQRequest(RTC_Alarm_IRQn, 1, 1);
}RTC闹钟中断服务函数
在中断服务函数中,检测到RTC闹钟中断后,清除相关标志位,并重新设置RTC计数器和闹钟值,以实现周期性的5秒定时。
void RTC_Alarm_IRQHandler(void)
{
if(RTC_ReadIntFlag(RTC_INT_ALR) == SET)
{
// 清除RTC闹钟和EXTI_Line17中断标志
RTC_ClearIntFlag(RTC_INT_ALR);
EINT_ClearIntFlag(EINT_LINE_17);
// 等待RTC寄存器同步及上一次写操作完成
RTC_WaitForSynchro();
RTC_WaitForLastTask();
// 重置RTC计数器和闹钟值
RTC_ConfigCounter(0U);
RTC_WaitForLastTask();
RTC_ConfigAlarm(ALARM_TIME_INTERVAL);
RTC_WaitForLastTask();
}
}进入STOP模式前的IO配置
为在停止模式下达到最低功耗,进入前将所有未使用的IO口配置为模拟输入模式,仅保留必要的唤醒引脚(如本例中用于调试的PA0)。
void GPIO_ALL_Init(void)
{
GPIO_Config_T GPIO_Configure;
// 使能所有GPIO时钟
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA | RCM_APB2_PERIPH_GPIOB |
RCM_APB2_PERIPH_GPIOC | RCM_APB2_PERIPH_GPIOD);
// 配置IO为模拟输入,保留PA0
GPIO_Configure.mode = GPIO_MODE_ANALOG;
GPIO_Configure.pin = GPIO_PIN_ALL & (~GPIO_PIN_0);
GPIO_Config(GPIOA, &GPIO_Configure);
GPIO_Configure.pin = GPIO_PIN_ALL;
GPIO_Config(GPIOB, &GPIO_Configure);
GPIO_Config(GPIOC, &GPIO_Configure);
GPIO_Config(GPIOD, &GPIO_Configure);
// 失能所有GPIO时钟
RCM_DisableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA | RCM_APB2_PERIPH_GPIOB |
RCM_APB2_PERIPH_GPIOC | RCM_APB2_PERIPH_GPIOD);
}进入停止模式函数
该函数用于配置并进入停止模式,使用低功耗调压器并采用WFI方式进入。
void System_Enter_StopMode(void)
{
// 使能PWR时钟
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);
// 清除唤醒标志
PMU_ClearStatusFlag(PMU_FLAG_WUE);
// 进入Stop模式
PMU_EnterSTOPMode(PMU_REGULATOR_LOWPOWER, PMU_STOP_ENTRY_WFI);
}主函数逻辑与验证
主函数中,系统先延时5秒以便进行程序擦除和下载,随后初始化GPIO和RTC,进入停止模式。RTC闹钟将在5秒后唤醒MCU,唤醒后需重新配置系统时钟和外设。
// RTC闹钟值宏定义
#define ALARM_TIME_INTERVAL (5U)
int main(void)
{
NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_2);
// 系统初始化
BSP_HSI64_SysclkConfig();
BSP_Systick_Init(64);
BSP_LED_Init(GPIOB, GPIO_PIN_8);
BSP_LED_Init(GPIOB, GPIO_PIN_9);
BSP_KEY2_Init(BUTTON_MODE_EXTI);
BSP_USART1_Init(115200);
printf("SYSCLKFreq = %d\r\n", RCM_ReadSYSCLKFreq());
// 延时5秒后进入停止模式
delay_ms(1000); delay_ms(1000); delay_ms(1000);
delay_ms(1000); delay_ms(1000);
printf("After a 5-second delay, enter Stop mode\r\n");
GPIO_ALL_Init();
RTC_Config_Init();
System_Enter_StopMode();
// 唤醒后重新配置时钟和外设
BSP_HSI64_SysclkConfig();
BSP_Systick_Init(64);
BSP_LED_Init(GPIOB, GPIO_PIN_8);
BSP_LED_Init(GPIOB, GPIO_PIN_9);
BSP_KEY2_Init(BUTTON_MODE_EXTI);
BSP_USART1_Init(115200);
printf("Exti Stop mode\r\n");
while (1)
{
printf("RUNNING\r\n");
delay_ms(200);
}
}通过串口工具观察输出信息,可验证系统已成功实现每5秒由RTC闹钟定时唤醒停止模式的功能。

Copyrights© Shenzhen Linkchip Co.,LTD All Rights Reserved.