STM32 待机模式与唤醒实验(标准库函数版)

一、核心原理与硬件基础

1. 待机模式(Standby Mode)简介

待机模式是STM32的最低功耗模式,核心特性:

  • 功耗极低:典型电流<2μA(仅保留备份域和待机电路,SRAM/寄存器内容丢失)。
  • 唤醒后复位 :退出待机模式时,系统执行硬件复位,程序从头开始执行(需通过复位标志判断唤醒事件)。
  • 唤醒源:支持外部WKUP引脚上升沿、RTC闹钟、IWDG复位、NRST引脚复位等。

2. 关键寄存器与库函数

模块 寄存器/函数 功能
电源控制(PWR) PWR_EnterSTANDBYMode() 进入待机模式(标准库函数)
PWR_GetFlagStatus(PWR_FLAG_SB) 检查是否由待机模式唤醒(复位标志)
PWR_ClearFlag(PWR_FLAG_SB) 清除待机唤醒标志
复位控制(RCC) RCC_GetFlagStatus(RCC_FLAG_PORRST) 检查复位源(上电/待机唤醒/看门狗等)

3. 唤醒源配置(以WKUP引脚为例)

  • WKUP引脚:PA0(默认),高电平(上升沿)触发唤醒,需配置为输入模式并使能唤醒功能。
  • 其他唤醒源:RTC闹钟(需配置RTC时钟和闹钟事件)、外部中断(需配置EXTI线并允许中断唤醒)。

二、硬件设计方案

1. 核心硬件需求

  • STM32主控:任意带PWR模块的型号(如F103C8T6、F407ZGT6)。
  • 唤醒按键:轻触按键接PA0(WKUP引脚)和GND,按下时PA0变为高电平(上升沿唤醒)。
  • 状态指示:LED接PB0(唤醒后点亮,提示系统复位)。
  • 电源测量:万用表(测量待机电流,验证低功耗效果)。

2. 电路连接要点

  • WKUP按键:PA0引脚接按键一端,按键另一端接GND,PA0内部上拉(或外部10kΩ上拉至3.3V),按下时PA0=0V,释放时PA0=3.3V(上升沿唤醒)。
  • LED指示:PB0接LED阳极,LED阴极接GND(串联220Ω限流电阻),STM32输出高电平时点亮。

三、软件设计与核心代码(标准库版)

1. 系统架构

  • 初始化阶段:配置系统时钟、GPIO(WKUP引脚、LED)、PWR(使能WKUP唤醒)。
  • 主循环:检测按键(非WKUP键)触发进入待机模式,或执行其他低功耗任务。
  • 唤醒后处理:系统复位后,通过PWR_FLAG_SB标志判断是否为待机唤醒,点亮LED提示。

2. 核心代码实现

