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

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

[复制链接]
wolfgang 发布时间:2017-7-5 22:53
前篇链接:
% n  k3 m2 A' u7 z  lST线下培训(05-23成都站)STM32L476低功耗设计(一)

* e: A5 _$ A" I. W) S; h# E
ST线下培训(05-23成都站)STM32L476低功耗设计(三)   

2 T: x! V8 T8 ?! i% k- Y6 M
——进入Stop2模式,延时5秒后唤醒

! Q# v7 n" o1 ]$ B$ C% L- }0 I8 V
& Z/ _# V! c9 r5 ^; l

8 ?# `, C; J0 l1 D) x: e
一、实验开始之前
    上一章节次实验实现的是进入低功耗后测得的电流值,但在要在实际应用中,只能进入低功耗是不够的。需要能进入低功耗后根据实际需要和应用场景实现频率、电源的恢复,能恢复到进入低功耗前的处理能力。本章就针对进入Stop2模式 后的经过RTC定时五秒后恢复进行数据测量。

) O0 A+ g' {  o: L, g二、实验过程1、实验前探索
1.1 RTC时钟源选择
  在正式实验前,将功能树上的是RTC功能打开,并在时钟树上查看RTC时钟源频率。
; B+ L6 L4 ]  T, v$ ^8 V2 S
( X5 M9 c/ f* {& [6 a% h4 L  I2 U
01.jpg
% i/ y; m$ H2 v7 r7 n+ I
) j* _8 u0 Q4 j! i
02.jpg

+ i/ j# u( m9 V6 f+ `. h
0 e% Z- V' T: ]" Y) @+ v
   从时钟数可以看到RTC时钟频率使用的是LSI RC的32KHz的频率。当然也能选择LSE或者HSE的RTC分频后的时钟作为RTC时钟源,进入除Shutdown模式外的低功耗(因实验中板卡为Nucleo L476RG 缺少LSE,无法对Shutdown模式进行唤醒,需要另外焊接LSE 的元器件后方可进行实验),将时钟源统一为LSI 的RC,具体的产品环境根据实际需要选择时钟源。
1.2 时钟源相关设置
03.jpg
7 j/ B( u" p" M4 ]% L& r
  设置唤醒时钟为 32K的16分频,频率为2K,唤醒定为5秒后,这里设置5*2K=10K次。

. U' _2 b2 ]) X7 n
设置唤醒中断使能。
04.jpg
1.3 LSI时钟功耗
将LSI、RTC始终设置后,因增加了设备,会增加进入功耗时的功耗值,分别测试打开LSI、RTC后的功耗值如下:
RUN:              15mA;(外设功能活动)
SHUTDOWN:      0.09uA;(外设功能停止)
STANDBY:       0.68uA;(外设功能停止)
STOP2:         2.13uA;(外设功能停止)
LPSLEEP2MHz:     87uA(外设功能活动);

/ T* q0 T, N$ K5 o% N: N% Q
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){6 H5 }, `# G& O# X( P
  2.          RCC_OscInitTypeDef    RCC_OscInitStruct;( ]% m: M5 r$ _; e
  3.          RCC_PeriphCLKInitTypeDef    PeriphClkInit;: U& t7 y/ ]7 h9 y2 O. a
  4.          RCC_OscInitStruct.OscillatorType=RCC_OSCILLATORTYPE_LSI;
    9 B' A2 w: |6 n- ]9 i. u
  5.          RCC_OscInitStruct.LSIState    = RCC_LSI_ON;
      e% c8 \. Q, a) P
  6.      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    % ~2 I6 M  V' @1 p1 T+ h# @0 p
  7.      {9 y6 y6 A* g4 j$ \) |& t* S
  8.        _Error_Handler(__FILE__, __LINE__);
    % V: p0 e- d0 O9 C% J  Y# T
  9.      }
复制代码
  1. PeriphClkInit.PeriphClockSelection    = RCC_PERIPHCLK_RTC;
    5 b8 K" X0 z- n- z+ h+ C
  2.          PeriphClkInit.RTCClockSelection    = RCC_RTCCLKSOURCE_LSI;   S; E6 L, j: n- b
  3.          if    (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)+ Y2 B# _9 D7 v8 b. [
  4.      {* @( h$ J2 H# k; J9 M0 f
  5.        _Error_Handler(__FILE__, __LINE__);: e4 I$ }7 n0 L+ Z9 l
  6.      }6 {" E( m# P: k

  7. 2 s" V( ~) `0 ^  Q8 e* g
  8.      /**Configure the main internal regulator output voltage
    $ e) d1 v7 e- }7 `, H, z$ L( f
  9.    ( f! H) }6 \2 ~; C0 J0 q0 |
  10.      */. E/ A1 V3 C% S, ^  c6 a  }: P( s
  11.      if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) !=    HAL_OK)
    6 t4 K3 Q1 _$ b- S: h
  12.      {. U0 s& A1 h! P, t) A7 r
  13.        _Error_Handler(__FILE__, __LINE__);1 A# A5 K! W: i/ u& j5 T) y
  14.      } ' T5 V5 g1 M+ ?+ b1 Z3 v
  15. }
