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

ST线下培训(05-23成都站)STM32L476低功耗设计(三)

[复制链接]
wolfgang 发布时间:2017-7-5 22:53
9 g; [# U5 S2 f4 @
ST线下培训(05-23成都站)STM32L476低功耗设计(三)   
8 K4 A  w, B: F# T
——进入Stop2模式,延时5秒后唤醒

$ ~  s1 U+ t" {( m% E0 D6 H$ E0 \' s, t1 L# e3 d" u2 y

; t+ d7 k9 b5 ?* a, G
一、实验开始之前
    上一章节次实验实现的是进入低功耗后测得的电流值,但在要在实际应用中,只能进入低功耗是不够的。需要能进入低功耗后根据实际需要和应用场景实现频率、电源的恢复,能恢复到进入低功耗前的处理能力。本章就针对进入Stop2模式 后的经过RTC定时五秒后恢复进行数据测量。

$ w6 z8 v  o, p' o3 h$ k二、实验过程1、实验前探索
1.1 RTC时钟源选择
  在正式实验前,将功能树上的是RTC功能打开,并在时钟树上查看RTC时钟源频率。

; l" `  r6 B4 w1 O$ q) b1 h  _
01.jpg

4 a0 ?1 _  Z1 U% d4 P7 Z# I7 u: C
% @% Z  S+ c- b6 @
02.jpg

: ~6 q6 D2 ?; w9 g: Y* `7 L
- E% V* T. a$ A- @6 F5 i
   从时钟数可以看到RTC时钟频率使用的是LSI RC的32KHz的频率。当然也能选择LSE或者HSE的RTC分频后的时钟作为RTC时钟源,进入除Shutdown模式外的低功耗(因实验中板卡为Nucleo L476RG 缺少LSE,无法对Shutdown模式进行唤醒,需要另外焊接LSE 的元器件后方可进行实验),将时钟源统一为LSI 的RC,具体的产品环境根据实际需要选择时钟源。
1.2 时钟源相关设置
03.jpg
# h! h+ Y+ `4 u. }3 f+ i
  设置唤醒时钟为 32K的16分频,频率为2K,唤醒定为5秒后,这里设置5*2K=10K次。

9 M0 v4 n0 ]5 b% I$ `2 L
设置唤醒中断使能。
04.jpg
1.3 LSI时钟功耗
将LSI、RTC始终设置后,因增加了设备,会增加进入功耗时的功耗值,分别测试打开LSI、RTC后的功耗值如下:
RUN:              15mA;(外设功能活动)
SHUTDOWN:      0.09uA;(外设功能停止)
STANDBY:       0.68uA;(外设功能停止)
STOP2:         2.13uA;(外设功能停止)
LPSLEEP2MHz:     87uA(外设功能活动);

1 W# o7 Y  n* B' L- ?  d0 o$ x
2、实验步骤
2.1 Stop2 模式使用RTC计数5秒后唤醒
2.1.1 唤醒方式LSI+ RTC
    进入Stop2模式后,除LSI、LSE之外的所有时钟都将关闭;
    触发唤醒的事件有:任意一线EXTI(已配置的EXTI寄存器)特定外设事件。
    唤醒后的系统时钟有两种情况:
       1、STOPWUCK=0时为进入Stop模式前的MSI频率;
       2、RCC_CFGR寄存器中STOPWUCK=1时为HSI16;
进入Stop2模式前,设置好低功耗模式的时钟:
  1. void Low_SystemClock_Config(void){
    0 U; e! p" W0 S! n6 a( Q
  2.          RCC_OscInitTypeDef    RCC_OscInitStruct;! r6 v( A- w! |' f0 H8 q$ [
  3.          RCC_PeriphCLKInitTypeDef    PeriphClkInit;; e+ Y# l) c! Q( f# U4 J
  4.          RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_LSI;
    8 w) ?, h+ _: H) v2 }! x, `
  5.          RCC_OscInitStruct.LSIState    = RCC_LSI_ON;
    $ z0 I$ ?+ A/ S/ f0 p; V, g
  6.      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)+ F' v& G$ X% k  R; J) ^
  7.      {
    ' V/ g( Y) _9 v6 N  F# w% C: U
  8.        _Error_Handler(__FILE__, __LINE__);7 i! P# D( f2 v+ S  n7 t- D" b- m* R7 O
  9.      }
复制代码
  1. PeriphClkInit.PeriphClockSelection    = RCC_PERIPHCLK_RTC;7 d8 z7 G* P: O0 u  i% ?5 S3 z
  2.          PeriphClkInit.RTCClockSelection    = RCC_RTCCLKSOURCE_LSI;
    ' h" Q; `. O' Q' e/ z5 S
  3.          if    (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK). M4 ]9 ~- n) K6 |
  4.      {
    8 c# t2 D9 z. K
  5.        _Error_Handler(__FILE__, __LINE__);6 C6 `; o' g& @& k; ~) ]9 u7 O
  6.      }4 n, U  P! C7 t- H

  7. 6 Y; @$ W/ d4 c, ]
  8.      /**Configure the main internal regulator output voltage; L/ M) e) N2 A7 H9 @2 h+ Z
  9.    9 C# N5 l2 E# b1 O. Y/ S" w$ |) l
  10.      */
    # _, E# [' z8 g7 `0 Q1 V" i' G
  11.      if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) !=    HAL_OK)8 h- L- m  j% ?
  12.      {1 q/ w% c7 ?5 \! F
  13.        _Error_Handler(__FILE__, __LINE__);
    2 _( k$ v2 l  |
  14.      } # s: d& `" Y4 ~/ p0 @* H3 q! x  O
  15. }
