基于极海APM32F402的RTC定时唤醒STOP模式实现方案

2026-05-28 17:39:42/ By Admin

  芯片低功耗模式概述

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

         1 (4)

           2 (1)

  睡眠模式(SLEEP Mode)

  睡眠模式通过关闭内核时钟使内核停止运行,但片上外设和内核外设仍保持工作。该模式可通过WFI(等待中断)或WFE(等待事件)两种方式进入,相应的唤醒方式也由进入方式决定。

  在APM32F402中,调用PMU_EnterSleepMode函数并传入参数PMU_SLEEPENTRY_WFI或PMU_SLEEPENTRY_WFE即可进入睡眠模式,分别对应中断和事件唤醒机制。

         3 (1)

  停止模式(STOP Mode)

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

  通过调用PMU_EnterSTOPMode函数,传入PMU_REGULATOR_ON或PMU_REGULATOR_LOWPOWER以及PMU_STOP_ENTRY_WFI或PMU_STOP_ENTRY_WFE参数,即可配置并进入停止模式。

         4

           5 (1)

  待机模式(STANDBY Mode)

  待机模式彻底关闭了所有时钟及1.2V区域的电源,唤醒后系统无先前运行记录,需复位并重新检测boot条件后从头开始执行程序。其唤醒方式包括:

  WKUP(PA0)引脚上升沿

  RTC闹钟事件

  NRST引脚复位

  IWDG(独立看门狗)复位

         6 (1)

  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闹钟定时唤醒停止模式的功能。

           7



icon_up
close_white