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

STM32心得:低功耗待机唤醒实验

[复制链接]
STMCU小助手 发布时间:2022-11-20 15:53
主要内容:
  A3 P  b2 D: Y1) STM32低功耗模式讲解;' A) T/ E& P2 ~- Q7 ~( X+ A4 C2 X0 w, l. k
2) 寄存器和库函数配置;' y! {0 i& p; y" ]9 Q
3) 实验代码解读。* E) B7 ?' T+ l- h1 C
实验功能:针对GPIOA,引脚0,启动后系统进入待机模式,长按3秒待机唤醒,LED0和LED1闪烁,长按3秒进入待机模式,LED0和LED1灭。
8 G& c( l& o8 T- u# L
" z- Z" C# V; N  x1. 待机唤醒
5 L9 t9 q) ^' W% q* A1 r8 B1 Q7 `很多单片机有低功耗模式,STM32也不例外。在系统或者电源复位后,微控制器处于运行状态之下,HCLK为CPU提供时钟,内核执行代码。当CPU不需要继续运行时,可以利用多种低功耗模式来节省功耗,例如等待某个事件触发。7 D: z- i* q! e, b7 v$ h% ?! r
' c' [! z3 W  D% @
2. 低功耗模式:* @! I* o" k5 s4 s/ Q/ K
2.1 睡眠模式:内核停止,外设如NVIC,系统时钟Systick仍运行;  M# p$ d. Y2 D, B, L! H6 x5 N' x, z
2.2 停止模式:所有时钟都已停止。1.8V内核电源工作。PLL,HIS和HSE RC振荡器功能禁止。寄存器和SRAM内容保留;
! ]) O6 o; }& z' a$ T' l2.3 待机模式:1.8V内核电源关闭。只有备份寄存器和待机电路维持供电。寄存器和SRAM内容全部丢失。实现最低功耗。& I0 M% w% _# E( x( Z, c% n
功耗消耗排序:睡眠模式>停止模式>待机模式(功耗消耗最低)6 r  k0 W1 A4 }$ n0 E# `
2.4 运行模式下降低功耗的办法:" |- [% M' c4 j; @5 g
2.4.1 降低系统时钟;
6 i! V( L  y# K( M$ P6 @; @% f# W2.4.2 关闭APB和AHB总线上未被使用的外设时钟。
& P% e. e; A# J1 \9 k& `' u' O7 _. ^$ ?
20200518100102494.png - O+ }* H: A8 g3 g- Y1 N3 I7 {& n9 C
. d, d% z6 x3 R/ C) p( E# e
用户可根据电源消耗,最快启动时间和可用的唤醒源等条件,选择一种最佳的低功耗模式。
4 B$ C/ V( r, B: k' R: Y* Z
) e2 k" K) z% S+ Z( |2 V3. STM32的待机模式
6 A3 d4 I. c# c! P/ V% S( _* B3 q

6 V, O: ^3 Y  w) E9 Q; O% S7 t 20200518100213879.png
# D! ^$ e% s' C6 ]$ Y待机模式理想状态下,只需要2uA电流。停机模式下典型电流为20uA。$ N- j5 S: h; S+ }. y% n
. R6 T0 H* P3 y" t5 r
4. 相关寄存器
# B+ `  {2 P- R. Z, _* I4.1 PWR_CR电源控制寄存器:
' Q% W" [$ o% g+ q7 u( [& I/ C) a5 h* W0 f- v
20200518100340920.png
% L! \! L& o4 ?, w8 a. ^% ~5 z' g4 n0 a+ r' H) n
4.1.1 设置PDDS位进入深度睡眠时进入待机模式;
8 u- R  a# t. i& ~& M! ^* n' K8 n4.1.2 设置CWUF位,清除之前的WUF唤醒位。( h9 b8 f, u6 K; G
4.2 PWR_CSR电源控制/状态寄存器:) Y. q5 a4 k2 d# z. h1 @