复制代码
/ `2 w* H( E$ h9 t% h
1 w5 ^# K2 a5 p; \# q: N/ w+ Y
RTC初始化,过去早的初始化RTC,增加正常工作时的功耗,若需要RTC在项目全生命周期工作的情况除外。
  1. tatic void MX_RTC_Init(void)
    1 h$ X. ^% J8 h8 m& r4 @
  2. {
    . _+ H! m! q/ ~. \2 C  N1 W
  3.      RTC_TimeTypeDef sTime;
    $ b* B1 t) z+ n% Q& v: {
  4.      RTC_DateTypeDef sDate;4 W$ T  E1 J8 s7 X* S- F& X. N& O

  5. 2 h! i7 p$ X1 a: m8 s8 k4 b
  6.      /**Initialize RTC Only
      W" U% }4 F; e
  7.       */
    4 S; f0 o6 d6 h9 v+ L  r9 f
  8.      hrtc.Instance = RTC;3 w4 P8 j" T3 K: k
  9.      hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
    $ B8 ~  ^0 ]/ m
  10.      hrtc.Init.AsynchPrediv = 127;2 P1 }* o* e' d, H9 L$ |: `& K. e9 G
  11.      hrtc.Init.SynchPrediv = 255;
    # C1 Y. \4 k( T: w3 o) B8 V1 @' G
  12.      hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;' O$ Q! @0 W- I" I  R
  13.      hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
    3 _9 I% s2 g. n  j9 Q6 f, y
  14.      hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
    4 q* m, T6 B( x0 o0 z  p
  15.      hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
    . `8 b5 y$ ?' k: Y6 ~0 K4 \) Y. T
  16.      if (HAL_RTC_Init(&hrtc) != HAL_OK)
    ) C& L& v- H+ z$ s  b
  17.      {
    1 J( E# z4 c7 D6 f9 U  `3 F
  18.        _Error_Handler(__FILE__, __LINE__);9 A  J# b0 a5 O* Y" Q7 E7 h4 i5 n' ?% h
  19.      }
