两天的调试与查阅资料终于明白了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 {$ ~+ @) 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
% 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
# ~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
. 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
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
; V3 _* [0 f8 \$ I! S% }4 z
4 \4 R! J! J+ I5 O" J* s
! 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- /* USER CODE BEGIN Includes */9 S4 W$ `* g. M* p6 [; F1 C* l
- #include "stdio.h"
- L2 `7 g7 Z, {$ m$ K - /* USER CODE END Includes */
% R" L# o L/ r" ^ - ' j' p t, n! B2 h9 w8 a
% @6 T4 B, r) q2 }1 b' {5 O+ H
- {; S3 r N1 A/ @" \, J' z- #ifdef __GNUC__8 H# w+ P! M! q$ a2 E r
- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf [% T3 S9 m7 y, m! M3 _1 Y
- set to 'Yes') calls __io_putchar() */
6 _5 v8 K: o; [ - #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)! G4 {/ H( Q" Q# m
- #else
; b# C$ {& ~1 m6 N$ n6 K z - #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)& i; d2 K# j" W/ h0 l5 Q6 ^+ q1 F
- #endif /* __GNUC__ */% P; i4 a+ o. W0 |' F9 f; B
- PUTCHAR_PROTOTYPE8 Q/ t3 h' D" H& I8 B
- {
2 o) N3 K& B5 B$ w: Z - /* Place your implementation of fputc here */
j4 Z5 [3 c, d q - /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
) v, R0 v( p" k) P3 o z7 \+ ?
R, _+ J J! o* W- e3 d2 f- HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);8 _# y9 n5 E& c
-
. N( u$ R& z2 z: u - return ch;# g3 p; e# E; a: s: \
- }
复制代码
5 h; r# M! M% v; P& A D" V3 V2.RTC时间获取函数
# b$ ?: N- {2 @% P: ~% M2 C: {9 G* I
- /* USER CODE BEGIN PTD */0 C$ p0 |4 k% w0 b* P. m2 H$ |& n
- RTC_DateTypeDef sdatestructureget;+ A4 I6 [2 E7 U1 W4 G' U; ]
- RTC_TimeTypeDef stimestructureget;% d. g- C+ q% h! g
- uint8_t aShowTime[16] = "hh:ms:ss";
! @' G$ Z5 ?# Z3 S0 B6 M - /* USER CODE END PTD */ T& O% D7 n0 d
- ' l+ W2 H; `3 \
- /* USER CODE BEGIN PD */
) Z- N2 X @- C! o4 e - static void RTC_TimeShow(uint8_t *showtime);
( t4 U8 l9 Z7 C: _* k% W* [ - /* USER CODE END PD */
8 E+ ?0 j7 z4 ?* ?7 c. O
& G4 y5 {* k; L- q& @7 b$ k- 8 \1 P, ?! L; E3 n
- static void RTC_TimeShow(uint8_t *showtime), A4 m6 n) X1 T9 T" Q' \/ K
- {3 p$ r" m$ J. X, d# X
- 1 H( k& A) |3 o7 R9 Q# |$ {3 M
- , b* `0 d6 W) |
- /* Get the RTC current Time */( w$ N1 @ l8 ]$ A; P/ A/ s9 Z ^ n
- HAL_RTC_GetTime(&hrtc, &stimestructureget, RTC_FORMAT_BIN);
, y4 Z! t3 s' S! _* c: x - /* Get the RTC current Date */; a5 H7 q" w9 q) s& s
- HAL_RTC_GetDate(&hrtc, &sdatestructureget, RTC_FORMAT_BIN);
; M1 v* c# I/ n9 Q& F' P% f& F - /* Display time Format : hh:mm:ss */
) H O/ z# N: a/ T - sprintf((char *)showtime, "%02d:%02d:%02d", stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds);
6 F9 w7 Z( ?7 @/ o - }
复制代码
+ G0 G* P8 C! Q3.standby进入函数2 u- g; @# ^' E6 \
- /* USER CODE BEGIN PD */
: ~4 ]0 }0 I( o$ k+ n - void Sys_Enter_Standby(void);1 _( _; f$ R9 v# [
- /* USER CODE END PD */
+ V* O3 V, d5 f1 F+ p4 c, g: _& s. h, q
; ^/ D F6 T6 ^+ l' I9 |- void Sys_Enter_Standby(void)
$ O8 ^$ K5 C6 \/ T0 {. F! i) }0 `9 b5 V - {4 S! h0 P* R" I2 b
- /* The Following Wakeup sequence is highly recommended prior to Standby mode entry
9 o9 C- W5 d2 a; S7 ~) j0 S2 V - - Enable wakeup Z; \( h* `# G, { ]5 s6 s
- - Clear wake up pin flag depending in edge detection & pin level.
. _4 |( G+ J! J9 k( _' T - - Enter the Standby mode.$ {4 t0 X0 a( U& _4 z- D
- */
% p- _* x2 o7 U" d I5 ?
' S8 A7 I& v+ x- z( t0 N- /* Enable WakeUp Pin PWR_WAKEUP_PIN2 connected to PC.13 */
5 n: U' x: P n3 C& b9 [# D. H - HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_LOW);//上升沿触发; b- m* g$ i1 y/ G7 R3 u
- HAL_PWREx_EnableInternalWakeUpLine();
6 U6 r: ~3 j# A; b! z - /* Clear all related wakeup flags*/
! [3 d6 p3 y' X) @0 ^ - __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF2);
2 c7 `% [, E" s/ X
% h8 ?1 `! k# r/ ?+ T8 V; e8 l2 _- /* Enter the Standby mode */5 S& e, M# K$ b. l5 b6 _5 Z
- //HAL_PWR_EnterSTANDBYMode();8 Y& B# r, F; S% h
- printf("enter Shutdown Mode!");6 f$ w2 Q/ t9 e( b7 }
- HAL_PWREx_EnterSHUTDOWNMode();% G$ x7 i$ W* m5 w) ]+ N
- % u$ B! S4 {$ f" [- C4 ^
- /* This code will never be reached! */
. a8 \* y/ r3 r+ f/ X, k - }
复制代码 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. @- void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)' P- u+ o. u$ g+ \3 F) A
- {! k* z, p- n( z
- /* Prevent unused argument(s) compilation warning */; L) B+ a. R* M- a$ ~
- UNUSED(hrtc);% L& d' ^# ]3 V. J9 ?7 ^( c
- v) H9 R5 B2 d! Q5 d& X
- /* NOTE : This function should not be modified, when the callback is needed,
# @. W( S+ F1 h3 A* G4 z - the HAL_RTC_AlarmAEventCallback could be implemented in the user file- K( m% J# {) j( e
- */
# R' d! p4 V! @, T2 X - 9 W+ G( Z! [, y& N$ i* `2 e/ g
- flag =1;$ D3 O8 G( D% }) j" r8 w
- // NVIC_SystemReset();
2 s( |( l$ e6 e9 n$ ~5 ~6 q5 c - 1 W# U% T! O$ E, r7 l3 D4 v2 h
- }
复制代码 " K4 J* P2 @% j3 @# B; K6 x
5.在main函数中5秒的时候进入低功耗模式! S& }* J* F; M+ D l) r
- /* USER CODE BEGIN 2 */7 r9 K4 a, D* G8 u5 L O
- uint8_t sec=0;) c9 C- U) h# p4 W7 M9 a3 w2 ~
- if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)/ C- l0 l5 c: y7 }, s4 `1 b& h; S
- {
9 p1 r9 s) k" |+ \- z2 w9 J0 K6 d - /* Clear Standby flag */
. ?% Y5 u2 R1 P: j - __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
; W3 v- [$ }" B - printf("wake up from standby!");
8 r0 H. K% A6 C0 ?6 N* \* w6 i - /* Check and Clear the Wakeup flag */2 S+ c1 p! D+ ]& V; ~$ c: ~# `
- if (__HAL_PWR_GET_FLAG(PWR_FLAG_WUF2) != RESET)
: D- I' j' u3 R/ w - {- J$ q: z1 d2 V" E9 @
- __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF2);
9 f4 v8 F8 [7 M- J. ]( n - }
0 b/ q" r: e0 D. E$ f5 ?* M - 9 ~ s' Z+ l5 q
- /* Wait that user release the User push-button *// K- a1 Z( l+ H5 [& i
- while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET){}- q' _+ z- X( m w
8 i- r! `9 C# C9 {+ m$ p- }
4 n+ _8 e+ b+ y
9 ]8 W( h$ j- V( H) t: i
: G$ \9 O% T; E& c9 E5 w' r- /* USER CODE END 2 */ I# p5 \' Q9 m& X; {+ _ U/ I' o
0 X Q }1 n4 b: e. ^; r- /* Infinite loop */' b( X6 H$ i$ G- q9 X8 e1 [. v( t& l
- /* USER CODE BEGIN WHILE */
: U( @ _. [4 B( b/ a i! \% e - while (1)
0 u' j6 R' X2 \2 v, W$ c - {
5 }; v( T0 D+ I- S% ` - /* USER CODE END WHILE */
M; p0 P9 N/ G- A! O4 J. F' M W - , {% X* p+ L0 V: ~- _
- /* USER CODE BEGIN 3 */
/ c8 q( U9 w, i' _- A - RTC_TimeShow(aShowTime);
6 b: j' j. s* _' D3 w: J - if(sec == 0)flag=0;8 x6 Z8 p/ h" p+ [: E: v' Z4 M% d' M' }
- " \, ~" A1 h! ^2 `8 I# Y: L
- if(sec == 5)Sys_Enter_Standby();/ S9 Q6 B- p1 {6 I+ |- N
- if(sec!=stimestructureget.Seconds)
6 t0 \: G* I9 n: R+ k6 I' a( i - {4 e1 S" K0 ?0 ?& \
- sec=stimestructureget.Seconds;
' o) q" k' y9 S- m3 h - printf("%s",(char *)aShowTime);- V8 v! M5 L) K$ i
- if(flag) HAL_GPIO_TogglePin(LD4_GPIO_Port,LD4_Pin);
1 Z/ G! X- B) H+ O" F1 J# } - }3 W$ d; o+ Z+ J
- }
0 v4 ]$ t; \' B O. y/ a) g5 y - /* USER CODE END 3 */( P. l5 A( [& j4 |# o
- }
复制代码
- |+ 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+ ~
- /* USER CODE BEGIN Check_RTC_BKUP */
2 W# G" x' X" w; F - if (__HAL_RTC_GET_FLAG(&hrtc, RTC_FLAG_INITS) == 0x00u){}9 @3 N* S! }" i" X" b# y
- else{return;}
) Q0 |8 K5 P4 v - /* 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
! @! 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) \
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 |