两天的调试与查阅资料终于明白了HAL库中的低功耗模式的切换和退出。主要还是自己作死选择了STM32G071,本文内容基于NUCLEO-G071RB,CUBEMX版本5.2.0,STM32Cube FW_G0 V1.2.0,MDK 5.27.1.0。
0 t& h8 j( ]' n$ C5 B2 n# X6 ~3 |5 R4 D6 I% N4 S3 E
首先配置时钟、UART、RTC和中断。7 Y; o9 v" q. M9 | w1 l7 ^
( k7 s) B$ D8 ^0 `; N: l* v; ?
3 Y) K5 A9 f. x# |6 e! t7 j% Q9 k, u8 x5 L3 K1 N
RCC选择外部晶振(shutdown 模式只能使用外部晶振)其他默认. u$ D( j3 j7 r0 z4 |
" q' v x. ?' q9 r7 J: l
% `* V' j& u) t+ T3 h
. {6 t+ q$ j$ z+ b2 n& X5 FSYS选择调试接口,和wakeup_pin2,STM32G0目前新线还是很多资源的6 B* P! A7 L: G7 W7 E& b# t
. J% p w) M1 _" J
7 E, \* r& E ]; M$ p6 ^
' I( N& f. y7 h3 U
设置RTC,填写相关初始化信息、开启ALARMA时间设定为开机后30秒,注意RTC_AlarmMask=RTC_AlarmMask_None;则为精确匹配,即闹钟不仅要求时分秒匹配还要匹配日期和星期,都匹配后触发闹钟中断)
% T7 X$ u+ O: f/ i% V9 M5 A% G2 {; Z2 ?
7 c% P. I$ t% t3 R5 x7 M/ X$ u
$ N4 ~" P! v$ A& D q U& M7 _设置串口
& @8 x9 m# F! e3 |0 E I6 A/ _2 F
0 S% C% ~- z! z+ n0 ?8 b; a
) W* B- K# B2 _) g4 s2 }% B9 x
+ }9 i' |- B I' ~打开中断入口
' @3 i) ?' _5 G1 ]$ t2 f4 t& j8 k; P- g; M0 H: m5 y
) y5 f$ N Q" c5 D. S) I2 i
& v/ ~+ N! x) M v, f( `+ P- @* f2 ~& T4 L
# @- o0 k7 p$ r1 O) L' d完成设置后点击生成代码创建工程
4 j' T9 D' T6 m- g$ ?
% E9 I: w9 l+ H2 m- a: w1.首先喜闻乐见的printf函数% d* Y X M' E7 ^% b
- /* USER CODE BEGIN Includes */
4 `0 t O6 Y1 M2 T6 v - #include "stdio.h"
( }5 B O4 ^- X; G - /* USER CODE END Includes */5 F( N! b4 j* ~. k! M& ^$ c0 M/ ~* f
; L7 z7 y+ f- Y4 X$ ]" u/ W
7 z3 E" I# {: m3 G+ U( C
6 I; d2 g: n5 `- N8 I- #ifdef __GNUC__
1 h6 s! x% s, P* ~: I - /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf+ Q& F8 A/ p) P6 {/ x
- set to 'Yes') calls __io_putchar() */) x2 H4 I7 K! u# N8 H: G+ \
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)4 |3 c' l5 k& b0 _. _
- #else) D0 L% D; I. B6 l" I1 F' b0 g
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
5 e* U8 M6 |' |# D3 i - #endif /* __GNUC__ */
2 }# ]/ I, C0 S( k4 n6 U5 m5 V - PUTCHAR_PROTOTYPE
+ \ A1 h! S: ^& O# p - {
6 k/ o6 s C- F+ C+ t - /* Place your implementation of fputc here */- z% D! N T; a4 Z, {! e+ B
- /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
8 d5 h* U5 l1 F0 f3 J& k, Z - ( |: ~4 X$ R& H( S
- HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
' I l, Z: h# [$ z" ~6 m/ v - / x3 @, ~6 d6 X9 U% u1 @
- return ch;; t8 g/ F& {* ]' i9 b) e" `
- }
复制代码
# r. s( G& D: w6 Z' n( H1 }2.RTC时间获取函数7 o, G' X& m. Y5 {# Q! {
+ `5 d N' A, J- S! v" {- /* USER CODE BEGIN PTD */* g7 a9 W0 C4 f* G& v. g
- RTC_DateTypeDef sdatestructureget;2 W3 {# d) c6 |/ }4 ^4 k% T" a8 A
- RTC_TimeTypeDef stimestructureget;$ f; ]+ ^( r3 [; S1 p+ f
- uint8_t aShowTime[16] = "hh:ms:ss";
+ r* Q: S3 t& \2 l - /* USER CODE END PTD */- h& d) G7 b& g3 b3 A! \* S3 M
- , e. a; e0 G$ r- I4 k6 T
- /* USER CODE BEGIN PD */% q/ Q+ B& M' ]. M: h8 W) g
- static void RTC_TimeShow(uint8_t *showtime);- [9 S }% j) q& G" n, }* e" H6 l
- /* USER CODE END PD */
& p* J+ L# ^% o9 g9 x ]2 C
; C6 W8 T% I/ @3 D6 D3 y9 j
! ?. X" z; N" l6 v+ x1 f- static void RTC_TimeShow(uint8_t *showtime)
5 k! F0 H% v1 T/ I' l - {# s, f; r2 t( Y( Q5 n% u
- ; X8 p( m/ O, T/ y4 {
- + p4 n, l0 n/ g3 ^5 N) ?
- /* Get the RTC current Time */% ]) G: g. ~9 v! q4 k' [8 n- p3 h- {
- HAL_RTC_GetTime(&hrtc, &stimestructureget, RTC_FORMAT_BIN);
x( H/ K6 G! i5 ]6 T1 ^ - /* Get the RTC current Date */# U% C) E3 ^0 Y& b+ M9 M
- HAL_RTC_GetDate(&hrtc, &sdatestructureget, RTC_FORMAT_BIN);
; q8 Z/ q, g* s! y+ I/ r- R - /* Display time Format : hh:mm:ss */+ a& t2 S4 x0 @, L5 j
- sprintf((char *)showtime, "%02d:%02d:%02d", stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds);
# W5 T2 W" T' r - }
复制代码
- L3 l; n) v- s3.standby进入函数
1 q' G* e! k2 F* W- /* USER CODE BEGIN PD */
& e1 `8 H# ]3 Z: o - void Sys_Enter_Standby(void);: X. y0 k: I( O7 a. [7 a. P
- /* USER CODE END PD */
- \0 U. m: `5 t' D/ F
1 b" e L+ }, c& W- void Sys_Enter_Standby(void)
: Y, q' h7 d& Z6 Q& R. u) } - {
/ ]2 A9 ^" `! L0 d/ A" {8 k8 Z- n6 J - /* The Following Wakeup sequence is highly recommended prior to Standby mode entry
& k6 f: T3 x: l9 _: s2 z" A+ u - - Enable wakeup3 F5 k4 I0 ]" f
- - Clear wake up pin flag depending in edge detection & pin level.
9 y& Y J1 Q: J: F: R) p* [5 r7 P - - Enter the Standby mode.3 A( [ l0 h6 A! F1 \( g7 C( s5 u# g
- */
4 h7 ^( H1 O0 d* ?) k J
; s _' q! O9 t1 I$ s+ k X( \- /* Enable WakeUp Pin PWR_WAKEUP_PIN2 connected to PC.13 */& K9 E$ p) O# F& y2 Z
- HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_LOW);//上升沿触发
3 s+ r# S& a1 P - HAL_PWREx_EnableInternalWakeUpLine();
9 Y- \. J& `' q/ Y! ` - /* Clear all related wakeup flags*/
; _$ U+ G* d5 x3 y g - __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF2);
( R7 H" u9 k* O6 a+ G8 y - " R- m `* K7 {4 C
- /* Enter the Standby mode */# k, @% ?, i8 P$ c% f% P+ R: g
- //HAL_PWR_EnterSTANDBYMode();
* u9 p& L+ E4 } - printf("enter Shutdown Mode!");4 {, K2 q( E! r
- HAL_PWREx_EnterSHUTDOWNMode();( ^1 {: O9 K. ?7 D) V1 {
- 9 o+ ^3 w) X( b+ W
- /* This code will never be reached! */
3 K9 _( K0 r$ e4 c2 {, e - }
复制代码
2 C; b9 T# {" p# C; L+ j4.ALarmA中断回调函数 NVIC_SystemReset()用于standby触发AlarmA时间后与wake_pin触发系统自复位不同进入rtc中断后无法复位问题(我解决不了就软复位)3 d2 ]0 a3 q. y! g0 _# K. v6 J6 F
- void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)5 M) y0 n- q7 E" m
- {
A3 p+ j0 Z, Q - /* Prevent unused argument(s) compilation warning */
C* l8 [/ a. q6 z' S$ {5 p- J - UNUSED(hrtc);
7 ]2 p, j) ^6 R8 A
2 C& N8 U$ [4 a# y6 c" R- /* NOTE : This function should not be modified, when the callback is needed," A% z9 N2 t8 e7 v9 E9 {4 D' z& q4 y
- the HAL_RTC_AlarmAEventCallback could be implemented in the user file8 A1 K: i+ M9 { I) v
- */
& U, @* G' M4 y/ k h - + Z8 X! X7 e8 p/ k1 b& Y% S5 g5 [
- flag =1;! ]- k% w7 g$ U0 h! J7 `( z2 u
- // NVIC_SystemReset();
7 _: }, F6 y N6 J3 O5 w - C4 ~# m) h6 r2 g/ K9 M0 _
- }
复制代码 ! k& E( D* ?8 e3 i: V. M9 F
5.在main函数中5秒的时候进入低功耗模式
# ?# c2 i0 c7 w( g- /* USER CODE BEGIN 2 */+ ]( M5 ]( |' ^3 K# L B
- uint8_t sec=0;
0 a- @0 ^* O4 G6 C; h: k- b - if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)
- n$ D, C5 E) h% K4 g! o) h - {: R1 d; i, D0 m$ F2 i# `6 d
- /* Clear Standby flag */1 h0 r3 ?$ C3 F6 F+ p0 G: u
- __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
+ {0 m9 b+ K/ \7 y. { - printf("wake up from standby!");
j" A0 d, M3 e! a8 J - /* Check and Clear the Wakeup flag */& v" n$ g2 t8 G" h' F
- if (__HAL_PWR_GET_FLAG(PWR_FLAG_WUF2) != RESET)
t8 A8 a7 o8 R, } - {6 C2 F0 F# @9 P- ^* K- s3 h) u
- __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF2);9 X; K! \: L7 T5 S! }3 B
- }
' a8 C- s: X" Z* o - " f: m$ `: R' X8 v
- /* Wait that user release the User push-button */" [. L6 D* e1 A. ^! d7 h/ b5 n7 K
- while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET){}* l3 [- |) u6 {5 G* E
! {6 U* y9 c& A m- }# R7 [* [/ _/ o/ `1 ^3 c+ R2 Z- c
- 3 M( `3 ?* }& |# q' k
5 T9 r& D4 g& _3 y3 N+ H- /* USER CODE END 2 */6 g" `/ ?1 v9 e8 h
- " ?' W, r; ?; U7 l, \) \. e6 K
- /* Infinite loop */4 R p [1 M1 B! M$ o
- /* USER CODE BEGIN WHILE */
, } y- K$ L6 s$ P" _1 g" _# v! f - while (1)0 b) L5 [6 X6 L# q/ u0 L
- {
, i" V7 {* h S5 y1 z+ A - /* USER CODE END WHILE */
) k3 [: b5 J* m8 R+ z5 N% X$ k+ G! i - ! t" m A( Y0 C
- /* USER CODE BEGIN 3 */
' Q; O* {6 x9 B( g - RTC_TimeShow(aShowTime);
+ \5 S: J. w" v7 p$ Q - if(sec == 0)flag=0;
5 `8 j" l |) m* }# X - 1 A: G# C) h' Z0 F
- if(sec == 5)Sys_Enter_Standby();
5 Q) g' f( M9 G' q& s9 b - if(sec!=stimestructureget.Seconds)) U& I- S Z' i! p; _# g
- {) T. h+ e& I" A
- sec=stimestructureget.Seconds;" U3 B& i2 q3 ?( S1 _# x
- printf("%s",(char *)aShowTime);
) s) l# y& Q/ {7 x - if(flag) HAL_GPIO_TogglePin(LD4_GPIO_Port,LD4_Pin);9 ]& V3 o. D. i- V( S0 Q
- }
7 P3 H. o3 E* C/ ] P - }% F- ^3 ~. R" s* q
- /* USER CODE END 3 */! `1 e2 \1 O' r. c- D9 p9 h
- }
复制代码
* P: n9 j# E. |2 @! ?至此STM32G071关于低功耗模式的进入与退出已经可以实际使用,大家可以参考,实际使用稍作调整。: q2 c( Z2 X! [# b
# C+ w5 q; d# I/ \8 Y ^
附加 避免上电自动配置RTC时钟3 \2 R5 m1 \0 C' ~) l: z
- /* USER CODE BEGIN Check_RTC_BKUP */
. {# @; M7 n- [# H5 t# H0 s - if (__HAL_RTC_GET_FLAG(&hrtc, RTC_FLAG_INITS) == 0x00u){}( b, I5 u6 j( V3 X
- else{return;}& G+ z1 O+ z8 G5 t6 `% V: }6 y
- /* USER CODE END Check_RTC_BKUP */
复制代码
( P! F1 F$ ~: {* x- k以上代码请添加于MX_RTC_Init(void)中, d# Z, i( ]4 k# h0 C
4 P u" `. d. u! |& t' o# I/ _" d* f
8 }1 e" X0 N3 M8 s
项目文件
! b) j6 T6 M! R3 [
7 v0 A. R+ x; F: C# S, c. h7 x
" t& p( a$ s( W- n$ y) s. o6 T l8 z2 o: U3 J
8 u3 e6 c" X! r
|