2.1 头文件与宏定义(standby_wakeup.h
c 复制代码
#ifndef __STANDBY_WAKEUP_H
#define __STANDBY_WAKEUP_H

#include "stm32f10x.h"

// 引脚定义
#define WKUP_PIN     GPIO_Pin_0
#define WKUP_PORT    GPIOA
#define LED_PIN      GPIO_Pin_0
#define LED_PORT     GPIOB

// 函数声明
void System_Init(void);          // 系统初始化(时钟、GPIO、PWR)
void Enter_Standby_Mode(void);   // 进入待机模式
void Wakeup_Handler(void);       // 唤醒后处理(复位时调用)

#endif /* __STANDBY_WAKEUP_H */
2.2 源文件实现(standby_wakeup.c
c 复制代码
#include "standby_wakeup.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"

/**
 * @brief  系统初始化(时钟、GPIO、PWR)
 * @param  无
 * @retval 无
 */
void System_Init(void) {
    // 1. 配置系统时钟(72MHz,F103C8T6)
    RCC_DeInit();                     // 复位RCC
    RCC_HSEConfig(RCC_HSE_ON);        // 使能外部高速时钟(8MHz)
    while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);  // 等待HSE就绪
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);  // PLL=8MHz×9=72MHz
    RCC_PLLCmd(ENABLE);               // 使能PLL
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);  // 等待PLL就绪
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  // 系统时钟=PLL
    RCC_HCLKConfig(RCC_SYSCLK_Div1);   // HCLK=72MHz
    RCC_PCLK1Config(RCC_HCLK_Div2);    // PCLK1=36MHz
    RCC_PCLK2Config(RCC_HCLK_Div1);    // PCLK2=72MHz
    
    // 2. 配置GPIO(WKUP引脚:PA0输入,LED:PB0推挽输出)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    // WKUP引脚(PA0):输入模式(上拉,默认高电平,按下接地)
    GPIO_InitStruct.GPIO_Pin = WKUP_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;  // 上拉输入
    GPIO_Init(WKUP_PORT, &GPIO_InitStruct);
    
    // LED引脚(PB0):推挽输出
    GPIO_InitStruct.GPIO_Pin = LED_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(LED_PORT, &GPIO_InitStruct);
    GPIO_ResetBits(LED_PORT, LED_PIN);  // 初始熄灭
    
    // 3. 配置PWR(使能WKUP唤醒功能)
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);  // 使能PWR时钟
    PWR_WakeUpPinCmd(ENABLE);  // 使能WKUP引脚唤醒(PA0)
}

/**
 * @brief  进入待机模式
 * @param  无
 * @retval 无
 */
void Enter_Standby_Mode(void) {
    // 1. 关闭外设时钟(降低功耗)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, DISABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, DISABLE);  // 仅保留PWR时钟
    
    // 2. 清除唤醒标志(避免误触发)
    PWR_ClearFlag(PWR_FLAG_WU);    // 清除唤醒标志
    PWR_ClearFlag(PWR_FLAG_SB);    // 清除待机标志
    
    // 3. 进入待机模式(标准库函数)
    PWR_EnterSTANDBYMode();  // 执行后系统进入待机,仅WKUP引脚可唤醒
}

/**
 * @brief  唤醒后处理(系统复位时调用)
 * @param  无
 * @retval 无
 */
void Wakeup_Handler(void) {
    // 检查是否由待机模式唤醒(PWR_FLAG_SB标志置位)
    if (PWR_GetFlagStatus(PWR_FLAG_SB) != RESET) {
        PWR_ClearFlag(PWR_FLAG_SB);  // 清除待机标志
        GPIO_SetBits(LED_PORT, LED_PIN);  // 点亮LED提示唤醒成功
        // 可添加其他唤醒后操作(如串口打印、状态恢复)
    }
}
2.3 主程序调用示例(main.c
c 复制代码
#include "stm32f10x.h"
#include "standby_wakeup.h"
#include "delay.h"  // 简单延时函数(需自行实现)

int main(void) {
    System_Init();       // 系统初始化
    Wakeup_Handler();    // 唤醒后处理(首次上电不执行,唤醒后执行)
    
    // 主循环:检测普通按键(PC13)触发进入待机
    while (1) {
        if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13) == Bit_RESET) {  // 按键按下(低电平)
            Delay_ms(20);  // 消抖
            if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13) == Bit_RESET) {
                Enter_Standby_Mode();  // 进入待机模式
            }
        }
        // 其他低功耗任务(如传感器采集,此处省略)
    }
}

四、关键注意事项

1. 待机模式进入步骤

  1. 关闭外设时钟:除PWR外,关闭其他外设时钟(如GPIO、UART),减少漏电流。
  2. 清除唤醒标志 :通过PWR_ClearFlag()清除PWR_FLAG_WUPWR_FLAG_SB,避免历史标志干扰。
  3. 使能唤醒源 :通过PWR_WakeUpPinCmd(ENABLE)使能WKUP引脚,或配置RTC闹钟。
  4. 调用PWR_EnterSTANDBYMode():执行后系统立即进入待机,程序停止运行。

