两天的调试与查阅资料终于明白了HAL库中的低功耗模式的切换和退出。主要还是自己作死选择了STM32G071,本文内容基于NUCLEO-G071RB,CUBEMX版本5.2.0,STM32Cube FW_G0 V1.2.0,MDK 5.27.1.0。
i4 @* m" @6 \ b0 j7 Z& Q6 s( j. ?* W0 ], h
首先配置时钟、UART、RTC和中断。) u W+ J( O; K6 _9 _' B
7 v/ r' A1 Q5 a; e" [; `0 |! W. b+ z+ Q$ K4 ^
( z$ z0 Q& I; |$ h2 e
RCC选择外部晶振(shutdown 模式只能使用外部晶振)其他默认5 ~3 E" a1 q w3 _2 x, y! `
+ ]5 X# o2 y$ F
+ Z/ e$ i8 l. }- c% q
+ g" |' w3 J, ^) J5 a2 Z
SYS选择调试接口,和wakeup_pin2,STM32G0目前新线还是很多资源的7 @8 }* e1 O( r
5 B9 H R, p! c0 `2 |0 k `
# o2 Q9 J3 t* ^; w0 [
3 n1 [, |; V% Q$ _+ d
设置RTC,填写相关初始化信息、开启ALARMA时间设定为开机后30秒,注意RTC_AlarmMask=RTC_AlarmMask_None;则为精确匹配,即闹钟不仅要求时分秒匹配还要匹配日期和星期,都匹配后触发闹钟中断)) w" m( P, B3 [: k) O, j
/ H- E Y1 f/ w
8 c& P% [- B8 [. P6 I3 r! l0 A0 v7 P6 X* i
设置串口5 U9 e; O# y7 I8 `: W5 [
; ]0 j$ N2 D9 [- |6 f
0 b; s% i& B- K, q; P1 R I5 F) U
) [# i( R# c9 d8 b% t- P打开中断入口6 [; q. |0 `3 j
4 A# i$ R1 [" a3 m: _# T, I+ e. T2 e/ F* z1 A. B& W2 C
+ ^- V, @% e" r& Z0 b5 T
5 ^% d# ], s2 D# E, Y
) X2 B1 \+ z- L$ N- q4 M! f完成设置后点击生成代码创建工程) w( S2 D+ t# d }. k
$ a& \; r: b# F3 L7 Q9 L$ I" @
1.首先喜闻乐见的printf函数# U* S( ?- b0 h- N
- /* USER CODE BEGIN Includes */
; s& T6 a+ |; R' A - #include "stdio.h"" A B. |% \0 W( {4 b
- /* USER CODE END Includes */
, E, W) P; @, w) \
# `' S+ j# d: y/ B
d5 K4 Y( f b |5 C% @- 2 k5 K% F" ~- j7 u1 W; w
- #ifdef __GNUC__ U1 ]* E' N+ F! L
- /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf8 r, g1 w: Q& h+ _! w
- set to 'Yes') calls __io_putchar() */7 h! B/ Y+ _1 G* C0 R
- #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
9 K- B+ z' ~: g3 P7 i - #else$ [$ T) {1 i. o- l# V% r' F" `( m# N
- #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)5 V# f5 M% h1 R. e0 i o
- #endif /* __GNUC__ */* f# a% k. Z/ T8 {& B
- PUTCHAR_PROTOTYPE5 }. S6 g& m5 q1 F2 ?
- {
8 L7 Q8 l3 w8 ^3 [- }8 V - /* Place your implementation of fputc here */2 c P3 M& }0 q* x2 [. P- v
- /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */. |' a+ m+ `; ?4 c
* \' U: |* J3 m; X: g' l! _- HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);. |0 M1 @# F3 y$ f2 t
-
2 P( a# w @( g9 j! @8 ? - return ch;" s0 Q. @: n# L, }( G, \5 d2 A) d
- }
复制代码 & t- _6 D. k) U l9 r9 \
2.RTC时间获取函数
# W. I% ^- d6 X2 M* l3 Z1 h3 o7 w: Q
- /* USER CODE BEGIN PTD */
' Y D0 i' d& d6 G6 ` - RTC_DateTypeDef sdatestructureget;- K* O' p0 {5 }% ^# L# D) X
- RTC_TimeTypeDef stimestructureget;. L# L- t, P# ~/ c# b4 G
- uint8_t aShowTime[16] = "hh:ms:ss";
5 L7 `/ [$ a; O - /* USER CODE END PTD */
6 j! i! {! s2 p+ e - & T7 o' C; B4 i& R% c1 L
- /* USER CODE BEGIN PD */' l# y9 E/ p: {4 b
- static void RTC_TimeShow(uint8_t *showtime);
4 ~* l) y7 G, Y. y* P6 K - /* USER CODE END PD */
3 A$ G* c( Z& e2 _ - * ?( @" c9 w9 p* j$ h
9 B' o/ P. J* `- static void RTC_TimeShow(uint8_t *showtime)
7 h! k) T3 S {' U% H" h1 o - {
* Z' d+ g! H4 I( e" ~. [ - , Y5 q! b1 R& u/ V. i
- 1 g- U# W; Z; ~6 P% z8 z
- /* Get the RTC current Time */, n$ v, R8 B+ t8 U" j: r ^- c. U
- HAL_RTC_GetTime(&hrtc, &stimestructureget, RTC_FORMAT_BIN); x' _2 r3 A8 V, f: L6 _% S4 u$ i
- /* Get the RTC current Date */
# d) i" p1 }* |$ d6 Y5 D - HAL_RTC_GetDate(&hrtc, &sdatestructureget, RTC_FORMAT_BIN);
* g3 A. {8 n) r5 H; d, w- B - /* Display time Format : hh:mm:ss */
; Q- }( h; y3 K- R \0 w+ S7 d - sprintf((char *)showtime, "%02d:%02d:%02d", stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds);
/ o i* W+ @5 o/ n+ a- {( _ - }
复制代码
" V7 m& H/ s) S% I1 f3.standby进入函数0 k- D' w- t' D: Z# O3 E
- /* USER CODE BEGIN PD */: y3 K" s$ e% X! Z
- void Sys_Enter_Standby(void);) N/ {* U8 C0 b" j) l" J0 q7 D
- /* USER CODE END PD */
& q( k4 m8 i+ ~# k - 2 f: ^# u) O$ [6 s( S
- void Sys_Enter_Standby(void)
7 L$ m; ]/ } W% H, U: ?; T3 H- k - {) Y/ u9 ~/ |7 @9 m
- /* The Following Wakeup sequence is highly recommended prior to Standby mode entry9 |" Z+ L. }2 f; z- k7 q+ E, g
- - Enable wakeup
7 ?1 b* ^ Q3 p8 X5 k - - Clear wake up pin flag depending in edge detection & pin level.
# e1 [; G# a5 Z( L9 h2 Z - - Enter the Standby mode.
2 I1 H% F U q x/ r - */
3 @, p2 A3 |% M/ ^2 Z* D - ! z( f) s; {5 G
- /* Enable WakeUp Pin PWR_WAKEUP_PIN2 connected to PC.13 */
, }( N$ d7 p9 T. a+ l0 z' D - HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2_LOW);//上升沿触发- ]' `- s. }0 u# Y8 n
- HAL_PWREx_EnableInternalWakeUpLine();
' ]5 T9 D# o) d - /* Clear all related wakeup flags*/
, f7 f) E/ Y. Z' D - __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF2);
, A( f: b6 K9 r8 |' D/ O, ^, u" |5 a" ?& x
: h' Y8 I" U# _. M! u! A- /* Enter the Standby mode */
3 N E d/ c4 |" z5 Q; e - //HAL_PWR_EnterSTANDBYMode();
6 j( D3 p* O$ g( Q; t% R; ~3 i - printf("enter Shutdown Mode!");
2 l0 t' c! o% K6 H' a - HAL_PWREx_EnterSHUTDOWNMode();
9 @# f& [& s0 g) G% J2 b - . ]$ `& V: F( O- u3 j' w! Z
- /* This code will never be reached! */
" ~3 D2 [; a# {) y m - }
复制代码
( \ ?2 i1 ]' X1 t! \4.ALarmA中断回调函数 NVIC_SystemReset()用于standby触发AlarmA时间后与wake_pin触发系统自复位不同进入rtc中断后无法复位问题(我解决不了就软复位)
0 [6 p9 F% S' _4 o+ ]3 a6 O% `- void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc), M0 H* q( u' {( y' X2 m, w7 K
- {
0 ?) B. G% e3 w) f1 M7 ~) E - /* Prevent unused argument(s) compilation warning */. N; m. c D0 [8 F& v
- UNUSED(hrtc);! l0 x! o1 b7 |( d" U
- 9 `4 z6 B3 D, A8 Z) i! M/ [; m0 A
- /* NOTE : This function should not be modified, when the callback is needed,
\! x% c2 \, o/ f8 S - the HAL_RTC_AlarmAEventCallback could be implemented in the user file/ j& X% q) O( r
- */
: w- x5 N2 P) n3 b% A - , o5 j+ w* S# {: M4 f4 e; |9 d& c
- flag =1;, X% u S' x1 o: l
- // NVIC_SystemReset();
1 _9 M7 i! f1 R1 E! c+ t7 W2 J! u -
4 Z" T3 d- F1 U" n - }
复制代码 ^) K1 T, ~# H% [
5.在main函数中5秒的时候进入低功耗模式
# d* k; I1 x, y) P* w2 w6 N- /* USER CODE BEGIN 2 */
9 j( C1 t9 k, C' U - uint8_t sec=0;+ f' t4 L* \3 W
- if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET)
: S" \2 I; g2 |9 u - {
$ p; \, p) x1 i. P - /* Clear Standby flag */$ `$ }# D! y+ Y: ~4 e& L$ ^
- __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);& X: c H' D: H( x
- printf("wake up from standby!");6 j0 R x2 ?/ \/ h' ]- ]' e5 m
- /* Check and Clear the Wakeup flag */
! o1 _" R3 Y0 |0 I - if (__HAL_PWR_GET_FLAG(PWR_FLAG_WUF2) != RESET)
! Z* d3 G3 Q3 H1 o5 N$ F& s - {
- ^( `" D" F. W0 s& ?8 v1 q - __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WUF2);
: L+ ]! @0 P" t7 l3 Y% i - }
" f- X* a4 \& P% G1 s+ c" u# V! Y% o! T -
' K& Z# C: e' c: D, T& W3 `! a - /* Wait that user release the User push-button */
) B, k! s! j! Q - while(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET){}
i7 ^- K/ L0 p6 s! H4 T - : h9 e. C2 n- e |" y' r# \3 b
- }, [7 r1 o+ w) M. o8 g! y
- - U" g9 p2 x/ b% @9 L1 Y! A, h
- 3 g8 M0 I8 j/ X* k, G& U& y
- /* USER CODE END 2 */
+ @& Y+ B# G& K; H5 w% `9 k7 j& n) K
: ~) o- x6 `" E9 U" I- /* Infinite loop */$ N9 O' g8 g7 c' A* p2 m
- /* USER CODE BEGIN WHILE */% d# c: D, S. w
- while (1)
u6 w; S6 w5 L - {/ E; t5 ^; `# C$ C7 L
- /* USER CODE END WHILE */
9 G" Z7 V! G) p/ g4 o) `; Y - / I: R z$ a9 C3 g0 i+ J4 [" b
- /* USER CODE BEGIN 3 */
% {; {9 B# ^: E! b - RTC_TimeShow(aShowTime);
9 W* C) E9 [ g+ U5 o - if(sec == 0)flag=0;
R: Z+ l7 h! g6 W - * l, F" ?2 f' m9 m% e( O3 c. ~
- if(sec == 5)Sys_Enter_Standby();
' R" d" Z7 l7 ^2 U6 j% Z/ N - if(sec!=stimestructureget.Seconds)
1 t! S9 s5 C* L, v - {! S0 @$ ]/ Q# `2 O: \8 n2 l
- sec=stimestructureget.Seconds;
1 h) ?8 \- ?; ]6 w1 S - printf("%s",(char *)aShowTime);6 N8 ?9 C0 Y/ s, F- `
- if(flag) HAL_GPIO_TogglePin(LD4_GPIO_Port,LD4_Pin);
1 D; o: n) \& J- y0 z I - }
# X6 z" J7 g& V- w3 n - }
: I9 K5 q9 p T2 U$ ^, | - /* USER CODE END 3 */
/ c' v; S5 X% |, g0 u3 ^ h% H/ N - }
复制代码
: g* L" W% L& f# m! N6 _1 o. p; n0 x9 m至此STM32G071关于低功耗模式的进入与退出已经可以实际使用,大家可以参考,实际使用稍作调整。
' E4 U3 @2 ^# \3 P- T
% m) K, M+ Q, [: Z% C附加 避免上电自动配置RTC时钟" \: d8 _" o& q: N" Z5 W! V
- /* USER CODE BEGIN Check_RTC_BKUP */
# s N0 c! |+ I: Y% \ - if (__HAL_RTC_GET_FLAG(&hrtc, RTC_FLAG_INITS) == 0x00u){}2 C) U( J# N- c: y1 H N' e
- else{return;}
+ P# ^' I1 O/ }8 O3 s - /* USER CODE END Check_RTC_BKUP */
复制代码
7 C4 ]; j- B3 ~& D以上代码请添加于MX_RTC_Init(void)中" n/ o# Q- f6 M; f& `
2 }) V8 X5 v0 | b3 W. t
7 c* b" q; T" x# ?! K) b' {3 c. ^! z. r: Z$ q9 u, r* I. D" C
项目文件. p4 T, j" l" A# B
- q) X" }3 e, F* p' W3 z, \& h4 d- v# l9 o# A7 `1 `
4 M5 \2 m' ~; Z
' K& E2 g$ k- G* n* U |