复制代码
  1. /**Initialize RTC and set the Time and Date
    6 F& {1 r& ^. v4 y
  2.    
    1 g  Y# ?4 H9 e6 ?! T
  3.       */+ O6 C2 t7 S1 B. f& R# c! {( `, q
  4.      if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2){
    - w1 r, @2 Y, p( Q
  5.      sTime.Hours = 0x0;( S0 @( s" t- K
  6.      sTime.Minutes = 0x0;4 I8 E: v2 ?, s- X& L9 l
  7.      sTime.Seconds = 0x0;- c+ _: G2 u* z3 P/ X5 \
  8.      sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    1 K0 f( t6 K' ]) m0 m; E
  9.      sTime.StoreOperation = RTC_STOREOPERATION_RESET;
    2 Q+ X  A/ O  `
  10.      if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) !=    HAL_OK)
    0 d: }) o+ t2 \% S! S
  11.      {6 h  O3 Y. Y( g+ C& `. S
  12.        _Error_Handler(__FILE__, __LINE__);% p1 Q6 ~# ?9 p  f# G3 t+ E. l+ a
  13.      }; u( G: Y4 O" _

  14. # e1 \" D" c, i) u: h
  15.      sDate.WeekDay = RTC_WEEKDAY_MONDAY;1 }* B! D1 {% a) t# M0 y0 v; a
  16.      sDate.Month = RTC_MONTH_JANUARY;
    - [9 a2 `6 j2 i9 P
  17.      sDate.Date = 0x1;4 t& t5 S( C1 N/ K% g, |) k
  18.      sDate.Year = 0x0;
    # x1 t3 k( e* u' p& J% Q6 u# p

  19. / L. K$ r( _, i% s0 V- F" S
  20.      if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) !=    HAL_OK)! Y: g! l' \! U9 h; y- a
  21.      {" G7 l* q6 H- ^  O6 \% Y5 z
  22.        _Error_Handler(__FILE__, __LINE__);6 ~( n% B& r1 i2 r
  23.      }' o7 M' o+ i  ?3 D! F

  24. & y5 t3 r  J: L4 E) }0 N" X
  25.        HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);
    $ ~8 }2 |+ D# x/ i* Y
  26.      } - x6 C* D7 T& I. R1 r$ }; q: a
  27. }
复制代码

% x. t0 T. n3 F. v' ?1 R& R0 j& }; q
设置RTC从STOP模式唤醒后的系统时钟以及事件唤醒中断:
  1. HAL_RCCEx_WakeUpStopCLKConfig(RCC_STOP_WAKEUPCLOCK_HSI);
    , R( A3 K+ q8 [4 V# y
  2. HAL_RTCEx_SetWakeUpTimer_IT(&hrtc,    20480, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
复制代码
$ W/ K& k8 D, r& l, W2 Y" t- c
随后就能进入STOP2模式了,直接调用Test_Stop2()。
$ f* k5 v  F9 |* c& k# U
1 `9 Y0 a: ]6 C9 y  [; G
在进入STOP2模式后, 经历RTC计数到达唤醒设定的延时时间,及触发RTC_WKUP中断,
在HAL生成的中断函数里调用了唤醒中断函数, HAL_RTCEx_WakeUpTimerIRQHandler(xxxx),
其中的HAL_RTCEx_WakeUpTimerEventCallback()回调函数,是需要根据开发者自己定义的,% U  G' _* Y; Y+ W/ `+ I+ p) e
* M; z$ P7 p- Y5 k# Y$ H

3 F4 P! w* G6 u% m# x8 i  E. p
  1. void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) {1 w+ U# T7 V1 K) K
  2.         WakeUpState=1;) _$ j1 c1 S- t0 v
  3. }
    4 \/ @  I6 F7 F& H
复制代码
考虑到唤醒中断优先级,这里只标记唤醒状态,具体唤醒后的操作交由主循环中的内容只执行:
  1. ........( l+ _+ C* R0 n" q' d' }: g3 x; B
  2.      if (WakeUpState){% J& n+ [4 a" _1 Z4 l3 V( p4 a
  3.                   WakeUpState=0;7 {: U2 x5 S/ R( M) P5 ]% D# B
  4.           //禁用RTC 定时器WakeUP,避免再次出发唤醒1 i4 `& E) k7 C# s) ]; ~  j" T
  5.                   HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
    5 k7 K& i1 C$ V( Y- ?7 P7 L: [# N; P
  6.                   //初始化变量及引脚功能2 S6 f+ S' u. s& X9 j) e
  7.                   EXTI_State = DISABLE;" t: C1 B5 g/ E8 n5 z1 [# Z
  8.                
    - e" d; e6 b; g& o! l" Y
  9.       //HAL_Init();/ S* _( ]3 ]& ]: y" n! D6 s
  10.       SystemClock_Config();
    # o8 k/ @9 |, g9 z* \: X
  11.       MX_GPIO_Init();
    8 O' i' u7 `3 O% i+ q$ \1 Z* Y
  12.       MX_USART2_UART_Init();
    ; D. X' J* ^% T' a
  13.       printf("\n\rWake Up From RTC  \n\r");7 `/ ?! {7 e& v7 `$ V5 r/ {
  14.           }
    5 m6 W+ G& J3 [+ i# s
  15. ........
    0 x1 J0 r- B1 {3 B, S  L
复制代码
至此,RTC 唤醒的功能就完整了

7 M/ ~" Z; j+ M  A# a; cSTOP2 状态定时5秒唤醒动图:" A" Z+ l! H2 _
STOP2 停止五秒唤醒_20170706230845.gif - {9 y' v# W5 B0 @5 q; T- i/ B3 M

$ M  [$ r% V0 J/ H# q
' _9 j/ ]8 q$ s7 V1 H$ }- X# y
$ \7 m. R8 V8 s0 `! k. Q  z+ u& u# y+ ]  Y5 E' \: W# V4 y
代码参考前一章节的内容作了适当调整,见附件Main.rar0 u* _6 K( x) R% X

. a4 L7 T$ o7 F9 Y9 M* U main.rar (6.04 KB, 下载次数: 125)
收藏 1 评论7 发布时间:2017-7-5 22:53

举报

7个回答
wolfgang 回答时间:2017-7-5 23:09:30
最近工作比较忙,再加上电脑重装系统,这篇文章等得有些久了。。。。
Paderboy 回答时间:2017-7-6 08:43:26
多谢分享。。
zero99 回答时间:2017-7-6 09:59:27
哇哦,楼主又有更新了,过来支持下
$ ]. i/ _& T5 i1 y2 p1 C
7 ^0 H. {, s3 k, P6 F+ ~/ c3 n2 I帮楼主把代码部分格式改了下,下次也可以这样操作哦
( e! T2 W6 `% S7 S, U* p4 C 1212.png
- F! V  \6 F4 p
wolfgang 回答时间:2017-7-6 10:25:01
zero99 发表于 2017-7-6 09:59
- D+ m& E5 `# R$ a哇哦,楼主又有更新了,过来支持下
. R2 B* [% b& O" E9 N: F
0 i' i5 Q; d6 R0 O6 w  o! d帮楼主把代码部分格式改了下,下次也可以这样操作哦

. y2 _' [) f4 O1 ~( U& U好,谢谢~~
epochal 回答时间:2017-7-6 11:15:59
谢谢分享!
wolfgang 回答时间:2017-7-6 22:13:54
唤醒的代码说明补全了
世事莫太贪-255746 回答时间:2020-1-9 10:08:31
谢谢分享
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版