复制代码

; ]0 u# X+ C4 B$ b* p
; X7 r) }8 D" Y5 S% Z! A
RTC初始化,过去早的初始化RTC,增加正常工作时的功耗,若需要RTC在项目全生命周期工作的情况除外。
  1. tatic void MX_RTC_Init(void)
    . l3 f, _: A5 z
  2. {6 Q8 ^6 }0 H- A) F) V  d- f5 ?
  3.      RTC_TimeTypeDef sTime;
    ) q) {' c/ G3 o5 K: n, u
  4.      RTC_DateTypeDef sDate;
    " Q2 e9 }! Q0 C7 k
  5. 5 ^0 s# Y: q+ M
  6.      /**Initialize RTC Only
    $ a# |/ `/ d" `: w
  7.       */$ A$ M8 N: m( Z9 Q2 j6 {
  8.      hrtc.Instance = RTC;
    9 h9 x. `3 `' Q6 l. M7 W
  9.      hrtc.Init.HourFormat = RTC_HOURFORMAT_24;% {% U: ~+ _+ |4 f: Z/ V
  10.      hrtc.Init.AsynchPrediv = 127;
    ( z3 t) i# f6 M- ^# j
  11.      hrtc.Init.SynchPrediv = 255;& c( O& f& _. l8 a
  12.      hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;, o( b! |) \& }) e
  13.      hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;5 Z2 W& y5 m! u- S5 l! V! u
  14.      hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;2 K: f' R% R* z9 u2 w
  15.      hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
    5 ~, P5 k# E+ k6 q; d
  16.      if (HAL_RTC_Init(&hrtc) != HAL_OK)' J2 \$ F& `2 R6 o' ^, Z7 D
  17.      {4 x0 n4 b: ?5 d
  18.        _Error_Handler(__FILE__, __LINE__);
    7 Y9 h; P) {3 _- O- C$ ^
  19.      }
复制代码
  1. /**Initialize RTC and set the Time and Date6 K, B3 m7 v3 U
  2.    
    7 u. y: W' ?# ?! a( Q! k
  3.       */4 W2 g. U# G+ A& C
  4.      if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) != 0x32F2){
    1 t. o. J8 f& L* ]" I: ^
  5.      sTime.Hours = 0x0;
    + E. F) s& X; W7 n
  6.      sTime.Minutes = 0x0;
    / T' e, M- ]# Q* _5 Q
  7.      sTime.Seconds = 0x0;$ [+ @0 G/ J$ n9 u6 v3 i! i: u4 n
  8.      sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    * y8 U3 v" Z" ?! b" g/ ^* ~
  9.      sTime.StoreOperation = RTC_STOREOPERATION_RESET;
    4 ]  i3 S: @, }/ S% n" X
  10.      if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) !=    HAL_OK)
      E7 q7 Y7 H' ]
  11.      {
    % W) |5 a; v3 T8 {* _7 W" p& S/ Y
  12.        _Error_Handler(__FILE__, __LINE__);
    , }0 f- T+ W2 C1 W( Z8 S
  13.      }
      G; |# u. o0 U/ D2 B3 X
  14.   k. k( O3 y+ v4 Z4 I# v" c$ Y5 _9 k
  15.      sDate.WeekDay = RTC_WEEKDAY_MONDAY;( m) N( e" K: V* K
  16.      sDate.Month = RTC_MONTH_JANUARY;
    + l1 q, p6 ^2 U5 c! _& Y! G" y
  17.      sDate.Date = 0x1;
    5 {4 i# m1 W% C) \! t# e
  18.      sDate.Year = 0x0;3 B% W# d. k; N
  19. & C8 `+ Q+ ]2 F
  20.      if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) !=    HAL_OK)6 q: n( d# S& r  H% \/ H* ]
  21.      {3 l/ S. S) e' s) L+ Y; B
  22.        _Error_Handler(__FILE__, __LINE__);
    8 @0 N) r8 I3 t5 h- Z5 Z' e
  23.      }7 Z8 m4 ?) H) E0 T
  24. 2 ]% B) S5 G# g+ q$ T: Q6 ]
  25.        HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);; o/ p7 c$ ?, h  k0 p
  26.      }
    6 a, B" L: ?. p" x# F# f7 C# m
  27. }
复制代码
2 M/ R- {" ^" t$ t: h
. X8 Z5 B1 A2 D3 I
设置RTC从STOP模式唤醒后的系统时钟以及事件唤醒中断:
  1. HAL_RCCEx_WakeUpStopCLKConfig(RCC_STOP_WAKEUPCLOCK_HSI);
    6 M7 S: `! _) K* |/ e; X6 r( N' |0 m/ a
  2. HAL_RTCEx_SetWakeUpTimer_IT(&hrtc,    20480, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
复制代码
' e$ \/ m; T& h$ r
随后就能进入STOP2模式了,直接调用Test_Stop2()。
' Q9 G# K7 [5 E
: z# m, C! s# m0 ?: l. @# K
在进入STOP2模式后, 经历RTC计数到达唤醒设定的延时时间,及触发RTC_WKUP中断,
在HAL生成的中断函数里调用了唤醒中断函数, HAL_RTCEx_WakeUpTimerIRQHandler(xxxx),
其中的HAL_RTCEx_WakeUpTimerEventCallback()回调函数,是需要根据开发者自己定义的,: w* m+ ]$ Z  ]
7 Q* B5 ]& M2 f; M' K6 Q
9 v0 ^% O* h8 c! H$ I
  1. void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) {
    " B3 d6 z( g4 h# b5 j+ `  K
  2.         WakeUpState=1;- k$ N, z$ b0 [( k/ v
  3. }2 v6 S1 s/ A& M- ~3 V' {8 n
复制代码
考虑到唤醒中断优先级,这里只标记唤醒状态,具体唤醒后的操作交由主循环中的内容只执行:
  1. ........2 R0 i4 s& ?/ K6 H# b
  2.      if (WakeUpState){
    / r+ T, Z8 ~  P1 ^8 U
  3.                   WakeUpState=0;) e2 j) P. Q$ m* w- @! K. s2 U
  4.           //禁用RTC 定时器WakeUP,避免再次出发唤醒
    - d* I4 @* _5 u' ]
  5.                   HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
    - V# o% ]2 M" W9 v8 X' Z/ w/ k
  6.                   //初始化变量及引脚功能6 H' y7 Z4 `8 _" E' s- f: z
  7.                   EXTI_State = DISABLE;) p5 p) l! |) K) d0 }8 t
  8.                 9 R/ Y3 o3 M+ Y, l" d- \9 C: n7 X
  9.       //HAL_Init();# v) P& J6 R* w' A" |
  10.       SystemClock_Config();$ P, X" E  N6 ?
  11.       MX_GPIO_Init();
    , n5 r% G4 u& l3 w0 [4 g
  12.       MX_USART2_UART_Init();* [" l+ h  W" o  Y) p' p
  13.       printf("\n\rWake Up From RTC  \n\r");* X! {% y& g+ j3 Q" N5 e$ ]
  14.           }4 d. \4 r2 h6 c
  15. ........
    ! }9 J: @& C4 V
