本帖最后由 wolfgang2015 于 2017-7-5 22:55 编辑 : x5 ~$ m; y0 W4 N
' \/ b( |6 h. u9 n4 W* g后篇链接: % p$ F! N+ w# h$ O ~
V0 q9 q, b) S6 c% L6 A
2 M# w9 S8 D$ _7 ?1 JST线下培训(05-23成都站)STM32L476低功耗设计(二)
7 }' p' A+ {% {6 `. b0 r——实际测量STM32L476 板子在不同功耗模式下的功耗值 & s, ~- U: j/ ?, M" e( h+ T/ S
/ @- S& v" K. l" o/ b3 u1、实验目标及原理分析操控STM32L476开发板在以下低功耗模式后测得低功耗值: 1、Shutdown; 2、Standby; 3、Stop2; 4、LPSLeep 2MHz 按照官方手册提供的方法,进入低功耗的相关操作如下: 1)、如需要进入Shutdown模式,步骤如下: a) LPMS="1--"; b) SleepDEEP置位; c) 执行WFI()汇编指令 或 从ISR/WFE返回 在HAL库提供了进入Shutdown模式的函数,在stm32l4xx_hal_pwr_ex.h 中,使用HAL_PWREx_EnterSHUTDOWNMode(); 可进入Shutdown模式; 9 K# w( n- p6 C' n3 i
2)、如需进入Standby模式,步骤如下: a)LPMS="011"; b)RRS置零; c)SleepDEEP置位 d) 执行WFI()汇编指令 或 从ISR/WFE返回 在HAL库提供了进入Shutdown模式的函数, 在stm32l4xx_hal_pwr.h 中,使用HAL_PWR_EnterSTANDBYMode();可进入Standby模式; - c6 b' i4 ]- ` B
3)、如需进入Stop2模式,步骤如下: a)LPMS="010"; b)SleepDEEP置位; c) 执行WFI()汇编指令 或 从ISR/WFE返回 在HAL库提供了进入Stop2模式的函数, 在stm32l4xx_hal_pwr_ex.h中,使用HAL_PWREx_EnterSTOP2Mode();可进入Stop2模式; ) b7 a, G f) W
4)、如需进入LPSLeep 并使用2MHz系统频率,进入低功耗操作如下: a) LPR置位; B) 执行WFI()汇编指令 ISR返回; 在HAL库提供了进入LPSLeep模式的函数, 在stm32l4xx_hal_pwr.h 中,使用HAL_PWR_EnterSLEEPMode();可进入LPSLeep模式; 另外,需要限定MCU输出2MHz的时钟频率,需要在进入低功耗时对MCU的基础时钟频率进行设置,满足2MHz的系统频率。 & b$ _5 O# k7 L: D5 P
j, ?7 ~9 _2 @) P2 q- k1 X) t2 S) o$ @ {; F9 @1 E. h$ T [
6 o V* L# p' m; z* a$ ^: D: e3 p
2、实验步骤2.1过程CubeMX代码生成 a)、选择Nucleo-L476RG开发板 6 v/ J+ B% a Q" G
b)、使用默认引脚配置,并增加USART2的引脚PA2、PA3设置
+ C/ [; o Z1 vc)、使用默认的80MHz的SysCLK
1 D8 S& q: G! ~ g, z
* [5 q3 J+ |7 A& Z1 z d)、USART2设置: e)、GPIO设置: LED2 Pin设置
8 M& {, Y) N% kKeyPin设置
" p. @5 L& A% s9 e3 Z# M+ I {! s7 L) Q$ Y5 u
f)、NVIC设置 " A6 y- i* R$ Z; G; v. o
9 p9 w4 a8 M$ ~4 l1 { 以上搭建了基本应用功能,然后用CubeMX自动生成代码,然后再Keil中进行调试。 备注:这里搭建代码初衷是建立一个标准的工作状态运行环境后,再利用低功耗函数进入低功耗模式,最后通过表格将标准工作状态的能耗与低功耗模式下的能耗进行比较: 标准工作状态使用环境:MCU使用最大主频(80MHz);1~2个LED受程序控制正常闪亮;1个具备中断使能的按键;1个具备收发数据功能的串口设备。 . Q$ J! Q5 i8 z. d
2.2代码调试 之前的LED、按键中断、串口功能可以见之前的系列文章 这里低功耗核心功能函数如下:分别进入ShutDown模式、Standby模式、Stop2模式、LowerPowerSleep模式
" W! g* L% L5 m- /* USER CODE BEGIN 4 */
' e5 y6 a( _7 V -
7 S/ f% w9 `; K' I - ........ M- Z$ d& D4 f2 H4 a1 z+ R
- 0 T- \ S5 ]& {2 f5 U
- void Test_Shutdown(void){5 V! E/ i" x' t) O& W
-
E$ s5 Q! e# d7 l. @, J( J, r$ T - /* Enter the SHUTDOWN mode */ f+ q, N- v& f; @; `! ]
- 0 |2 k: X& L" C5 V
- HAL_PWREx_EnterSHUTDOWNMode();" h$ f' F/ f7 o6 B
- 7 a( r. I. _* b0 W
- }% G: h$ }9 @! n1 b
7 `3 q6 M; m; B+ `5 P' ^5 @8 Z3 V$ ~- void test_standby(void){8 }8 ~, T0 Q4 y/ i8 G8 w
-
8 q$ J( e m* U6 C* r - /* Request to enter STANDBY mode */7 @2 q! z( N" q( `
- 1 h6 ~7 B$ f$ Z8 B8 i
- HAL_PWR_EnterSTANDBYMode();
5 o& K6 z5 l+ _- L* ] - # t |. i5 }& M# Q+ L
- }8 o' P2 n# b0 y3 {- j; N& s4 \
- 9 [8 {, O; {0 L {) F R
- void test_stop2(void){
: _& w$ W2 \1 W- A j* J - }: y( q) u" R9 O
- /* Enter STOP 2 mode */
" s; I: c5 t4 Y K -
5 A1 i9 ^. I2 m0 G - HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFE);
7 }7 e4 j& i# W; H; V - 2 o: O/ Q- y7 v" E; z5 g1 l0 d
- }7 ~% f! @1 B5 e R5 q) o% @
- % i% q2 v( O" X( R7 z1 k" ^; @" }
- void test_lpsleep_2mhz(void){, h. C9 |* l7 {, O
-
) }3 X! A; E- s( g2 q - SystemClock_2MHz();% L X, E/ b4 b% }) k
- ( r; L A3 L8 c6 v3 K
- /* Enter SLEEP Mode, Main regulator is OFF */- z# L. B6 O3 ?
-
4 ` K/ Q. q1 {! j - HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);& a, x, i! K# K2 d! P
-
' K7 \" _+ {" v9 Q X - }
' ~7 l: S6 c8 I4 b+ H& W$ G$ X - / A: i" a+ d9 j) p$ K8 v( l0 `# u/ y
- ......( k, F! @: g- v# g6 }$ J
- 3 I# t: D& p0 b3 [4 Y$ F7 q$ v0 K
- /* USER CODE END 4 */
复制代码 ( a+ S4 V" v2 W* J- ^
5 Z/ ?& ^% e% k4 F, Q3 f
- void SystemClock_2MHz(void){
. g; X7 J6 O% O6 u; n -
1 j2 r# V: f: S0 E. p2 X6 B3 d - RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
5 e& O' L' O8 O: Y5 F( _% ?# U( t - 2 w3 W6 H5 ~6 ?3 Y. p% ^# w
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
2 s/ f, c2 a0 z# q( o1 D; z9 d - : U' X/ Z2 a( l" F& R7 \# d
- /* MSI is enabled after System reset, update MSI to 2Mhz (RCC_MSIRANGE_5) */
0 W; N7 o8 r+ W7 H& R - # N; H# ^! j7 B" P0 Y5 L* g
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;% R3 L/ C' B( Q* I! p6 R: v3 d% n
-
$ I& M( e" {! h' x$ z - RCC_OscInitStruct.MSIState = RCC_MSI_ON;
0 t- c/ e6 b. k - 1 O; \" X7 L8 Z$ |' S
- RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
6 W- O2 v( O/ q6 @4 ? -
/ X5 P$ J$ o" q1 H - RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;- @6 D0 I6 S* ]- M& V
- - U* H2 E# L" Q% K# P I9 c: m( i
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
$ p1 `& @. b- C1 ?: n - * t1 M# n, a% B$ J
- if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK): J/ b% H& X1 ]& s
-
" c- O5 @0 X J4 r0 @' @6 s% w - {
8 _* o9 N; d7 i4 L4 \ -
" c7 W$ U- s3 L' B; N9 A$ N$ v - /* Initialization Error */
$ a" P. [. W% E: ^( { -
6 L0 p7 O0 i: Z; p4 Y# J - Error_Handler();% ?5 t2 a7 k$ y$ d# D
- ' ]: C+ M& q0 w4 y, k; a
- }
: l1 v0 C4 `6 r3 J" q
. x: z+ O& h9 {" K6 i- /* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2
( V0 C G( l1 ?/ w8 \ -
% a# m# }' K- i6 x. o2 A" N - clocks dividers */
7 Y, j8 T: a5 n' U -
6 t/ g/ u8 A/ Y; F( d' o3 [4 l5 s4 @ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
5 L2 {5 E0 V: F- w' P -
7 C/ s+ s: i) W0 Z3 m+ ^ - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
' x6 s6 ^5 M: [5 F4 T# W' i - / {5 @( [7 \" P: ~9 d
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
& {2 }& d& C% q8 m - 2 J6 B; t8 u6 p! ^- a" i- A
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; ( ~) Y+ F% M7 ]' Q0 D
- E' `0 P& \; F( ?; }' i( i6 V
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
/ k3 d' U& U% ` - 6 R- E6 x, n' d
- if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)$ O" u' I7 x: V8 F- d
- 2 Z$ C: m" o: }; r3 K7 T m1 |
- {
& v0 a; G2 n9 H7 `; F0 @$ l h - & Y3 k' T. S* v/ J' B
- /* Initialization Error */# d3 H5 P9 g3 ~1 |
- 2 H1 `; `3 `! S0 R
- Error_Handler(); q4 l% r* I" r! y$ m( J
- & X9 ?* ?. X$ \) R/ X4 z
- }
1 R0 j0 p) K0 r o9 E2 i1 { - - i% x! X) V& G4 g
- }
复制代码 4 F+ G, G+ _6 ~+ V# K
! v$ J0 w5 M- M; E* n5 N" i
4 N# M1 s* Q, r) A- n" D z7 V( s这里值得注意的是:进入2MHz主频需要选择MSI,原因在后面描述。 使用以上基础功能对低功耗进行测量后的结果如下 RUN: 15mA;(外设功能活动) SHUTDOWN:0.08uA;(外设功能停止) STANDBY: 0.18uA;(外设功能停止) STOP2: 2.6mA;(外设功能停止) LPSLEEP2MHz: 1.0~3.6mA(外设功能活动);
& j9 R5 e7 M6 i+ d& q; Q' A在进入低功耗功能时还在串口还在发送数据“\0”(波特率不匹配的乱码),截图如下: " A, _8 k$ @. U$ Q8 s, P& o
2.3试验改进与数据测量 2.3.1关闭必要调度器(FLASH 进入休眠模式) + I$ S, r# k- a4 v
- /* Enable Flash power down mode during Sleep mode */: z+ p/ I8 P6 Q$ z, k2 O
- / [1 ^3 e3 ^9 {9 P3 s3 D
- /* (uncomment this line if power consumption figures */
# U8 W6 S0 M1 a4 p5 t; } - L9 E% u; Y3 G/ [
- /* must be measured with Flash still on in Low Power */
$ \, @# L) i; X* G5 H0 j7 a -
# G/ t: }: C, E* s - /* Sleep mode) */
r R- ?# ?: u; c& h+ O4 ^ - 7 n& L0 W0 g2 h; M6 G' H
- __HAL_FLASH_SLEEP_POWERDOWN_ENABLE();
复制代码 7 \6 b# P& r* q4 |5 {1 u1 z
5 i+ y/ v! }; x/ b* {0 N* f7 J在进入Low Power Sleep 2MHz模式前关闭调度器 测的各种模式下的功耗值: RUN: 15mA;(外设功能活动) SHUTDOWN: 0.08uA;(外设功能停止) STANDBY: 0.18uA;(外设功能停止) STOP2: 2.6mA;(外设功能停止) LPSLEEP2MHz: 1.0~3.6mA(外设功能活动); 主要针对LPSLEEP的功能改进,应本应用未涉及FLASH的调用,所以对测量结果影响不大,待使用了FSMC接口或IAP相关功能代码后进一步测量。 2.3.2改进引脚功能设置 在进入低功耗之前将无关的引脚功能关闭,或者设置称为逻辑电路的功能。是否能有效降低各种模式下的能耗水平 ( ?/ S1 z, l& @; d- s
- void GPIO_AnalogState_Config(void)3 ]! j( }2 P* T' \! v) `
- 6 h( q1 p* L" K8 K
- {
: e* ~, b& s7 h& M: f) i& ~5 _ - % Y/ Q( e6 n5 n3 v6 v9 g
- GPIO_InitTypeDef GPIO_InitStruct1;
; v+ L8 g. t' L Z |; Q4 H4 ^% |# k+ W - 8 j$ }$ h4 @: }9 r! t2 k4 k
- /* Set all GPIO in analog state to reduce power consumption, */2 H6 [9 z$ I' m# Z: z) J
-
e# W, |& P0 R* K+ w# K - __HAL_RCC_GPIOA_CLK_ENABLE();6 U, X+ l( _8 l F( ]- q8 T# [
- __HAL_RCC_GPIOB_CLK_ENABLE();7 A) X0 \" l, }0 M
- __HAL_RCC_GPIOC_CLK_ENABLE();5 n5 U9 k! d+ o" P
- __HAL_RCC_GPIOD_CLK_ENABLE();1 G8 L$ A: w; w# _) ]4 j
- __HAL_RCC_GPIOE_CLK_ENABLE();
" p. V/ J+ h* q( v5 l - __HAL_RCC_GPIOF_CLK_ENABLE();
/ g& U- l# I- \8 @- ~: o, S - __HAL_RCC_GPIOG_CLK_ENABLE();
! D' M( T6 @0 k8 a: d) [7 N+ Y- V - __HAL_RCC_GPIOH_CLK_ENABLE();
4 Z3 f' z3 b3 g& P -
q4 A% I& {; S1 D8 n4 V - GPIO_InitStruct1.Pin = GPIO_PIN_All;
. F, C# k. \2 M8 y# x1 D% f - GPIO_InitStruct1.Mode = GPIO_MODE_ANALOG;
. k3 G5 t* o: F, D; }$ d( V - GPIO_InitStruct1.Speed = GPIO_SPEED_FREQ_LOW;
! S6 y2 G" b7 u) I, T- T7 D: y - GPIO_InitStruct1.Pull = GPIO_NOPULL;
+ @; ], Z. j }7 e
' c- J- O9 V; U! |7 d9 R- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct1);$ W* `8 k8 D/ h1 a& D( Z
- HAL_GPIO_Init(GPIOB, &GPIO_InitStruct1);
9 H) q% Z# ], ? U6 \ - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct1);
& o7 ~& v2 P' Q - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct1);
- R. ]# l/ a! P f3 [6 d% j - HAL_GPIO_Init(GPIOE, &GPIO_InitStruct1);
) b) U( V6 n6 _! x$ O) m7 J - HAL_GPIO_Init(GPIOF, &GPIO_InitStruct1);( U* {- F3 H) ]/ ]& D+ s
- HAL_GPIO_Init(GPIOG, &GPIO_InitStruct1);
+ @0 m! h F o ^ - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct1); % h8 ^4 Z) W1 u4 h: w8 I
- - X$ l7 f+ b8 i3 D% G& @5 o
- __HAL_RCC_GPIOA_CLK_DISABLE();
6 `" _0 o5 ^2 k5 K# W- l2 F4 ~ - __HAL_RCC_GPIOB_CLK_DISABLE();
x3 a/ J8 m x# H" l7 Y - __HAL_RCC_GPIOC_CLK_DISABLE();
0 m0 ^' }9 N8 \# @: l0 m - __HAL_RCC_GPIOD_CLK_DISABLE();
4 e9 G/ Z: x: T9 W, J. E, @ - __HAL_RCC_GPIOE_CLK_DISABLE();) {+ Y6 k' I% s* q% j4 v
- __HAL_RCC_GPIOF_CLK_DISABLE();: V8 ?! M2 g# Z( M5 y% v& r" d
- __HAL_RCC_GPIOG_CLK_DISABLE();/ b) W$ B& `) R- n! [
- __HAL_RCC_GPIOH_CLK_DISABLE();5 o3 ]# u5 S* [
7 ]3 R- v3 r3 m' T) I" n- }
复制代码
; E* O2 h; J0 n" V( q1 ERUN: 15mA;(外设功能活动) SHUTDOWN: 0.08uA;(外设功能停止) STANDBY: 0.18uA;(外设功能停止) STOP2: 1.55uA;(外设功能停止) LPSLEEP2MHz: 1.0mA(外设功能停止); Stop2 模式 及 LPSLEEP 模式 均出现了功耗下降的情况。但LPSLEEP 2MHz模式与官方提供的最低功耗仍然有差距,优化模式还待挖掘。
! W5 G5 w) c9 F3 U' l U+ D" u9 k2.3.3改进时钟及主频 0 E4 L8 l4 g- G7 q
- void SystemClock_Config(void){
2 C5 {% _1 P5 b/ N# [3 C2 U -
7 X) p5 u( t9 N, ` - ......... U+ k( v- f2 ?
-
. T. Q0 @ D$ L5 v+ W% I - //2M时钟配置好后,关闭HSI时钟及相关的PLL时钟。最佳到函数内最后
; e, u; \' t: r/ K - : W+ W9 N8 B* W8 ?- V7 T. e
- #ifdef CORRECT_STEP3; w0 R. U1 G7 U! i2 ]
- 4 I% |! `0 Y8 M$ ?/ L% E: B1 S$ R# i
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
$ j8 h/ u% r4 b- Y. S -
) \, P l3 h3 h3 V/ e0 c* @9 P - RCC_OscInitStruct.HSIState = RCC_HSI_OFF;9 h' S) W# Q1 N+ p
- 2 a0 a3 D# _& i5 H
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_OFF;
/ x9 `& R1 f) a& I& @ -
; L( k: w4 c$ `# O - if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
$ [4 E. m4 S# m1 r" ^ - 6 l! \; m4 N2 f+ J7 ` f' c8 o
- {2 V1 N7 y. J5 I( T o) v" F
- , z1 r) y- S _" S2 d. Q, F2 G
- /* Initialization Error */
5 i& O% h0 P5 m0 B -
" m' v2 U' O$ @+ m: x" ~ - Error_Handler();
. d6 X2 y& S4 t# D) _. K - ; m8 @9 R; Z4 N5 J7 O0 X
- }
" h2 q Q8 Y( H' M2 a+ v- a -
5 J& z% x6 `- L0 t - #endif
# M {: E) t- m! S. ` -
% N1 ^/ w ]( B+ Y9 H - }
复制代码+ _5 I) ?3 r7 {& J: B
在CubeMX生成的时钟配置函数中SystemClock_Config(),使用的是HSI,按80MHz额定最大频率跑应用,为规避相关时钟未关闭造成的空转能耗,这里需要将HSI及相关PLL配置关闭停用。 RUN: 15mA;(外设功能活动) SHUTDOWN: 0.08uA;(外设功能停止) STANDBY: 0.18uA;(外设功能停止) STOP2: 1.51uA;(外设功能停止) LPSLEEP2MHz: 0.351mA(外设功能停止); LPSLEEP 模式功耗下降特别大,但仍旧还在百uA级别与官方提供的几十uA还差一个数量级。还需要进一步优化处理。
% {0 H: J0 O; O# A% {0 M 2.3.4关闭SystemTick及AHB、APB外设时钟进入休眠模式 - void SystemClock_2MHz(void){
2 ^% \7 D U9 [. |& X7 l -
; u6 F+ n; F- l5 d* x- w& f - ......... [5 p! d: v- S. w) K; X
-
- j8 J' z1 w+ v& t - /* Suspend Tick increment to prevent wakeup by Systick interrupt. */9 s& k. Z h: I4 A7 e$ }/ h3 y
- - i5 G: }, D9 _4 ?4 S" D
- /* Otherwise the Systick interrupt will wake up the device within 1ms */
; h. v/ `" i7 W - ! v" D4 u9 o4 `. u2 N' y
- /* (HAL time base). */
* z( E) B6 _$ h' _4 p& d( y - ( g, l; g* [% m( d# X
- HAL_SuspendTick();
. O+ e+ P N/ U3 B1 L9 u+ h' }5 { - 2 L- |- r1 f C3 ]/ \2 f$ J0 F
- /* Switch off all clock enable ... */
. N5 S$ s8 Z, d -
! O0 _" ^7 o/ e$ ` - RCC->AHB1SMENR = 0x0;
3 I% B- M2 Z7 Z$ q8 \ - RCC->AHB2SMENR = 0x0;. p2 \5 D4 k" g* `/ ~" ?
- RCC->AHB3SMENR = 0x0;
3 K5 ]# Z: {) s" ^ P - RCC->APB1SMENR1 = 0x0;; c: J: a, r. k3 w8 \; \$ T
- RCC->APB1SMENR2 = 0x0;
9 E6 Q& b$ J5 a7 o% o - RCC->APB2SMENR = 0x0;
! |% V1 T0 P3 A2 C - ......9 g2 e% Q4 y" X: y+ q
- }
复制代码RUN: 15mA;(外设功能活动) SHUTDOWN: 0.08uA;(外设功能停止) STANDBY: 0.18uA;(外设功能停止) STOP2: 1.51uA;(外设功能停止) LPSLEEP2MHz: 86uA(外设功能停止); LPSLEEP 模式功耗下降几十uA数量级了,界此针对80MHz主频下LED、按键、串口基础功能应用上低功耗优化可以告一段落。已经满足和接近官方提供的参考数据。 0 z# K$ ~& B8 m1 \4 Y) \
5 P. u5 E! m0 S+ O: P
2.4试验结果数据汇总一览 : M) f* c: q0 S! q* L2 B! w5 i
|
感谢分享!!