你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32实例-待机唤醒实验

[复制链接]
STMCU小助手 发布时间:2022-6-7 10:02
    本文我们来学**STM32的待机唤醒功能。要实现的功能是:系统运行时 D1 指示灯闪烁,5 秒后进入待机模式,D1 指示灯熄灭,同时串口 printf输出相关提示信息,可通过 K_UP 按键实现唤醒。学习本内容可以参考《STM32F10x中文参考手册》-4 电源控制器(PWR)章节。
/ ^4 X) B6 X0 p& V
STM32 低功耗模式介绍
    很多单片机具有低功耗模式,比如 MSP430、STM8L等。默认情况下,系统复位或上电复位后,微控制器进入运行模式。在运行模式下,HCLK 为 CPU 提供时钟,并执行程序代码。当 CPU 不需继续运行(例如等待外部事件)时,可以利用多种低功耗模式来节省功耗。用户需要根据最低电源消耗、最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。
    当然在运行模式下,也可以通过如下方式降低功耗:
(1)降低系统时钟速度
(2)不使用 APBx 和 AHB 外设时,将对应的外设时钟关闭
    STM32 提供了 3 种低功耗模式,以达到不同层次的降低功耗的目的,这三
种模式如下:
(1)睡眠模式( CM3 内核停止工作,外设仍在运行)
(2)停止模式(所有时钟都停止)
(3)待机模式( 1.8 V 内核电源关闭)
    这三种模式所需的功耗是逐级递减,也就是说待机模式功耗是最低的。三种低功耗模式汇总表如下图所示:

) y6 N! |+ `7 ]
) i: t( L& C  w" @' a! ?" d4 I
    我们仅对 STM32 的待机模式进行介绍,其他 2 种模式可以参考《STM32F10x 中文参考手册》-4电源控制器(PWR)章节,里面有详细的介绍。
(1)待机模式
    在睡眠模式中,仅关闭了内核时钟,内核停止运行,但其片上外设, CM3 核心的外设全都照常运行。在停止模式中,进一步关闭了其它所有的时钟,于是所有的外设都停止了工作,但由于其 1.8V 区域的部分电源没有关闭,还保留了内核的寄存器、内存的信息,所以从停止模式唤醒,并重新开启时钟后,还可以从上次停止处继续执行代码。在待机模式中, 它除了关闭所有的时钟, 还把 1.8V 区域的电源也完全关闭了,也就是说,从待机模式唤醒后,由于没有之前代码的运行记录,只能对芯片复位,重新检测 BOOT 条件,从头开始执行程序。
    那么我们如何进入待机模式呢?其实很简单,只要按下图所示待机模式进入与退出步骤的步骤执行就可以了。

7 \4 b5 R. T% V/ s6 U

+ ?1 D1 S% e6 q
    上图还列出了退出待机模式的操作,当检测到外部复位(NRST 引脚)、
IWDG 复位、 WKUP 引脚上升沿、 RTC 闹钟事件的上升沿时,微控制器退出待机模式。本文我们是通过 WKUP 引脚(PA0)上升沿来退出待机模式,当然也可以直接通过芯片复位管脚 NRST退出。
    从待机模式唤醒后,除了电源控制/状态寄存器(PWR_CSR),所有的寄存器豆被复位,程序将按照复位(启动引脚采样、复位向量已获取等)后的方式重新执行。电源控制/状态寄存器(PWR_CSR)将会指示内核由待机状态退出。
    在进入待机模式后,除了复位引脚以及被设置为防侵入或校准输出时的
TAMPER (PC13)引脚和被使能的唤醒引脚( WK_UP 脚(PA0)),其他的 IO 引脚都将处于高阻态。
    由于篇幅限制,本文并没有对待机模式相关寄存器进行介绍,大家可以参考《STM32F10x 中文参考手册》-4 电源控制器(PWR)章节,里面有详细的讲解。如果看不懂的可以暂时放下,因为我们使用的是库函数开发。
4 _9 y. E) J+ t; s) W. s$ w* U# H5 f& W
待机模式配置步骤
    接下来我们介绍下如何使用库函数进入和退出待机模式。这个也是在编写程序中必须要了解的。
    具体步骤如下:(电源管理相关库函数在 stm32f10x_pwr.c和 stm32f10x_pwr.h 文件中)
(1)使能电源时钟
    因为低功耗模式是通过 STM32 电源(PWR)系统进行管理的,所以需要使能电源时钟,调用的库函数为:
  1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//使能 PWR 外设时钟
复制代码

4 q$ l' I# G7 x6 M, u
(2)设置 WK_UP 引脚为唤醒源
' P* H6 j+ v' k" f
    待机唤醒方式有很多种,我们选择 WK_UP 引脚(PA0)上升沿来退出待机模式。在库函数中,设置使能 WK_UP 用于唤醒 CPU 待机模式的函数是:
  1. PWR_WakeUpPinCmd(ENABLE);
复制代码

" D3 i: {' _" ]7 G! u8 R
    因为按键 K_UP 连接在PA0 管脚上,并且是高电平有效,这样一来就可以使用 K_UP按键来退出待机模式。
(3)进入待机模式
    进入待机模式, 首先要设置 SLEEPDEEP 位 ( 详见 《 Cortex M3 权威指南(中文)》 , chpt13 Cortex-M3 的其它特性--电源管理章节) ,接着我们通过 PWR_CR设置 PDDS 位,使得 CPU 进入深度睡眠时进入待机模式,最后执行 WFI 指令开始进入待机模式,并等待 WK_UP 中断的到来。整个操作可以通过一个库函数完成,如下:
  1. PWR_EnterSTANDBYMode();//进入待机模式
复制代码
4 h7 v3 N' ], o* \
    通常在进入待机模式前,我们会清除唤醒标志,以等待下次进入。清除唤醒标志库函数为:
  1. PWR_ClearFlag(PWR_FLAG_WU);//清除 Wake-up 标志
复制代码

) E/ w' b) E2 P" W3 e
    以上几步全部配置好后,我们就可以正常进入待机模式了,并且可以通过按键 K_UP或者复位按键唤醒。
    特别提醒下,如果学到 RTC 实时时钟实验的时候,需要进入待机模式,如果使能了 RTC 闹钟中断的时候,进入待机模式前,必须按如下操作处理:
1.禁止 RTC 中断( ALRAIE、 ALRBIE、 WUTIE、 TAMPIE 和 TSIE 等)。
2.清零对应中断标志位。
3.清除 PWR 唤醒(WUF)标志(通过设置 PWR_CR 的 CWUF 位实现)。
4.重新使能 RTC 对应中断。
5.进入低功耗模式。
    本实验使用到硬件资源如下:
(1)D1 指示灯
(2)串口 1
(3)K_UP 按键
    D1指示灯、K_UP 按键、串口 1 电路在前面章节都介绍过,这里不多说。D1指示灯用来提示系统正常运行,K_UP 按键用来唤醒待机模式,串口 1 用来输出提示信息。
    所要实现的功能是:系统运行时 D1 指示灯闪烁,5 秒后进入待机模式,D1 指示灯熄灭,同时串口 printf 输出相关提示信息,通过 K_UP 按键实现唤醒。
    程序框架如下:
(1)配置进入与退出待机模式
(2)编写主函数
    前面介绍待机模式配置步骤时,就已经讲解如何配置。下面我们打开“待机唤醒实验”工程,在 APP 工程组中可以看到添加了wkup.c文件(里面包含了待机模式驱动程序),在 StdPeriph_Driver 工程组中添加了 stm32f10x_pwr.c 库文件。电源系统管理相关操作的库函数都放在stm32f10x_pwr.c 和 stm32f10x_pwr.h 文件中,所以使用到电源系统管理就必须加入 stm32f10x_pwr.c 文件,同时还要包含对应的头文件路径。
    这里我们分析几个重要函数,其他部分程序大家可以打开工程查看。
! C- G( }/ N# ^: d- d, V$ L8 u) h# f
待机模式配置函数
    要让系统进入待机模式,我们必须对它进行配置。进入待机模式代码如下:
  1. /****************************************************************
    5 U5 z8 e& B9 M& T  d  `
  2. * 函 数 名 : Enter_Standby_Mode! B# u( h+ T" q7 d8 U. ~
  3. * 函数功能 : 进入待机模式
      U7 F+ u* X; y' M
  4. * 输 入 : 无8 _- |/ k' G* f4 }
  5. * 输 出 : 无
    . ~# B/ e/ {% w+ G" D! {% j  p( F
  6. *****************************************************************/
    / a6 k! _4 e! l+ M# A
  7. void Enter_Standby_Mode(void)( E; {/ s, W  r' @4 `
  8. {
    2 p- ~5 ?! N+ S% O
  9.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//使能 PWR 外设时钟2 N4 @5 w5 h: h. h% z) p4 }
  10.   PWR_ClearFlag(PWR_FLAG_WU);//清除 Wake-up 标志- f2 w- R( B' f. d$ v
  11.   PWR_WakeUpPinCmd(ENABLE);//使能唤醒管脚 使能或者失能唤醒管脚功能
    / B3 D* b) b( w7 S+ U' R0 b
  12.   PWR_EnterSTANDBYMode();//进入待机模式0 }1 W+ m6 M( T0 e" p
  13. }
复制代码

) S% e2 y3 _$ z: W% U$ w4 u
   该函数首先使能电源PWR时钟,然后清除唤醒标志位,并使能 WK_UP管脚为唤醒方式,最后进入待机模式。这一过程在前面步骤介绍中已经提了。
主函数
    配置待机模式后,我们就可以编写主函数,代码如下:
  1. /****************************************************************
    # S7 i+ H! P# u& g& ~& y3 G
  2. * 函 数 名 : main
    2 J- u) O3 a$ c" @- \: r5 P
  3. * 函数功能 : 主函数
    3 Q) R& \8 T. i5 s/ U* M. t
  4. * 输 入 : 无; j( J. x8 v: E) y1 e
  5. * 输 出 : 无. L1 H: U. _- t
  6. *****************************************************************/7 g- _# a& z8 M1 D8 {) j' S6 P
  7. int main()
    3 Y+ h: [( D# Z( M- l$ k
  8. {
    + w0 @- J0 V; q. o7 J# `
  9.   SysTick_Init(72);
    , U; x( |& N: p' h2 A
  10.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断优先级分组 分2 组2 t) S0 d6 P! J9 ^* o
  11.   LED_Init();% S5 f0 J, r! q% t& Q; a
  12.   USART1_Init(9600);
    9 d" f  m/ M% q
  13.   while(1)
    & s0 S0 T- J- F% E' a# ~. T4 T# m$ C
  14.   {
    2 J" n; U& j/ e7 E1 E
  15.     printf("time: 5\r\n");
    " U- W' l9 J  Q0 d/ `; f
  16.     led1=0;: z& k9 B3 {3 N. j+ J9 ~" Z, E: v
  17.     delay_ms(1000); //隔 1 秒显示计数7 g/ \. I. k: ]8 h* M$ F/ Z7 x
  18.     printf("time: 4\r\n");$ ~# E& p. n+ i, C+ z
  19.     led1=1;/ F( r, Q( n3 ]! b0 P' z  `
  20.     delay_ms(1000);4 s! C' B* R+ b: M& L
  21.     printf("time: 3\r\n");: f/ Z4 L2 G" c7 f( H6 u0 c  V+ P
  22.     led1=0;
    2 b8 @4 Y6 p) M7 m& V* j/ U
  23.     delay_ms(1000);
    - J9 m  p/ T0 g& E
  24.     printf("time: 2\r\n");
    5 L2 N' z0 j/ O' w, ~/ U; P
  25.     led1=1;; v" R6 a# L' \' d7 U) G( {, c
  26.     delay_ms(1000);
    : `* |+ W- z+ |7 J8 e1 _
  27.     printf("time: 1\r\n");
    2 b# G! w8 J3 j. k. N" [
  28.     led1=0;, Z! }4 n2 ^. u4 Q0 h3 [
  29.     delay_ms(1000);) Y; D$ D* r2 H: ]
  30.     printf("进入系统待机模式\r\n");
    $ F+ c0 b- a- M& Q) B/ ?8 r+ ]" R* ]
  31.     Enter_Standby_Mode();
    4 K0 U* O) T7 ?, ^/ w, f: U! L
  32.   }
    7 b1 T: P* S5 l" e2 U! H3 v
  33. }
复制代码
% t" z$ ?  Z/ [) K" I
    主函数实现的功能很简单,首先调用之前编写好的硬件初始化函数,包括
9 u/ r% L  L3 x4 \
SysTick 系统时钟,中断分组,LED 初始化等。然后进入 while 循环,每间隔一秒让 printf 输出一个信息,同时指示灯状态发生变化。倒计 5 秒钟后,调用函数 Enter_Standby_Mode进入待机模式,此时指示灯熄灭。
    将工程程序编译后下载到开发板内,可以看到系统运行时 D1 指示灯不断闪烁,5 秒钟后进入待机模式,此时 D1 指示灯熄灭。当按下 K_UP 按键或复位按键时,待机模式被唤醒,系统重新运行,同时串口打印提示信息。如果想在串口调试助手上看到输出信息,可以打开“串口调试助手”,首先勾选下标号 1 DTR 框,然后再取消勾选。这是因为此串口助手启动时会把系统复位住, 通过 DTR 状态切换下即可。然后设置好波特率等参数后,串口助手上即会收到 printf发送过来的信息。(串口助手上先勾选下标号1 DTR框,然后再取消勾选)如下图所示。

: C: F1 k8 T0 i1 M$ W% P
: K- O9 c! ?$ D# I5 o3 j: L1 G
    实验说明:下载待机唤醒实验程序后,若使用普中 ARM 仿真器下载其他的程序会出现报警,这是因为处于低功耗模式时,所有外设时钟都已关闭,所以需要在下载程序前先复位下系统。

/ v% ~" u/ `4 k& p4 H7 K
赞 收藏 评论0 发布时间:2022-6-7 10:02

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版