2. 唤醒后处理

  • 系统复位 :退出待机模式时,STM32执行硬件复位,程序从main()函数重新执行。
  • 判断唤醒源 :通过PWR_GetFlagStatus(PWR_FLAG_SB)检查是否由待机唤醒(标志在复位后由硬件置位)。
  • 状态恢复:唤醒后需重新初始化外设(如时钟、GPIO),因待机模式会丢失SRAM/寄存器内容。

3. 常见问题排查

问题 原因 解决方案
无法进入待机模式 未使能PWR时钟或未调用PWR_EnterSTANDBYMode 检查RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE)是否执行
唤醒后无反应 未清除PWR_FLAG_SB或未检测标志 main()开头调用Wakeup_Handler(),检查标志
待机电流过大 外设未完全关闭(如ADC、DMA时钟) 关闭所有非必要外设时钟,确保仅PWR工作

参考代码 STM32 待机并唤醒实验(库函数) www.youwenfan.com/contentcst/133694.html

五、系统调试与优化

1. 调试步骤

阶段 操作 工具
硬件检查 测量PA0电压(按下按键时应为3.3V,释放时0V) 万用表、示波器
待机电流测试 进入待机后,测量VCC电流(应<2μA) 万用表(电流档,串联测量)
唤醒测试 按下WKUP按键,观察LED是否点亮(唤醒成功) 肉眼观察、逻辑分析仪(复位信号)

2. 低功耗优化

  • 关闭未用外设 :进入待机前,通过RCC_APBxPeriphClockCmd(DISABLE)关闭所有非必要外设时钟。
  • 降低IO功耗 :将未用GPIO配置为模拟输入模式(减少漏电流),避免浮空。
  • 使用RTC唤醒:若需定时唤醒,可配置RTC闹钟(如每小时唤醒一次),替代按键唤醒。

六、扩展应用

  • 电池供电设备:如无线传感器节点,待机时仅保留RTC运行,定时唤醒采集数据。
  • 远程唤醒:通过WKUP引脚外接无线模块(如433MHz接收器),接收指令后唤醒系统。
  • 多唤醒源融合:同时配置WKUP引脚、RTC闹钟、IWDG复位,实现多条件唤醒。

七、总结

本实验通过标准库函数 实现了STM32的待机模式与WKUP引脚唤醒,核心步骤包括PWR配置外设关闭进入待机唤醒后复位处理。待机模式适用于电池供电场景,可将系统功耗降至μA级,配合定时唤醒或外部触发,实现"休眠-工作"循环。

相关推荐
somi72 小时前
ARM-驱动-06-中断底半部 + ioctl + 原子操作与锁
arm开发·单片机·嵌入式硬件
进击的小头2 小时前
第9篇:嵌入式芯片指令集架构(ISA)详解:ARM_RISC-V等主流ISA全对比
arm开发·单片机·架构·risc-v
篮子里的玫瑰3 小时前
一个隐藏的坑:MicroLib与串口打印的关系
驱动开发·stm32·嵌入式硬件
qq_401700413 小时前
大彩串口屏DC80480M070使用以及软件配置
嵌入式硬件
LNN202215 小时前
STM32H7 + 迪文屏 DGUS 开发实战:从零构建工业级时间设置界面
stm32·单片机·嵌入式硬件
Z文的博客18 小时前
嵌入式MCU与迪文屏通信:DMA+环形FIFO+变长队列+状态机完整手册
stm32·单片机·串口·dma·中断·串口dma·嵌入式单片机
BackCatK Chen19 小时前
STM32保姆级入门教程|第7章:串口通信(USART)收发数据 + printf重定向打印调试(功能超详细+CubeIDE手把手)
stm32·串口通信·usart·stm32cubeide·printf重定向·嵌入式调试·中断接收
12.=0.19 小时前
【stm32_5】Systick嘀嗒定时器、解析时钟源、分析时钟树、应用Systick设计延时
c语言·stm32·单片机·嵌入式硬件
达不溜的日记20 小时前
CAN总线网络传输层CanTp详解
网络·stm32·嵌入式硬件·网络协议·网络安全·信息与通信·信号处理