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

【经验分享】STM32G0 stm32g071 关于待机模式和关闭模式的进入和退出(RTC和wakeup pin) HAL库 Standby Mode and

[复制链接]
STMCU小助手 发布时间:2021-11-8 15:49
两天的调试与查阅资料终于明白了HAL库中的低功耗模式的切换和退出。主要还是自己作死选择了STM32G071,本文内容基于NUCLEO-G071RB,CUBEMX版本5.2.0,STM32Cube FW_G0 V1.2.0,MDK 5.27.1.0。$ `9 ^- G- t8 e

+ G" h/ N3 a# d2 f7 d首先配置时钟、UART、RTC和中断。/ }- ]# {/ L4 H( X8 K

5 U. \6 p, G5 {$ ~
20190510004029552.png
+ @) A2 M' s5 v" D( D4 _, S
7 X/ z  Q, Q: v6 |
RCC选择外部晶振(shutdown 模式只能使用外部晶振)其他默认
( c2 X" d* J" y7 ?* a  A7 s1 v0 g- q' P  i1 W' Z5 v( Z% A
20190510004154456.png

% Z- c3 R2 Y' L( e: {+ ~; ]/ z# f  x4 D( \
SYS选择调试接口,和wakeup_pin2,STM32G0目前新线还是很多资源的) M/ x! v  e2 q8 i. n
! @) r. h; w( j6 M' _1 |! Y. w% Y
20190510005141588.png

# ~2 M$ k6 P0 J
7 [! ?! n) d  F2 d! B2 m设置RTC,填写相关初始化信息、开启ALARMA时间设定为开机后30秒,注意RTC_AlarmMask=RTC_AlarmMask_None;则为精确匹配,即闹钟不仅要求时分秒匹配还要匹配日期和星期,都匹配后触发闹钟中断)3 A% z: t1 V( h; h2 u* {

3 `+ V7 @$ j( i2 [; M1 f
20190510005211104.png

. s5 G( r' ^1 w+ s
0 m5 ~0 ^5 B# ?1 j' K& H设置串口6 r/ K; Z. \' u
6 f6 {, Q  F9 }9 z+ c" z. {0 z
20190510005241164.png
8 ~2 b9 I( `; C2 z; X! l

: b- u0 i# O) q' E& R* x. P- n7 I打开中断入口
6 y/ }3 o$ V! C0 Y) Y4 j8 `5 N& a; N, H" c, y, Q
2019051000534771.png
; V3 _* [0 f8 \$ I! S% }4 z
4 \4 R! J! J+ I5 O" J* s
20190510005358325.png

! P$ M: q( ]) r( n) Y, F: g* k2 j" a/ U$ K/ C$ T  p
完成设置后点击生成代码创建工程  \7 |- z! t& A4 k' }, q' v
; }7 P2 o8 C8 c1 }- k8 l  g
1.首先喜闻乐见的printf函数
1 u: [+ r/ X: ?2 G
  1. /* USER CODE BEGIN Includes */9 S4 W$ `* g. M* p6 [; F1 C* l
  2. #include "stdio.h"
    - L2 `7 g7 Z, {$ m$ K
  3. /* USER CODE END Includes */
    % R" L# o  L/ r" ^
  4. ' j' p  t, n! B2 h9 w8 a

  5. % @6 T4 B, r) q2 }1 b' {5 O+ H

  6. - {; S3 r  N1 A/ @" \, J' z
  7. #ifdef __GNUC__8 H# w+ P! M! q$ a2 E  r
  8.   /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf  [% T3 S9 m7 y, m! M3 _1 Y
  9.      set to 'Yes') calls __io_putchar() */
    6 _5 v8 K: o; [
  10.   #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)! G4 {/ H( Q" Q# m
  11. #else
    ; b# C$ {& ~1 m6 N$ n6 K  z
  12.   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)& i; d2 K# j" W/ h0 l5 Q6 ^+ q1 F
  13. #endif /* __GNUC__ */% P; i4 a+ o. W0 |' F9 f; B
  14. PUTCHAR_PROTOTYPE8 Q/ t3 h' D" H& I8 B
  15. {
    2 o) N3 K& B5 B$ w: Z
  16.   /* Place your implementation of fputc here */
      j4 Z5 [3 c, d  q
  17.   /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
    ) v, R0 v( p" k) P3 o  z7 \+ ?

  18.   R, _+ J  J! o* W- e3 d2 f
  19.         HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);8 _# y9 n5 E& c
  20.         
    . N( u$ R& z2 z: u
  21.   return ch;# g3 p; e# E; a: s: \
  22. }
复制代码

5 h; r# M! M% v; P& A  D" V3 V2.RTC时间获取函数
# b$ ?: N- {2 @% P: ~% M2 C: {9 G* I
  1. /* USER CODE BEGIN PTD */0 C$ p0 |4 k% w0 b* P. m2 H$ |& n
  2. RTC_DateTypeDef sdatestructureget;+ A4 I6 [2 E7 U1 W4 G' U; ]
  3. RTC_TimeTypeDef stimestructureget;% d. g- C+ q% h! g
  4. uint8_t aShowTime[16] = "hh:ms:ss";
    ! @' G$ Z5 ?# Z3 S0 B6 M
  5. /* USER CODE END PTD */  T& O% D7 n0 d
  6. ' l+ W2 H; `3 \
  7. /* USER CODE BEGIN PD */
    ) Z- N2 X  @- C! o4 e
  8. static void RTC_TimeShow(uint8_t *showtime);
    ( t4 U8 l9 Z7 C: _* k% W* [
  9. /* USER CODE END PD */
    8 E+ ?0 j7 z4 ?* ?7 c. O

  10. & G4 y5 {* k; L- q& @7 b$ k
  11. 8 \1 P, ?! L; E3 n
  12. static void RTC_TimeShow(uint8_t *showtime), A4 m6 n) X1 T9 T" Q' \/ K
  13. {3 p$ r" m$ J. X, d# X
  14. 1 H( k& A) |3 o7 R9 Q# |$ {3 M
  15. , b* `0 d6 W) |
  16.   /* Get the RTC current Time */( w$ N1 @  l8 ]$ A; P/ A/ s9 Z  ^  n
  17.   HAL_RTC_GetTime(&hrtc, &stimestructureget, RTC_FORMAT_BIN);
    , y4 Z! t3 s' S! _* c: x
  18.   /* Get the RTC current Date */; a5 H7 q" w9 q) s& s
  19.   HAL_RTC_GetDate(&hrtc, &sdatestructureget, RTC_FORMAT_BIN);
    ; M1 v* c# I/ n9 Q& F' P% f& F
  20.   /* Display time Format : hh:mm:ss */
    ) H  O/ z# N: a/ T
  21.   sprintf((char *)showtime, "%02d:%02d:%02d", stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds);
    6 F9 w7 Z( ?7 @/ o
  22. }
复制代码

+ G0 G* P8 C! Q3.standby进入函数2 u- g; @# ^' E6 \
  1. /* USER CODE BEGIN PD */
    : ~4 ]0 }0 I( o$ k+ n
  2. void Sys_Enter_Standby(void);1 _( _; f$ R9 v# [
  3. /* USER CODE END PD */
    + V* O3 V, d5 f1 F+ p4 c, g: _& s. h, q

  4. ; ^/ D  F6 T6 ^+ l' I9 |
  5. void Sys_Enter_Standby(void)
    $ O8 ^$ K5 C6 \/ T0 {. F! i) }0 `9 b5 V
  6. {4 S! h0 P* R" I2 b
  7.   /* The Following Wakeup sequence is highly recommended prior to Standby mode entry
    9 o9 C- W5 d2 a; S7 ~) j0 S2 V
  8.   - Enable wakeup  Z; \( h* `# G, {  ]5 s6 s
  9.   - Clear wake up pin flag depending in edge detection & pin level.
    . _4 |( G+ J! J9 k( _' T
  10.   - Enter the Standby mode.$ {4 t0 X0 a( U& _4 z- D
  11.   */
    % p- _* x2 o7 U" d  I5 ?

  12. ' S8 A7 I& v+ x- z( t0 N
  13.   /* Enable WakeUp Pin PWR_WAKEUP_PIN2 connected to PC.13 */
    5 n: U' x: P  n3 C& b9 [# D. H
  14.   HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_LOW);//上升沿触发; b- m* g$ i1 y/ G7 R3 u
  15.   HAL_PWREx_EnableInternalWakeUpLine();
    6 U6 r: ~3 j# A; b! z
  16.   /* Clear all related wakeup flags*/
    ! [3 d6 p3 y' X) @0 ^
  17.   __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF2);
    2 c7 `% [, E" s/ X

  18. % h8 ?1 `! k# r/ ?+ T8 V; e8 l2 _
  19.   /* Enter the Standby mode */5 S& e, M# K$ b. l5 b6 _5 Z
  20.   //HAL_PWR_EnterSTANDBYMode();8 Y& B# r, F; S% h
  21.         printf("enter Shutdown Mode!");6 f$ w2 Q/ t9 e( b7 }
  22.         HAL_PWREx_EnterSHUTDOWNMode();% G$ x7 i$ W* m5 w) ]+ N
  23. % u$ B! S4 {$ f" [- C4 ^
  24.   /* This code will never be reached! */
    . a8 \* y/ r3 r+ f/ X, k
  25. }
复制代码
  T1 n4 O4 J# n& p) d6 m- q
4.ALarmA中断回调函数 NVIC_SystemReset()用于standby触发AlarmA时间后与wake_pin触发系统自复位不同进入rtc中断后无法复位问题(我解决不了就软复位)
* w, v8 S6 h0 S. ^5 h. @
  1. void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)' P- u+ o. u$ g+ \3 F) A
  2. {! k* z, p- n( z
  3.   /* Prevent unused argument(s) compilation warning */; L) B+ a. R* M- a$ ~
  4.   UNUSED(hrtc);% L& d' ^# ]3 V. J9 ?7 ^( c
  5.   v) H9 R5 B2 d! Q5 d& X
  6.   /* NOTE : This function should not be modified, when the callback is needed,
    # @. W( S+ F1 h3 A* G4 z
  7.             the HAL_RTC_AlarmAEventCallback could be implemented in the user file- K( m% J# {) j( e
  8.    */
    # R' d! p4 V! @, T2 X
  9. 9 W+ G( Z! [, y& N$ i* `2 e/ g
  10.         flag =1;$ D3 O8 G( D% }) j" r8 w
  11. //        NVIC_SystemReset();
    2 s( |( l$ e6 e9 n$ ~5 ~6 q5 c
  12.         1 W# U% T! O$ E, r7 l3 D4 v2 h
  13. }
复制代码
" K4 J* P2 @% j3 @# B; K6 x
5.在main函数中5秒的时候进入低功耗模式! S& }* J* F; M+ D  l) r
  1. /* USER CODE BEGIN 2 */7 r9 K4 a, D* G8 u5 L  O
  2.         uint8_t sec=0;) c9 C- U) h# p4 W7 M9 a3 w2 ~
  3.         if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)/ C- l0 l5 c: y7 }, s4 `1 b& h; S
  4.   {
    9 p1 r9 s) k" |+ \- z2 w9 J0 K6 d
  5.     /* Clear Standby flag */
    . ?% Y5 u2 R1 P: j
  6.     __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
    ; W3 v- [$ }" B
  7.                 printf("wake up from standby!");
    8 r0 H. K% A6 C0 ?6 N* \* w6 i
  8.     /* Check and Clear the Wakeup flag */2 S+ c1 p! D+ ]& V; ~$ c: ~# `
  9.     if (__HAL_PWR_GET_FLAG(PWR_FLAG_WUF2) != RESET)
    : D- I' j' u3 R/ w
  10.     {- J$ q: z1 d2 V" E9 @
  11.       __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF2);
    9 f4 v8 F8 [7 M- J. ]( n
  12.     }
    0 b/ q" r: e0 D. E$ f5 ?* M
  13.                 9 ~  s' Z+ l5 q
  14.     /* Wait that user release the User push-button *// K- a1 Z( l+ H5 [& i
  15.      while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET){}- q' _+ z- X( m  w

  16. 8 i- r! `9 C# C9 {+ m$ p
  17.   }
    4 n+ _8 e+ b+ y

  18. 9 ]8 W( h$ j- V( H) t: i

  19. : G$ \9 O% T; E& c9 E5 w' r
  20.   /* USER CODE END 2 */  I# p5 \' Q9 m& X; {+ _  U/ I' o

  21. 0 X  Q  }1 n4 b: e. ^; r
  22.   /* Infinite loop */' b( X6 H$ i$ G- q9 X8 e1 [. v( t& l
  23.   /* USER CODE BEGIN WHILE */
    : U( @  _. [4 B( b/ a  i! \% e
  24.   while (1)
    0 u' j6 R' X2 \2 v, W$ c
  25.   {
    5 }; v( T0 D+ I- S% `
  26.     /* USER CODE END WHILE */
      M; p0 P9 N/ G- A! O4 J. F' M  W
  27. , {% X* p+ L0 V: ~- _
  28.     /* USER CODE BEGIN 3 */
    / c8 q( U9 w, i' _- A
  29.                 RTC_TimeShow(aShowTime);
    6 b: j' j. s* _' D3 w: J
  30.                 if(sec == 0)flag=0;8 x6 Z8 p/ h" p+ [: E: v' Z4 M% d' M' }
  31. " \, ~" A1 h! ^2 `8 I# Y: L
  32.                 if(sec == 5)Sys_Enter_Standby();/ S9 Q6 B- p1 {6 I+ |- N
  33.                 if(sec!=stimestructureget.Seconds)
    6 t0 \: G* I9 n: R+ k6 I' a( i
  34.                 {4 e1 S" K0 ?0 ?& \
  35.                         sec=stimestructureget.Seconds;
    ' o) q" k' y9 S- m3 h
  36.                         printf("%s",(char *)aShowTime);- V8 v! M5 L) K$ i
  37.                         if(flag) HAL_GPIO_TogglePin(LD4_GPIO_Port,LD4_Pin);
    1 Z/ G! X- B) H+ O" F1 J# }
  38.                 }3 W$ d; o+ Z+ J
  39.   }
    0 v4 ]$ t; \' B  O. y/ a) g5 y
  40.   /* USER CODE END 3 */( P. l5 A( [& j4 |# o
  41. }
复制代码

- |+ r4 T- V5 o; K- P, u至此STM32G071关于低功耗模式的进入与退出已经可以实际使用,大家可以参考,实际使用稍作调整。; M1 @9 f6 x& A3 X% v

5 w3 y$ S* w4 G: c- d7 n3 n附加 避免上电自动配置RTC时钟5 _* g* h; a0 H8 t7 Y! o+ ~
  1. /* USER CODE BEGIN Check_RTC_BKUP */
    2 W# G" x' X" w; F
  2.         if (__HAL_RTC_GET_FLAG(&hrtc, RTC_FLAG_INITS) == 0x00u){}9 @3 N* S! }" i" X" b# y
  3.         else{return;}
    ) Q0 |8 K5 P4 v
  4.   /* USER CODE END Check_RTC_BKUP */
复制代码

! L8 X5 x& Z& L9 z3 v以上代码请添加于MX_RTC_Init(void)中% w" C( M1 u' G1 `

: M- D1 ?. f: f- f
2019051001272486.png

! @! i' W( t/ `/ U" F$ M2 A
0 E" R8 T; Y" b+ n$ a- H6 C项目文件, l8 S5 h. @; a5 {" e

, W$ R8 b1 }* }# M) \
20190510013203724.png

2 K" G: {2 D' W" T5 a. x* D% b& z
2 f9 K+ b* h! D" o1 i
5 G* s# @) S) G8 x
赞 收藏 评论0 发布时间:2021-11-8 15:49

举报

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