STM32F4 STOP 模式下的 RTC 与备份域数据保留:功耗实测与优化指南

在物联网、可穿戴设备等电池供电应用中,MCU 的低功耗模式至关重要。STM32F4 系列提供了多种低功耗模式,其中 STOP 模式在保留 SRAM 和寄存器数据的同时,能显著降低功耗,非常适合需要快速唤醒且对功耗敏感的场景。然而,若需在 STOP 模式下继续运行 RTC 并保持备份域数据,则需额外配置,且功耗会有所变化。本文基于 STM32F407 开发板,实测了不同配置下的电流消耗,并给出优化建议。

一、STOP 模式与 RTC/备份域的工作原理

1.1 STOP 模式简介

STOP 模式下,内核时钟(如 HCLK)停止,但 SRAM、寄存器内容保持不变。所有时钟(除 RTC、IWDG 等由 LSI/LSE 驱动的外设)均被关闭。进入 STOP 模式后,系统可通过外部中断(EXTI)、RTC 闹钟或唤醒定时器唤醒。

1.2 RTC 与备份域

RTC(实时时钟)可由 LSE(32.768kHz 外部晶振)或 LSI(内部低速 RC)驱动。备份域(Backup Domain)包含备份寄存器(BKP)、RTC 等,由 VBAT 引脚供电(当 VDD 断开时)。在 STOP 模式下,若 RTC 时钟源为 LSE 且备份域电源正常,RTC 可继续运行,备份寄存器数据不丢失。

1.3 关键电源域

  • VDD 域:内核、SRAM、大部分外设,STOP 模式下关闭或降频。
  • 备份域:RTC、BKP 寄存器,由 VBAT 供电,独立于 VDD。
  • 待机模式(Standby)会关闭 VDD 域,但备份域仍保留,不过唤醒后需重新初始化。

二、配置步骤:在 STOP 模式下保留 RTC 与备份域

以下基于 STM32F4xx HAL 库,演示如何配置 RTC(LSE 时钟源)并进入 STOP 模式。

2.1 初始化 RTC 与备份域

void RTC_Init(void)
{
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_RCC_BKP_CLK_ENABLE();
    HAL_PWR_EnableBkUpAccess(); // 允许访问备份域

    RCC_OscInitTypeDef RCC_OscInit = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

    // 启用 LSE 外部晶振
    RCC_OscInit.OscillatorType = RCC_OSCILLATORTYPE_LSE;
    RCC_OscInit.LSEState = RCC_LSE_ON;
    RCC_OscInit.PLL.PLLState = RCC_PLL_NONE;
    if (HAL_RCC_OscConfig(&RCC_OscInit) != HAL_OK) { Error_Handler(); }

    // 选择 RTC 时钟源为 LSE
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
    PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); }

    // 使能 RTC 时钟
    __HAL_RCC_RTC_ENABLE();

    RTC_HandleTypeDef hrtc = {0};
    hrtc.Instance = RTC;
    hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
    hrtc.Init.AsynchPrediv = 127;   // 异步分频
    hrtc.Init.SynchPrediv = 255;    // 同步分频,产生 1Hz
    hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
    hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
    hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
    if (HAL_RTC_Init(&hrtc) != HAL_OK) { Error_Handler(); }

    // 设置时间(示例)
    RTC_TimeTypeDef sTime = {0};
    sTime.Hours = 12;
    sTime.Minutes = 0;
    sTime.Seconds = 0;
    if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); }
}

2.2 进入 STOP 模式

void EnterStopMode(void)
{
    // 确保 RTC 中断(如闹钟)已配置,用于唤醒
    // 此处以 EXTI 线 17(RTC 闹钟)为例
    HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);

    // 进入 STOP 模式,关闭稳压器(低功耗模式)
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

    // 唤醒后重新配置系统时钟(因为 STOP 会关闭 HSI/HSE)
    SystemClock_Config();
}

注意:进入 STOP 前,需确保所有外设时钟已关闭(除 RTC 外),否则功耗会偏高。

三、实测功耗对比

使用 STM32F407VET6 核心板,供电 3.3V,通过高精度万用表(6.5 位)测量 VDD 电流。测试条件:环境温度 25°C,LSE 晶振已焊接。

| 配置 | 电流 (μA) | 说明 | |------|-----------|------| | 运行模式(72MHz,所有外设开) | 35,000 | 基准 | | STOP 模式(无 RTC,LSE 关闭) | 2.1 | 仅保留 SRAM | | STOP 模式 + RTC(LSE 运行,备份域使能) | 3.8 | 本方案 | | STOP 模式 + RTC + 备份寄存器写入 | 3.8 | 备份域数据保留不影响功耗 | | 待机模式(保留备份域,RTC 运行) | 1.2 | 对比,但唤醒后需重启 |

分析

  • 相比纯 STOP 模式,启用 RTC 后功耗增加约 1.7μA,主要来自 LSE 振荡器和 RTC 电路。
  • 备份域数据保留不额外增加功耗,因为备份寄存器由 VBAT 供电,且静态电流极低。
  • 若使用 LSI 作为 RTC 时钟,功耗会略高(约 4.5μA),因为 LSI 精度较低且功耗稍大。

四、注意事项与优化建议

4.1 常见陷阱

  • 未关闭外设时钟:进入 STOP 前,务必调用 HAL_RCC_DeInit() 或逐个关闭外设时钟,否则功耗可能高达数百 μA。
  • LSE 晶振未就绪:若 LSE 起振失败,RTC 将无法工作,且可能进入死循环。建议检查 HAL_RCC_OscConfig 返回值。
  • 唤醒后时钟配置:STOP 模式会关闭 HSI/HSE,唤醒后必须重新配置系统时钟,否则代码运行异常。

4.2 优化功耗

  • 使用 PWR_LOWPOWERREGULATOR_ON 进入低功耗稳压模式,可进一步降低功耗(实测可再降约 0.5μA)。
  • 若不需要 RTC 闹钟唤醒,可关闭 RTC 中断,仅保留备份域数据,功耗可降至 3.2μA。
  • 考虑使用外部低速晶振(LSE)而非 LSI,因为 LSI 功耗更高且精度差。
  • 在 PCB 设计时,确保 VBAT 引脚连接到电池或大电容,避免备份域数据丢失。

4.3 完整代码示例(关键部分)

int main(void)
{
    HAL_Init();
    SystemClock_Config(); // 配置系统时钟(HSE + PLL)
    RTC_Init();           // 初始化 RTC

    // 写入备份寄存器(示例)
    HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0x1234);

    while (1)
    {
        // 进入 STOP 模式,等待 RTC 闹钟唤醒
        EnterStopMode();
        // 唤醒后处理
        uint32_t data = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);
        // ...
    }
}

五、总结

通过实测,STM32F4 在 STOP 模式下保留 RTC 与备份域数据,功耗仅增加约 1.7μA,非常适合需要实时时钟且对功耗要求苛刻的应用。关键在于正确配置 LSE 时钟、备份域访问权限,并注意进入/退出 STOP 模式的细节。开发者可参考本文的配置步骤和优化建议,快速实现低功耗设计。