复制代码
至此,RTC 唤醒的功能就完整了
3 o- X: S. ?! h- j+ s7 x" H) s
STOP2 状态定时5秒唤醒动图:: p+ F1 U! h) |* I$ O
STOP2 停止五秒唤醒_20170706230845.gif / F" K& H+ R) \7 F0 U

: p& l8 I% _) d# y* u% `/ {3 Y( J7 g4 r. J2 l* r

" `( e5 J) M7 E( m- O( \# @  M3 H+ d! b$ C
代码参考前一章节的内容作了适当调整,见附件Main.rar  G- h) w1 v' V

5 R+ D% F# ^( E$ H 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
哇哦,楼主又有更新了,过来支持下7 a& G; y# p. [
$ T% q. h+ n* p
帮楼主把代码部分格式改了下,下次也可以这样操作哦
8 H* X( m  K5 u/ P! @ 1212.png
1 e# _6 J/ J3 M! H
wolfgang 回答时间:2017-7-6 10:25:01
zero99 发表于 2017-7-6 09:59
' c/ L/ p$ l1 {$ N哇哦,楼主又有更新了,过来支持下6 L% ~. j; a7 g; F: J/ d" ]  g

5 B) {% w6 Z+ c5 A) O帮楼主把代码部分格式改了下,下次也可以这样操作哦
3 y) N0 x: P( k) S" e3 n
好,谢谢~~
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 手机版