
STM32L0低功耗应用+ k$ E2 m+ Z$ a* m STM32L0支持7种低功耗模式,本文重点讨论停止(STOP)模式。 8 h, I; g) `' q k 首先介绍几点影响功耗的因素。 1.IO口的状态,不用的IO口设置成模拟输入。 2.时钟,时钟越低功耗越低。$ ^6 F/ t2 [- @7 R6 i1 \ 3.外设,禁用不使用的外设。; k- s, n5 n# c4 } R/ J5 u/ h! w# z 4.PLL是一个耗电大户,如果做低功耗还是把PLL禁用,直接HSE/HSI/MSI到SYSCLK。* k. P) ?4 m. O" @ 5.内核电压,根据不同的运行速度和VDD电压调节动态调压器,达到速度与功耗的平衡。 " R) E% C) o7 B. Z 官方描述如下: ![]() ![]() ' B, w$ q* r7 i' f 使用下面这个函数调节内核电压 ' w1 m: [+ [# b( @/ J
1.睡眠模式' y7 V! G$ i- ~* y% _! ?8 J" ^( s 睡眠模式下只有CPU停止工作,所有外设继续工作,任何中断或者事件都能唤醒CPU,此时约16MHz/1mA。 2.低功耗运行模式 c# o# I2 f, t& |0 o 低功耗运行模式使用 内部MSI RC振荡器为低速模式(最大工作频率131kHz),内部调压器在低功率模式下,时钟频率和可用外设都有限制。仅当 电压调节器 处于范围 2 时,才能进入低功耗运行模式。 3.低功耗睡眠模式# |0 F% e/ V5 z! r 进入睡眠模式时,调整内部调压器为低功率模式,时钟频率和可用外设都有限制;一个典型的例子是计时器以32kHz的速度运行。当事件或中断触发唤醒时,系统将恢复到运行模式,并打开调节器 5 e9 k1 p: S; m' ? 4.带RTC的停止模式. F9 `7 F9 o* ~* C8 F3 }: v" u 停止模式在保持RAM和寄存器内容以及实时时钟的同时,实现了最低的功耗。Vcore域中的所有时钟都被停止禁用PLL、MSI RC、HSE和HSI。LSE或LSI仍在运行。调压器处于低功率模式。一些具有唤醒功能的外围设备可以使HSI在停止模式下检测它们的 触发唤醒的动作。 设备可以被外部中断在3.5us内唤醒,处理器会进入唤醒中断后恢复现场。也可以被PVD中断,比较事件(如果此外设使能),RTC alarm/tamper/timestamp/wakeupevents, USB/USART/I2C/LPUART/LPTIMER 唤醒事件唤醒。 唤醒后需要重新配置时钟。$ [; z' i- K8 A- H / J$ D1 p: B, A 5.不带RTC的停止模式; z$ B+ _/ `8 F! I9 g! a o 停止模式在保持RAM和寄存器内容以及实时时钟的同时,实现了最低的功耗。Vcore域中的所有时钟都被停止禁用PLL、MSI RC、HSE和HSI。LSE或LSI仍在运行。调压器处于低功率模式。一些具有唤醒功能的外围设备可以使HSI在停止模式下检测它们的 触发唤醒的动作。# U6 y+ d5 X5 ]7 L7 |8 u2 \ 设备可以被外部中断在3.5us内唤醒,处理器会进入唤醒中断后恢复现场。也可以被PVD中断,比较事件(如果此外设使能),RTC alarm/tamper/timestamp/wakeupevents, USB/USART/I2C/LPUART/LPTIMER 唤醒事件唤醒。 唤醒后需要重新配置时钟。& f3 Q) O P% ^2 P1 f5 Q 4 }4 k) t* q X/ Z. |' V% v 6.带RTC待机模式& v2 w% w& V- q9 a8 W Z6 G 关闭内部电压调节器,从而关闭整个Vcore。PLL MSI HIS HSE 都被关闭,LSE/LSI在运行。 除了备用电路中的寄存器外(wakeup logic, IWDG,RTC, LSI, LSE Crystal 32 KHz oscillator, RCC_CSR register),RAM和寄存器内容都丢失了。0 K' D) E$ ^0 q; [ 设备会在以下情况在60us内被唤醒0 Y- b. ^$ q$ o2 h0 L& \" Z 1.外部引脚复位& h; b6 K& ~ n( F8 a6 w 2.IWDG复位 \7 v2 B' W& `/ q! R& _/ | 3.唤醒引脚上升沿 4.RTC Alarm tamper timestamp Wakeup 事件' J3 T) p/ B: O9 [! ` 7.不带RTC待机模式 关闭内部电压调节器,从而关闭整个Vcore。PLL MSI HIS HSE LSE LSI都被关闭。! W2 B( x2 q2 t |8 c! W% R: S2 l 除了备用电路中的寄存器外(wakeup logic, IWDG,RTC, LSI, LSE Crystal 32 KHz oscillator, RCC_CSR register),RAM和寄存器内容都丢失了。 设备会在以下情况在60us内被唤醒3 R. `7 w8 }6 ?. b5 ?1 K 1.外部引脚复位) H# ?3 E* l% E! a" A1 P* l; Q( I" G 2.唤醒引脚上升沿3 U3 I2 [7 [* E, F; _, y RTC 和IWDG 的时钟源进入停止或者待机模式不会自动停止。, N! z& Z) c: A9 T 进入STOP模式 停止模式基于 Cortex®-M0+ 深度睡眠模式与外设时钟门控。调压器既可以配置为正常模式,也可以配置为低功耗模式。在停止模式下,VCORE 域中的所有时钟都会停止,PLL、MSI、HSI16 和 HSE RC 振荡器也被禁止。内部 SRAM 和寄存器内容将保留。' [6 D/ O& C* C! H9 }/ Z) Y5 t2 A 要使停止模式下的功耗最低,内部 Flash 也进入低功耗模式。Flash 处于掉电模式时,将器件从停止模式唤醒将需要额外的启动延时。7 R5 i" g0 O6 v* _! g 要使停止模式下的功耗最低,可在进入停止模式前关闭 VREFINT、BOR、PVD 和温度传感器。退出停止模式后,可以使用 PWR_CR 寄存器中的 ULP 位通过软件重新打开它们。 # `( ]. `3 T3 e7 V5 T, y 在停止模式下,所有 I/O 引脚的状态与运行模式下相同。% ? q" B0 E8 B; y4 \ 1 }0 k/ c* W3 c" ]6 C. ~ 要求( I/ o* X2 a9 a. y4 @' ]5 H/ \ + ^% ~7 z9 p' c& S: h- L; B2 `5 r – 没有中断(对于 WFI)或事件(对于 WFE)挂起。 – 将 Cortex®-M0+ 系统控制寄存器中的 SLEEPDEEP 位置 1 – 电源控制寄存器 (PWR_CR) 中的 PDDS 位 = 0 – 电源控制/状态寄存器 (PWR_CSR) 中的 WUF 位 = 0 – 通过配置 RCC_CFGR 寄存器中的 STOPWUCK 位退出停止模式时,选# p- O: ^. H" c& C" P 择 MSI 或 HSI16 RC 振荡器作为系统时钟。" f* I5 L8 o( ~( n 注: 要进入停止模式,所有 EXTI 线挂起位(在第 13.5.6 节:EXTI 挂起, M" S5 Z& V% y9 U1 w: W. r 寄存器 (EXTI_PR) 中)、所有外设中断挂起位、RTC 闹钟(闹钟 A7 s/ X M7 c2 i+ g5 I 和闹钟 B)、RTC 唤醒、RTC 入侵和 RTC 时间戳标志位必须复) X* ]; F2 i q9 Z0 | 位。否则将忽略进入停止模式这一过程,继续执行程序。7 p( I# [8 O' p; H: C / h$ y6 C- o, {2 i0 w' \. B) S2 h2 s 下面咱们来看下寄存器描述4 Q6 b7 ^! H" ] + o% t6 D9 w- b# c# j7 c- a 系统控制寄存器中的 SLEEPDEEP 位 我在ARM-CortexM0 权威指南上找到的0 Z4 A( N$ m: M$ L ![]() 5 N I [2 [/ Z# i; i (PWR_CR) PDDS位:掉电深度睡眠 (Power-down deepsleep) 此位由软件置 1 和清零。9 C) C2 @8 N6 _4 b. s$ ]- e 0:器件在 CPU 进入深度睡眠时进入停止模式。调压器处于低功耗模式。 1:器件在 CPU 进入深度睡眠时进入待机模式。 # f4 s' o- s( o5 j) Q (PWR_CSR) WUF 位* b! [% P' k# e2 k- f) b 该位通过硬件置 1,并且只能通过系统复位或通过将 PWR 电源控制寄存器 (PWR_CR) 中的 CWUF 位置 1 清零1 T5 W+ O* E4 X P 0:未发生唤醒事件 1:收到唤醒事件,可能来自 WKUP 引脚、RTC 闹钟(闹钟 A 和闹钟 B)、RTC 入侵事+ b c+ z( k% ]4 | S 件、RTC 时间戳事件或 RTC 唤醒事件。" G' e* {5 H, |( T% O 注: 如果使能 WKUP 引脚(将 EWUPx (x=1, 2, 3) 位置 1)时 WKUP 引脚已为高电平,系 统将检测到另一唤醒事件。 * B2 j+ t& Z+ w" { 然后还要配置选择唤醒后的时钟源 通过此函数
唤醒后如果需要,记得重新配置时钟。 LPUART在DMA模式下唤醒STOP 不讨论怎么实现DMA,只讨论唤醒SOTP模式。* R% `' m8 X! f- G% ?$ u 首先咱们来看官方描述: y& S# m% p+ B, p # t P- v; R' L- [4 i3 \; m ![]() ; a0 _9 Q) [$ ]7 |! B% T+ V5 F3 x 我使用的是LSE时钟9 ]% y+ L: ~% l% j' }3 ~* q . d7 Z. b5 r$ D% U- S( a8 H/ _ 其实官方手册有这样一段描述 当 DMA 用于接收时,它必须在进入停止模式前禁止,并在退出停止模式后重新使能。 从停止模式唤醒功能并非在所有模式下均可用。例如,该功能在 SPI 模式下不起作用,因为 SPI 仅在主模式下工作。; \+ |: ]1 H T) g 也就是说要在进入STOP模式前禁止DMA。这里不是去操作DMA的寄存器去禁止DMA,而是在LPUART里面的寄存器DMAR位禁止即可。5 S9 g3 s7 H- W9 r3 D LPUART_CR3(DMAR位)7 ^* \# E9 ?+ F. ^6 u 位 6 DMAR:DMA 使能接收器 (DMA enable receiver). c; A5 I$ X0 t- a/ w& j 此位由软件置 1/复位。* N4 y+ D8 Y# @; _* w4 Q6 V$ Y9 h 1:针对接收使能 DMA 模式 0:针对接收禁止 DMA 模式 1 V$ h+ s7 U, z3 [# q 进入停止模式的步骤 1.禁止DMA,记得在唤醒后在串口唤醒中断里面重新使能DMA即可(其实使用HAL库是有点小BUG,会导致无法重新使能,后面会说(看串口中断回调函数))+ ~& J3 V' W# n* u 2.确认串口忙标志为0) T5 y2 _5 f% }2 v- i 3.确认串口做好接受数据准备+ K( |6 {* o" m( f R" t 4.选择唤醒模式(接受完成唤醒,起始位唤醒,地址匹配唤醒) 5.配置串口使能唤醒中断,使能停止模式唤醒 下面介绍要使用的函数 9 S2 }7 [) t3 ?% r
**然后在串口唤醒中断里面使能DMA即可# D$ D) r% \+ g; E) S5 m* ]/ B 串口唤醒中断回调函数
记得唤醒之后稍微延时一下,让串口数据接受完成在进入停止模式,不然数据会乱。 **下面重点来了**5 q, W% N( [7 P0 G 这里稍微不注意就会发现 我唤醒之后接受到的数据怎么老是少第一个字节1 D6 p6 P. `3 R- r7 g 经过我测试发现 是有一个设置的问题 下面看函数和寄存器描述
置 1 时,VREFINT 在低功耗模式下关闭。通过复位 RCC_APB1RSTR 寄存器中的 PWRRST 位不会复位该位。当该位置 1 时,寄存器 LCD_CR 的 LCDEN 位不能置 1。/ d3 d+ a. C* E% U# o+ P# j 0:VREFINT 在低功耗模式下打开8 a; h1 R/ t: _3 X" m( D 1:VREFINT 在低功耗模式下关闭, E. ]! w4 @& U3 L2 M [ 当我们调用HAL_PWREx_EnableUltraLowPower();使能超低低功耗模式; @1 i6 u I' l5 f 此时你使用9600(不包括9600)以下的波特率就不会少第一个字节 但是你的波特率在9600及以上,收到的数就会少第一个字节 但是我们能不能在超低功耗模式下唤醒,波特率超过9600情况下怎么办呢? 还有一个函数和寄存器描述1 w3 H; c) l5 K. l* x
PWR_CR 位 10 FWU:快速唤醒 (Fast wakeup) 此位与 ULP 位结合使用。6 i1 N1 b1 `5 N6 y! G, r" e 如果 ULP = 0,则忽略 FWU7 b3 O" \8 [: T2 }, A: ^ 如果 ULP = 1 且 FWU = 1:从低功耗模式退出时忽略 VREFINT 启动时间。当 VREFINT 重新就 绪时,通过 PWR_CSR 寄存器中的 VREFINTRDYF 标志加以指示。 如果 ULP = 1 且 FWU = 0:仅当 VREFINT 就绪(其启动时间后)时,才会从低功耗模式退" q7 J. S- q* E3 q 出。通过复位 RCC_APB1RSTR 寄存器中的 PWRRST 位不会复位该位。* y# V8 j5 @2 _" g; H 0:仅当 VREFINT 就绪时,才会退出低功耗模式! c' F$ B4 A4 V, D! `. ^. B* | 1:退出低功耗模式时忽略 VREFINT 启动时间/ z1 B. w1 M+ @2 W$ I: O7 a 就是醒的时候不等待 VREFINT稳定,但是可能会影响ADC,这样在超低功耗模式下就能快速唤醒不丢第一个字节了 仅在9600下测试不会丢,其他未测$ s9 X* S# ?% x) D! x3 n/ L; H# `0 q 当然如果你不使能超低功耗模式,那就造吧。+ | n; j3 u! |2 \# I! W 最近一直在搞Linux,这个博客写了快一年了,都忘记了。有时间把RTC和LPTIM也更上。实测功耗在0.8uA左右。 & ^8 u* u& h9 U& F1 I- ? , J! c1 ~$ U: K8 E) `8 y |