
STM32L0低功耗应用$ o+ p4 A9 R/ b0 A* N+ O L0 H c STM32L0支持7种低功耗模式,本文重点讨论停止(STOP)模式。% R+ ?- I3 p h& P: M 首先介绍几点影响功耗的因素。 1.IO口的状态,不用的IO口设置成模拟输入。0 E4 G+ y+ A/ V0 M9 u 2.时钟,时钟越低功耗越低。 3.外设,禁用不使用的外设。& c, \0 h9 e$ B 4.PLL是一个耗电大户,如果做低功耗还是把PLL禁用,直接HSE/HSI/MSI到SYSCLK。; K% \" k8 W q% r" A 5.内核电压,根据不同的运行速度和VDD电压调节动态调压器,达到速度与功耗的平衡。 官方描述如下:! Q. S; K5 j5 e5 i; J7 D ![]() * L) U, @) S/ z1 i9 G ![]() 使用下面这个函数调节内核电压 8 l3 N# l( f0 v/ _9 m
1.睡眠模式, p5 [, ~2 @# Z$ @" R- ? 睡眠模式下只有CPU停止工作,所有外设继续工作,任何中断或者事件都能唤醒CPU,此时约16MHz/1mA。- K( a R; E- f; Q1 _7 g1 r) v& Q d1 q5 Y% b l 2.低功耗运行模式- h$ b9 a$ G8 y8 F; [8 Y. _ 低功耗运行模式使用 内部MSI RC振荡器为低速模式(最大工作频率131kHz),内部调压器在低功率模式下,时钟频率和可用外设都有限制。仅当 电压调节器 处于范围 2 时,才能进入低功耗运行模式。 3.低功耗睡眠模式 进入睡眠模式时,调整内部调压器为低功率模式,时钟频率和可用外设都有限制;一个典型的例子是计时器以32kHz的速度运行。当事件或中断触发唤醒时,系统将恢复到运行模式,并打开调节器& e3 a t, U+ r9 E% q$ T/ y/ F 4.带RTC的停止模式 o& t) A- ] U5 a6 |& ]% G- x 停止模式在保持RAM和寄存器内容以及实时时钟的同时,实现了最低的功耗。Vcore域中的所有时钟都被停止禁用PLL、MSI RC、HSE和HSI。LSE或LSI仍在运行。调压器处于低功率模式。一些具有唤醒功能的外围设备可以使HSI在停止模式下检测它们的 触发唤醒的动作。( E2 k, e$ f! |1 r4 I 设备可以被外部中断在3.5us内唤醒,处理器会进入唤醒中断后恢复现场。也可以被PVD中断,比较事件(如果此外设使能),RTC alarm/tamper/timestamp/wakeupevents, USB/USART/I2C/LPUART/LPTIMER 唤醒事件唤醒。 唤醒后需要重新配置时钟。, P+ V9 ?0 t$ l5 m 5.不带RTC的停止模式5 c7 Q" ~* W! r) H- h- E 停止模式在保持RAM和寄存器内容以及实时时钟的同时,实现了最低的功耗。Vcore域中的所有时钟都被停止禁用PLL、MSI RC、HSE和HSI。LSE或LSI仍在运行。调压器处于低功率模式。一些具有唤醒功能的外围设备可以使HSI在停止模式下检测它们的 触发唤醒的动作。 设备可以被外部中断在3.5us内唤醒,处理器会进入唤醒中断后恢复现场。也可以被PVD中断,比较事件(如果此外设使能),RTC alarm/tamper/timestamp/wakeupevents, USB/USART/I2C/LPUART/LPTIMER 唤醒事件唤醒。 唤醒后需要重新配置时钟。4 A- d7 v4 Y% F3 K$ |& v 6.带RTC待机模式 关闭内部电压调节器,从而关闭整个Vcore。PLL MSI HIS HSE 都被关闭,LSE/LSI在运行。1 P9 _# |* O- S& e3 n- B 除了备用电路中的寄存器外(wakeup logic, IWDG,RTC, LSI, LSE Crystal 32 KHz oscillator, RCC_CSR register),RAM和寄存器内容都丢失了。 设备会在以下情况在60us内被唤醒& l4 b. O8 Q6 o% z 1.外部引脚复位& R1 h U- l# S) ]) p. a1 ? 2.IWDG复位- Q6 a% `9 U# L6 K/ T; i/ N- X3 o' g 3.唤醒引脚上升沿 4.RTC Alarm tamper timestamp Wakeup 事件) q4 [; l' g) `. f5 v8 u) V# t L - d' y6 v1 {6 L1 x, [ 7.不带RTC待机模式: b ^0 I+ Z" A1 j 关闭内部电压调节器,从而关闭整个Vcore。PLL MSI HIS HSE LSE LSI都被关闭。' I7 Q; D& H2 b8 ~ 除了备用电路中的寄存器外(wakeup logic, IWDG,RTC, LSI, LSE Crystal 32 KHz oscillator, RCC_CSR register),RAM和寄存器内容都丢失了。. X7 i. ] _+ r; O# ?3 m 设备会在以下情况在60us内被唤醒2 l4 J8 `- \) B: Z8 D 1.外部引脚复位 2.唤醒引脚上升沿 RTC 和IWDG 的时钟源进入停止或者待机模式不会自动停止。3 c8 U. B r R8 t" @$ A1 R. ~2 N/ o ( i2 y; z9 J! Z6 F- P. I 进入STOP模式: v& q N5 t& e 停止模式基于 Cortex®-M0+ 深度睡眠模式与外设时钟门控。调压器既可以配置为正常模式,也可以配置为低功耗模式。在停止模式下,VCORE 域中的所有时钟都会停止,PLL、MSI、HSI16 和 HSE RC 振荡器也被禁止。内部 SRAM 和寄存器内容将保留。 要使停止模式下的功耗最低,内部 Flash 也进入低功耗模式。Flash 处于掉电模式时,将器件从停止模式唤醒将需要额外的启动延时。 要使停止模式下的功耗最低,可在进入停止模式前关闭 VREFINT、BOR、PVD 和温度传感器。退出停止模式后,可以使用 PWR_CR 寄存器中的 ULP 位通过软件重新打开它们。 5 L) I) O9 o6 |7 b# m3 h0 I- j# t 在停止模式下,所有 I/O 引脚的状态与运行模式下相同。 + N. v' P; d5 J4 x3 P1 k$ k 要求 ' t- k0 G, ?* ^5 O- D – 没有中断(对于 WFI)或事件(对于 WFE)挂起。' Y% \5 D; \ E* o2 \! q% i – 将 Cortex®-M0+ 系统控制寄存器中的 SLEEPDEEP 位置 1% s0 ?) X) B; w0 z: J0 x – 电源控制寄存器 (PWR_CR) 中的 PDDS 位 = 0 – 电源控制/状态寄存器 (PWR_CSR) 中的 WUF 位 = 0$ g2 M1 ]+ y% S Z4 E0 ? – 通过配置 RCC_CFGR 寄存器中的 STOPWUCK 位退出停止模式时,选. W# L! y. d: P7 C: ? 择 MSI 或 HSI16 RC 振荡器作为系统时钟。4 J6 C @/ j! i9 d$ U) w 注: 要进入停止模式,所有 EXTI 线挂起位(在第 13.5.6 节:EXTI 挂起 寄存器 (EXTI_PR) 中)、所有外设中断挂起位、RTC 闹钟(闹钟 A8 m/ m9 R6 X [+ B% O3 S/ G( i 和闹钟 B)、RTC 唤醒、RTC 入侵和 RTC 时间戳标志位必须复3 ]$ W2 w# Y3 a0 Q( ]0 X; d 位。否则将忽略进入停止模式这一过程,继续执行程序。- O( C f6 j' A7 q( C3 V/ X ( K( G; Q& d" P, I" f8 Q1 { 下面咱们来看下寄存器描述 系统控制寄存器中的 SLEEPDEEP 位 我在ARM-CortexM0 权威指南上找到的 I V% l f4 Y3 s4 C4 [9 t' r; ~ ![]() ) d& U% U) J! k2 D+ g8 l (PWR_CR) PDDS位:掉电深度睡眠 (Power-down deepsleep) 此位由软件置 1 和清零。 0:器件在 CPU 进入深度睡眠时进入停止模式。调压器处于低功耗模式。" b; f$ w; @; H 1:器件在 CPU 进入深度睡眠时进入待机模式。8 Q' y8 ]; a4 ]) A' l (PWR_CSR) WUF 位: u# N1 @# o0 D+ p6 }# p: u 该位通过硬件置 1,并且只能通过系统复位或通过将 PWR 电源控制寄存器 (PWR_CR) 中的% G+ D0 o, Z& s$ c4 B0 N CWUF 位置 1 清零+ k2 u# P/ k* {% p: R 0:未发生唤醒事件 1:收到唤醒事件,可能来自 WKUP 引脚、RTC 闹钟(闹钟 A 和闹钟 B)、RTC 入侵事9 ^; a5 [6 i% _; y& | c3 W% x- Z% d 件、RTC 时间戳事件或 RTC 唤醒事件。9 X( _* n7 i5 e+ i5 \: u O 注: 如果使能 WKUP 引脚(将 EWUPx (x=1, 2, 3) 位置 1)时 WKUP 引脚已为高电平,系 统将检测到另一唤醒事件。! H z9 H* k" ~+ _: O 然后还要配置选择唤醒后的时钟源 通过此函数
唤醒后如果需要,记得重新配置时钟。 5 d2 {6 ~ m" _( n, Y LPUART在DMA模式下唤醒STOP2 I8 e: `# u! @" b. L 不讨论怎么实现DMA,只讨论唤醒SOTP模式。; y. S+ ~* c1 p3 z2 P. q* ? 首先咱们来看官方描述9 s! @* V7 j" _ : T- n6 c% E. G7 @4 S ![]() 我使用的是LSE时钟 其实官方手册有这样一段描述$ K" _6 E; o3 R# A8 m3 [2 g 当 DMA 用于接收时,它必须在进入停止模式前禁止,并在退出停止模式后重新使能。 从停止模式唤醒功能并非在所有模式下均可用。例如,该功能在 SPI 模式下不起作用,因为 SPI 仅在主模式下工作。8 E) X6 ]* n5 v& f8 V4 ^ 也就是说要在进入STOP模式前禁止DMA。这里不是去操作DMA的寄存器去禁止DMA,而是在LPUART里面的寄存器DMAR位禁止即可。 LPUART_CR3(DMAR位) 位 6 DMAR:DMA 使能接收器 (DMA enable receiver) 此位由软件置 1/复位。 1:针对接收使能 DMA 模式 0:针对接收禁止 DMA 模式4 ^( m+ L4 R4 v1 E7 O: i 进入停止模式的步骤 1.禁止DMA,记得在唤醒后在串口唤醒中断里面重新使能DMA即可(其实使用HAL库是有点小BUG,会导致无法重新使能,后面会说(看串口中断回调函数)) 2.确认串口忙标志为0- p B) l% g+ ]5 |' v 3.确认串口做好接受数据准备% b) B0 e6 Q5 I/ a/ I 4.选择唤醒模式(接受完成唤醒,起始位唤醒,地址匹配唤醒), s. d2 v5 w3 M0 V' x. w" l* d( Y8 C 5.配置串口使能唤醒中断,使能停止模式唤醒 下面介绍要使用的函数 1 W: h" L4 X7 t: i- V( Y3 @# C
**然后在串口唤醒中断里面使能DMA即可 串口唤醒中断回调函数% x1 D% z6 w7 @
记得唤醒之后稍微延时一下,让串口数据接受完成在进入停止模式,不然数据会乱。, L! \- H! f' T" W4 {/ V) I **下面重点来了**5 {8 z; m6 S* ]9 f% n2 @$ e: b; h 这里稍微不注意就会发现 我唤醒之后接受到的数据怎么老是少第一个字节1 T! U- @$ z" H" E8 U1 s6 g1 I 经过我测试发现1 j" j/ t+ r# O 是有一个设置的问题 下面看函数和寄存器描述
置 1 时,VREFINT 在低功耗模式下关闭。通过复位 RCC_APB1RSTR 寄存器中的 PWRRST6 I2 E5 b+ _( U+ q/ k. _, ] 位不会复位该位。当该位置 1 时,寄存器 LCD_CR 的 LCDEN 位不能置 1。 0:VREFINT 在低功耗模式下打开. E$ G/ g# N7 J1 l3 d& Y& y 1:VREFINT 在低功耗模式下关闭) f1 s+ l5 m! }; | 当我们调用HAL_PWREx_EnableUltraLowPower();使能超低低功耗模式 此时你使用9600(不包括9600)以下的波特率就不会少第一个字节 但是你的波特率在9600及以上,收到的数就会少第一个字节 但是我们能不能在超低功耗模式下唤醒,波特率超过9600情况下怎么办呢?5 Q u* _6 Z+ d 还有一个函数和寄存器描述" r: @4 \8 t- `0 ]/ l; W9 D( {$ Z3 h
PWR_CR 位 10 FWU:快速唤醒 (Fast wakeup)3 W* |- d9 G. B1 G2 c3 p) X 此位与 ULP 位结合使用。4 w1 d" A) s" l- r% R8 w 如果 ULP = 0,则忽略 FWU 如果 ULP = 1 且 FWU = 1:从低功耗模式退出时忽略 VREFINT 启动时间。当 VREFINT 重新就 绪时,通过 PWR_CSR 寄存器中的 VREFINTRDYF 标志加以指示。# `) `. Z8 C# I) [+ P 如果 ULP = 1 且 FWU = 0:仅当 VREFINT 就绪(其启动时间后)时,才会从低功耗模式退 出。通过复位 RCC_APB1RSTR 寄存器中的 PWRRST 位不会复位该位。 0:仅当 VREFINT 就绪时,才会退出低功耗模式' j% } d0 `7 [; ?* }- P- l6 I1 Y, X 1:退出低功耗模式时忽略 VREFINT 启动时间 就是醒的时候不等待 VREFINT稳定,但是可能会影响ADC,这样在超低功耗模式下就能快速唤醒不丢第一个字节了 仅在9600下测试不会丢,其他未测$ U* G# R7 p$ z5 A1 V8 J0 e7 K 5 U# T6 a5 R: ?8 @6 W 当然如果你不使能超低功耗模式,那就造吧。: H: W6 `; p2 }0 I 最近一直在搞Linux,这个博客写了快一年了,都忘记了。有时间把RTC和LPTIM也更上。实测功耗在0.8uA左右。# D+ M5 M1 I8 p7 B1 z ) I0 m; l+ F0 w1 K+ E |