+ e, J/ Q( b. B 20200518100440476.png ( y/ l" H# _0 ^0 ]
  L# ~8 w  a; ]2 {. o
4.1.1 设置EWUP,使能WKUP引脚用于待机模式唤醒;1 f8 R- g, Y2 G6 ?' R9 }
4.1.2 WUF唤醒标志,用来判断是否发生唤醒事件。$ `; B4 d: h9 D
% P; c9 |/ M8 t
5. 相关库函数( }6 g6 T6 Q/ ?" I, T3 U5 @: S$ ]
5.1 官方文件为stm32f10x_pwr.c / stm32f10x_pwr.h;
' J8 n9 _; Z$ P% _- H* @; b5.2 主要库函数:
3 p$ P; H8 T- i/ C) _+ h" n# w" ]2 X$ Q
  1. voidPWR_EnterSTOPMode();                           //进入停机模式
    6 Z0 W8 x$ m- P' S0 @; R; [
  2. voidPWR_EnterSTANDBYMode(void);                    //进入待机模式
    5 |" u) o- Z2 O
  3. void PWR_WakeUpPinCmd(FunctionalState NewState);   //使能Wakeup引脚唤醒( g- }3 l7 f) [, |, X6 d
  4. FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG);
    6 ?& V! R$ c8 T( F. r0 ]
  5. void PWR_ClearFlag(uint32_t PWR_FLAG);
复制代码
5 k; E" b, ~) Q5 y. i/ W2 ^5 {
6. 待机唤醒配置步骤:
* h. \4 G0 J8 G/ ?# N% ?. U) [. a) H, M6.1 使能电源时钟。因为要配置电源控制寄存器,所以必须先使能电源时钟:
! S& U* V: h! ^! {  H
5 \! G8 N9 [4 w
  1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
复制代码

% t8 y  G* B3 {6.2 设置WK_UP引脚作为唤醒源。设置PWR_CSR的EWUP位,使能WK_UP用于将CPU从待机模式唤醒:
2 T7 K& N, R: g1 K6 i* D: M! P( s' t4 ^- O4 Z. X9 M9 d) i
  1. PWR_WakeUpPinCmd(ENABLE);  //使能唤醒管脚功能
复制代码

8 L' F( \9 `% ^' N6.3 设置SLEEPDEEP位,设置PDDS位,执行WFI指令,进入待机模式:
3 n7 ^6 K/ Q! n+ n1 b- N! Q% s( u2 T. _# t5 P) Q, }* O' z( U! S
  1. void PWR_EnterSTANDBYMode(void);
复制代码

- s2 N4 l/ X  _- @4 J& F. `% i& ~7. 程序思路
2 b0 o( a7 [) W+ h8 w7.1 在待机模式下,WKUP用来唤醒。按下WKUP,就会从待机模式唤醒;
- g+ [' Z; F& V. C4 l7.2 正常情况下(没有进入低功耗模式),WKUP是可以作为正常的输入口,或者中断触发引脚来使用。
/ u0 ^& g( B# |1 [% i0 U. S5 O& i9 M
8. 相关实验代码解读# A/ ]/ K7 r8 s" Y- u5 G3 r
8.1 wkup.h头文件代码/ z& r" c- D7 H2 i2 V! o

% L* i: V1 m3 T3 E: y
  1. #ifndef __WKUP_H" t, P" s7 a* Y" [! b9 j! Q4 k; m
  2. #define __WKUP_H  
    - |, ]8 l1 P, f- q' u0 j: S: |
  3. #include "sys.h"         
    4 s' S6 I2 n- M( Z
  4. #define WKUP_KD PAin(0)        //位带操作,WKUP_KD对应GPIOA_IDR的0位//
    0 t+ _5 A. @* R" l. P
  5. //三个函数//# X" l# W. ]9 y6 b& Z* @
  6. u8 Check_WKUP(void);           //检测WKUP脚的信号,返回u8格式数据//
    + p1 v8 S; O6 E+ @. \7 l
  7. void WKUP_Init(void);          //PA0 WKUP唤醒初始化//3 M: z0 _3 L0 @, O: c3 r6 x* ^
  8. void Sys_Enter_Standby(void);  //系统进入待机模式//
    5 {' [9 `, ?5 p2 c: A3 ]
  9. #endif
复制代码

5 F# k% Q) Q% z7 P( C! J- O5 B- W8.2 wkup.c文件代码解读1 O4 v' H2 C5 D5 z. W
9 t; ~1 n1 p3 Z) w) o' I
  1. #include "wkup.h"
    ' u! Z% d$ G2 p1 }; I$ i8 c9 l
  2. #include "led.h"
    3 F" n0 U3 K5 H" ?$ q& N2 B7 ]
  3. #include "delay.h"
    . V9 I: C, D/ L) c
  4. //待机唤醒配置函数//  * m. W. a: R+ w7 X+ n7 O
  5. void Sys_Standby(void)
    5 w. V4 x& q5 m/ [( @  k) k' V: L
  6. {  5 K* H' Q, i& y! A- k/ N6 s
  7. //第一步,使能PWR外设时钟//( V* K9 P8 s( x! v% c
  8. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
    9 Z4 W4 @8 `$ [: ?7 F2 ]: t8 O# W
  9. //第二步,设置PWR_CSR的EWUP位,使能WK_UP用于将CPU从待机模式唤醒//
    6 y' z- i6 r6 ]: I, R; f
  10. PWR_WakeUpPinCmd(ENABLE);  
    : _6 T+ c( w6 F- R
  11. //第三步,进入待机模式/// D# p- J9 ~! ?2 B
  12. PWR_EnterSTANDBYMode();      0 ~5 j3 v5 G0 n# z4 Y- v. l
  13. }  S7 a# F2 I9 }+ ~) Q
  14. //系统进入待机模式//
    / b0 U% t0 J5 e
  15. void Sys_Enter_Standby(void). B7 D! m6 r9 m& x' J' p, M
  16. {    / P% K1 o* d0 a2 |9 ~7 w$ w
  17. RCC_APB2PeriphResetCmd(0X01FC,DISABLE);    //复位所有IO口$ p* N0 s4 N# w+ _; X
  18. Sys_Standby();
    + Y6 e( M5 `" D2 u0 z2 Q- Q
  19. }4 N2 l% t! V- b+ V: D
  20. //检测WKUP脚的信号,纯C语言//; U' B( V2 z# ?1 x4 p4 _
  21. //返回值1:连续按下3s以上;0:错误的触发// 5 S, y6 a6 \, ]% A7 t  {5 \
  22. u8 Check_WKUP(void)
    5 o, C3 X& V- H6 W) S
  23. {( ^  F" A; [( ^" ^
  24. u8 t=0;                                    //记录按下的时间//# d0 I2 G6 e1 F" ?# i& t0 F
  25. LED0=1;                                    //LED0灭//
    4 Q8 e& n% G, X! y
  26. LED1=1;                                    //LED1灭//1 R; l* M( u, G' C! p$ Z
  27. while(1)
    9 f! R8 E/ \- v& _0 a! X. ?' `
  28. {" Q/ [8 [4 d% R, s
  29.   if(WKUP_KD)                               //WK_UP按键对应PA0,即按下时为高电平//9 ]) F+ F6 i- k; M* c& g
  30.   {
    7 x6 C9 t$ O- s. z( M
  31.    t++;                                     //已经按下了// 5 J" I1 w4 f/ _' I& D( z5 U4 e9 {
  32.    LED0=!LED0;5 V: b/ |- @+ M1 Y
  33.    LED1=!LED1;9 T# J( y; F) B2 J) H
  34.    delay_ms(30);   
    , j( a7 _( x; U% S* N; a
  35.    if(t>=100)                               //按下超过3秒钟//
    3 Q/ z) T2 n! C+ z/ r
  36.    {
    ; `) b- p4 T1 }6 t5 ~
  37.     LED0=0;                                 //LED0亮// 3 J. n, D' o# q9 O4 N
  38.     LED1=0;                      : J. G9 R" w' P/ Q" _" r
  39.     return 1;                               //按下3s以上了//
    ! V8 K" o& w5 u# W" Z, p' d
  40.    }$ G* @! o& j3 p  f: A) m, e  n+ g
  41.   }else
    % ~; H! [: T- X: c+ F
  42.   {
    : z$ `! q# m+ V- i$ R$ f! J
  43.    LED0=1;                                  //LED0灭//
    . X" c$ m3 V: X9 k( u4 P) y  p
  44.    LED1=1;                                  //LED0灭//
    ) y2 Q( [3 f7 f; V- S' @
  45.    return 0;                                //按下不足3秒//
    # ?1 L. B' i! \( J" [/ ^
  46.   }
    7 u; s' F; n) p# Z) c6 S
  47. }
    ) p1 B& F1 p* m2 W
  48. }
      }2 N# [5 v0 d. Z) U8 _9 b& b
  49. //编写外部中断服务函数//
    ' [  Q- R* {, q$ D
  50. void EXTI0_IRQHandler(void)                 //因为检测PA0,所以用EXTI0//
    2 ]+ |0 o1 k3 ~; e! y' H8 d; W
  51. {                            ) P% \4 ~2 W6 ]1 s1 e0 A; o
  52. EXTI_ClearITPendingBit(EXTI_Line0);        //清除LINE0上的中断标志位//    2 u' S; D! H! B  Q
  53. if(Check_WKUP())                           //检查WK_UP是否按下3s以上//3 i7 }2 L. o" I2 |, x
  54. {   
    5 \2 a$ G6 q* v  X
  55.   Sys_Enter_Standby();                      //按下3s以上,系统进入待机模式//; F* [% }8 M/ w' C* t
  56. }
    ; ?& H, f4 s/ u+ F
  57. } 3 ^. G+ ~  U* l8 O4 C1 s) X! h# G
  58. //编写WK_UP初始化函数//+ s9 i: V, C) o0 C; ]
  59. void WKUP_Init(void)/ M) L! M( Y, z
  60. {
    " [) q3 N, u6 a5 O1 I
  61. GPIO_InitTypeDef  GPIO_InitStructure;      - b. C: `9 L1 ?6 K
  62. NVIC_InitTypeDef  NVIC_InitStructure;
    . X0 E4 L: r+ @( R* j9 A
  63. EXTI_InitTypeDef  EXTI_InitStructure;+ x9 d3 c& d% _; ?2 r+ j% T, y' x- R
  64. //使能GPIOA和复用功能时钟//# Z( w6 i3 Z0 W: F( n+ f
  65. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    8 J, K1 F9 f# b+ \
  66. //GPIOA,引脚0配置//
    5 a/ @3 ~  t$ g+ J3 X) o7 U& X
  67. GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;                     //GPIOA,引脚0//+ J% y& I; {/ \# h- f$ w6 v
  68. GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPD;                 //上拉输入//
    $ L/ c2 `; M- e& w
  69. GPIO_Init(GPIOA, &GPIO_InitStructure);      
    * Q* F; Q% B! e' n
  70. //使用外部中断方式//
    ; k$ W+ [) A. @" e8 f
  71. GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);  //中断线0连接GPIOA.0//
    2 u' K6 N8 Q" X, m
  72. EXTI_InitStructure.EXTI_Line = EXTI_Line0;                   //设置按键所有的外部线路//
    $ Z2 A% M7 D. v, z% L1 R3 B
  73. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;          //中断模式//
    2 @0 `- Z3 [( t& L/ G
  74. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;       //上升沿触发//
    2 ]# Q! r0 P) {6 l4 [, r* }
  75. EXTI_InitStructure.EXTI_LineCmd = ENABLE;                    //使能//
    + c) Y  N9 c3 b, {
  76. EXTI_Init(&EXTI_InitStructure);
    , E' O3 j% j2 x- {( J* r, R9 \
  77. //中断优先级初始化//
    7 V; ^4 N, n6 o! z1 W1 m- M
  78. NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;             //使能按键所在的外部中断通道//
    / H( Q" w  g: q, m* O" M8 W
  79. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //先占优先级2级//% {4 L( Y' d" {: H- L" l2 r3 f* ?  o
  80. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;           //从优先级2级//- p' |6 U4 a1 p( j
  81. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //使能外部中断通道//+ f; j+ @. ^  q
  82. NVIC_Init(&NVIC_InitStructure); 3 a, V4 _# V# N4 F! a. n: f' \- d
  83. if(Check_WKUP()==0) Sys_Standby();                         //不是开机,进入待机模式//
    " J# h/ u1 O. o" j1 }( x  J% h/ X: e
  84. }
复制代码

3 p) n( h& W- O8.3 main.c文件代码
, _- r: U9 h/ _# S3 x8 \3 G9 x* X  y
  1. #include "led.h"
    , e* v8 G& `/ K# w! Z
  2. #include "delay.h"7 G( \# }* k, j$ ]3 D
  3. #include "sys.h"
    0 N" R5 M1 J/ ]4 E
  4. #include "usart.h"  # W# ?: O: T9 x' t( U+ R
  5. #include "wkup.h"
    * J/ T" r, G7 q# i. {0 v
  6. int main(void)
    $ f. b- Q! T, _8 T! L
  7. {  
    $ ^  K5 o6 ]  K+ `" ]; B) R
  8. delay_init();                                   //延时函数初始化   
    8 K% S. `0 @- {( C5 b) Z7 P' u
  9. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组为组2//
    9 `5 t" }5 G& e) N
  10. uart_init(115200);                              //串口初始化为115200, B6 o; A- j6 ^$ b4 \2 `& ^( h
  11. LED_Init();                                     //LED端口初始化 ! o5 t( g# D2 h; _; j$ C8 Y' [
  12. LED0=0;5 c% T( o. O- U) j- G
  13. LED1=0;
    6 c6 y9 g* j4 {9 Y- z
  14. delay_ms(500);  
    + A) W- ]9 R- \3 g/ {; o/ C  B  O( z
  15. WKUP_Init();                                    //待机唤醒初始化  ) N% h6 r- [* x; b5 j# F
  16. while(1)6 S1 k- V/ f6 t/ y% U" f) Z; a
  17. {5 s) {, Z' v+ n0 _, {
  18.   LED0=!LED0;
      V4 l  {2 ?  o7 b1 c+ p& V7 A9 l
  19.   LED1=!LED1;
    ' b1 W' V  d/ m. T7 N( C5 s
  20.   delay_ms(1000);% d  v$ p4 ]: G: c
  21. }
    + c! n3 @1 C, u) {
  22. }
复制代码
2 n2 F1 v+ G' t6 {: E6 A/ G
————————————————
6 y+ O, |( d# n1 y6 Q2 B0 l4 r版权声明:天亮继续睡
& \2 }" M1 n" M4 _2 |; Q9 {: \- d
& M2 ?* m+ s& ?, t# V1 y
" J% L8 Q+ G6 Y. |0 v2 j9 U' N) j
收藏 评论0 发布时间:2022-11-20 15:53

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版