STMCU小助手
发布时间:2021-11-17 22:01
|
STM32L0低功耗应用, [8 H8 n% \, |" o STM32L0支持7种低功耗模式,本文重点讨论停止(STOP)模式。 首先介绍几点影响功耗的因素。# J, c/ v( o. v- I6 O2 \) }! @/ K 1.IO口的状态,不用的IO口设置成模拟输入。% i3 X+ o) B5 n, F/ u9 X: G 2.时钟,时钟越低功耗越低。! N3 G- R0 j3 `9 D2 p9 q) R9 [) T 3.外设,禁用不使用的外设。3 _, D: Y% {3 [4 ~: N 4.PLL是一个耗电大户,如果做低功耗还是把PLL禁用,直接HSE/HSI/MSI到SYSCLK。 5.内核电压,根据不同的运行速度和VDD电压调节动态调压器,达到速度与功耗的平衡。 官方描述如下: O3 z" {1 f, ?' y; w4 z+ E* N
" f2 }6 R: {# ^$ ?& `
- f! X, S9 V- [) W+ U 使用下面这个函数调节内核电压8 i2 \* G0 C, s J/ H( ~
1.睡眠模式5 Y# T2 G5 i3 T2 E 睡眠模式下只有CPU停止工作,所有外设继续工作,任何中断或者事件都能唤醒CPU,此时约16MHz/1mA。9 O9 F m5 v: k# X% I 2.低功耗运行模式* a0 F5 X+ J* O 低功耗运行模式使用 内部MSI RC振荡器为低速模式(最大工作频率131kHz),内部调压器在低功率模式下,时钟频率和可用外设都有限制。仅当 电压调节器 处于范围 2 时,才能进入低功耗运行模式。9 }) C4 }" I; {1 w: t3 f: N 3.低功耗睡眠模式* R/ X( \. z5 {( s% y& l2 I8 n5 P 进入睡眠模式时,调整内部调压器为低功率模式,时钟频率和可用外设都有限制;一个典型的例子是计时器以32kHz的速度运行。当事件或中断触发唤醒时,系统将恢复到运行模式,并打开调节器& ~1 a6 d5 ]: @9 p7 c 7 v% e& b9 i+ x# h: `) ]3 H 4.带RTC的停止模式 ^- F' i6 k6 c; f! X 停止模式在保持RAM和寄存器内容以及实时时钟的同时,实现了最低的功耗。Vcore域中的所有时钟都被停止禁用PLL、MSI RC、HSE和HSI。LSE或LSI仍在运行。调压器处于低功率模式。一些具有唤醒功能的外围设备可以使HSI在停止模式下检测它们的 触发唤醒的动作。 设备可以被外部中断在3.5us内唤醒,处理器会进入唤醒中断后恢复现场。也可以被PVD中断,比较事件(如果此外设使能),RTC alarm/tamper/timestamp/wakeupevents, USB/USART/I2C/LPUART/LPTIMER 唤醒事件唤醒。 唤醒后需要重新配置时钟。 + u: q" n. B' Q' k& F6 c! V 5.不带RTC的停止模式 停止模式在保持RAM和寄存器内容以及实时时钟的同时,实现了最低的功耗。Vcore域中的所有时钟都被停止禁用PLL、MSI RC、HSE和HSI。LSE或LSI仍在运行。调压器处于低功率模式。一些具有唤醒功能的外围设备可以使HSI在停止模式下检测它们的 触发唤醒的动作。 设备可以被外部中断在3.5us内唤醒,处理器会进入唤醒中断后恢复现场。也可以被PVD中断,比较事件(如果此外设使能),RTC alarm/tamper/timestamp/wakeupevents, USB/USART/I2C/LPUART/LPTIMER 唤醒事件唤醒。 唤醒后需要重新配置时钟。 6.带RTC待机模式 关闭内部电压调节器,从而关闭整个Vcore。PLL MSI HIS HSE 都被关闭,LSE/LSI在运行。# `* f/ r g, e& _- s' O4 Q 除了备用电路中的寄存器外(wakeup logic, IWDG,RTC, LSI, LSE Crystal 32 KHz oscillator, RCC_CSR register),RAM和寄存器内容都丢失了。$ v7 i2 f) E) a* z' M( B9 N 设备会在以下情况在60us内被唤醒8 ?2 |& j/ [% G 1.外部引脚复位 2.IWDG复位 3.唤醒引脚上升沿' Y* {& u9 w& |* f* A6 S, H" T 4.RTC Alarm tamper timestamp Wakeup 事件 5 I+ O* H4 d* ~* D( g 7.不带RTC待机模式 关闭内部电压调节器,从而关闭整个Vcore。PLL MSI HIS HSE LSE LSI都被关闭。" H C: I- O& W 除了备用电路中的寄存器外(wakeup logic, IWDG,RTC, LSI, LSE Crystal 32 KHz oscillator, RCC_CSR register),RAM和寄存器内容都丢失了。% ~. W7 ?4 B' a2 v, i3 P! f0 r( { 设备会在以下情况在60us内被唤醒+ b; f% U% B& O/ E 1.外部引脚复位 2.唤醒引脚上升沿2 g1 a/ h1 h4 m5 B6 M" h6 R% S RTC 和IWDG 的时钟源进入停止或者待机模式不会自动停止。 * G {+ T' r; M 进入STOP模式3 p0 j7 h3 ]( K& ~ G 停止模式基于 Cortex®-M0+ 深度睡眠模式与外设时钟门控。调压器既可以配置为正常模式,也可以配置为低功耗模式。在停止模式下,VCORE 域中的所有时钟都会停止,PLL、MSI、HSI16 和 HSE RC 振荡器也被禁止。内部 SRAM 和寄存器内容将保留。% q( c7 l3 ]* _$ T! I 要使停止模式下的功耗最低,内部 Flash 也进入低功耗模式。Flash 处于掉电模式时,将器件从停止模式唤醒将需要额外的启动延时。- z: v+ H+ \- {/ C5 |( U3 \ 要使停止模式下的功耗最低,可在进入停止模式前关闭 VREFINT、BOR、PVD 和温度传感器。退出停止模式后,可以使用 PWR_CR 寄存器中的 ULP 位通过软件重新打开它们。 在停止模式下,所有 I/O 引脚的状态与运行模式下相同。4 s, H( T, J1 h/ @! F2 g 0 Y2 O# w! I Q" t, g9 D 要求 – 没有中断(对于 WFI)或事件(对于 WFE)挂起。8 R$ ]2 @( E+ G- d3 C – 将 Cortex®-M0+ 系统控制寄存器中的 SLEEPDEEP 位置 1: i) G% |' a! a7 k6 p8 w- A – 电源控制寄存器 (PWR_CR) 中的 PDDS 位 = 09 o( ~9 F4 ]( T) c – 电源控制/状态寄存器 (PWR_CSR) 中的 WUF 位 = 0 – 通过配置 RCC_CFGR 寄存器中的 STOPWUCK 位退出停止模式时,选! Q" C, ^" B9 _9 @ 择 MSI 或 HSI16 RC 振荡器作为系统时钟。8 w @ K( l" R8 t0 @3 v/ H8 m F 注: 要进入停止模式,所有 EXTI 线挂起位(在第 13.5.6 节:EXTI 挂起 寄存器 (EXTI_PR) 中)、所有外设中断挂起位、RTC 闹钟(闹钟 A 和闹钟 B)、RTC 唤醒、RTC 入侵和 RTC 时间戳标志位必须复 位。否则将忽略进入停止模式这一过程,继续执行程序。 1 I- n% w! h6 y& |0 B" D- y 下面咱们来看下寄存器描述3 n# g+ k$ L9 L/ L * K4 {$ E* O) \+ G6 p 系统控制寄存器中的 SLEEPDEEP 位3 m. p; O7 q5 u1 }" f& Y. K 我在ARM-CortexM0 权威指南上找到的' R9 C- z3 {4 S. |
(PWR_CR) PDDS位:掉电深度睡眠 (Power-down deepsleep) 此位由软件置 1 和清零。. C% h; n; l# e! P' G z5 d7 X 0:器件在 CPU 进入深度睡眠时进入停止模式。调压器处于低功耗模式。+ L* p$ H- U, o( t; L 1:器件在 CPU 进入深度睡眠时进入待机模式。5 S% O) g, h5 s# s 1 a: Q: d, B8 A- e6 L( X (PWR_CSR) WUF 位 该位通过硬件置 1,并且只能通过系统复位或通过将 PWR 电源控制寄存器 (PWR_CR) 中的6 h2 D% K# L/ l0 {- [7 [ CWUF 位置 1 清零5 A0 r1 I+ r; b* R; v 0:未发生唤醒事件7 K' X& G; q/ l% A' v. w/ A 1:收到唤醒事件,可能来自 WKUP 引脚、RTC 闹钟(闹钟 A 和闹钟 B)、RTC 入侵事 件、RTC 时间戳事件或 RTC 唤醒事件。 注: 如果使能 WKUP 引脚(将 EWUPx (x=1, 2, 3) 位置 1)时 WKUP 引脚已为高电平,系 统将检测到另一唤醒事件。7 R3 F2 M; Z; y2 n% _; I 然后还要配置选择唤醒后的时钟源5 G: x1 `. k3 |" I) ~$ L0 m 通过此函数
唤醒后如果需要,记得重新配置时钟。 LPUART在DMA模式下唤醒STOP( a3 |7 z: k* z8 [. p 不讨论怎么实现DMA,只讨论唤醒SOTP模式。1 e3 T7 L E* z9 p/ u" t 首先咱们来看官方描述! M! ?" @2 _. a$ a8 z& W 7 p6 o- S2 p5 s
2 H( ~$ c: L# G 我使用的是LSE时钟 # o* p U& a/ a- F8 q7 L9 L 其实官方手册有这样一段描述2 b) e- j4 U$ f. p 当 DMA 用于接收时,它必须在进入停止模式前禁止,并在退出停止模式后重新使能。 从停止模式唤醒功能并非在所有模式下均可用。例如,该功能在 SPI 模式下不起作用,因为 SPI 仅在主模式下工作。 也就是说要在进入STOP模式前禁止DMA。这里不是去操作DMA的寄存器去禁止DMA,而是在LPUART里面的寄存器DMAR位禁止即可。5 M( Z* m4 o8 L2 G: B/ ] LPUART_CR3(DMAR位)7 \2 y* i: f- L8 h# y 位 6 DMAR:DMA 使能接收器 (DMA enable receiver) 此位由软件置 1/复位。. @0 x! u# g: h% R4 Q 1:针对接收使能 DMA 模式4 R: |9 i! Q; }: }6 V0 K 0:针对接收禁止 DMA 模式. Y9 K% d! h8 r' U7 |% x$ [ / n3 [1 I$ [" g 进入停止模式的步骤/ P, g( Q i5 k& k 1.禁止DMA,记得在唤醒后在串口唤醒中断里面重新使能DMA即可(其实使用HAL库是有点小BUG,会导致无法重新使能,后面会说(看串口中断回调函数)) 2.确认串口忙标志为0$ b2 e1 T" ^- v% G. M 3.确认串口做好接受数据准备/ E+ W9 e& {8 |$ [ 4.选择唤醒模式(接受完成唤醒,起始位唤醒,地址匹配唤醒)7 t7 S; B5 t) ]" q' X 5.配置串口使能唤醒中断,使能停止模式唤醒 下面介绍要使用的函数 0 ?- ]' P( ?+ A3 L* X0 P/ W
**然后在串口唤醒中断里面使能DMA即可 串口唤醒中断回调函数
记得唤醒之后稍微延时一下,让串口数据接受完成在进入停止模式,不然数据会乱。& F: J2 C1 A2 B& e! P2 P **下面重点来了*** h0 m F9 ]" e2 h/ V5 W 这里稍微不注意就会发现 我唤醒之后接受到的数据怎么老是少第一个字节 经过我测试发现9 K5 I$ c: P3 w2 w0 V7 M3 ^ 是有一个设置的问题5 V* r' N6 b1 x8 M+ ^ 下面看函数和寄存器描述/ x9 K/ S4 _/ N% ?. q- ~5 D/ n1 `, F5 _
置 1 时,VREFINT 在低功耗模式下关闭。通过复位 RCC_APB1RSTR 寄存器中的 PWRRST [6 F; l* |0 _1 e! C, B% t& z; C 位不会复位该位。当该位置 1 时,寄存器 LCD_CR 的 LCDEN 位不能置 1。4 U# C9 h8 |6 o! W- @ 0:VREFINT 在低功耗模式下打开 1:VREFINT 在低功耗模式下关闭' }7 Z" j: u8 J+ ^1 A. M# V & M9 F! s) h; X* y 当我们调用HAL_PWREx_EnableUltraLowPower();使能超低低功耗模式 此时你使用9600(不包括9600)以下的波特率就不会少第一个字节 但是你的波特率在9600及以上,收到的数就会少第一个字节 但是我们能不能在超低功耗模式下唤醒,波特率超过9600情况下怎么办呢? 还有一个函数和寄存器描述
PWR_CR 位 10 FWU:快速唤醒 (Fast wakeup) 此位与 ULP 位结合使用。; N0 `+ A* U" | 如果 ULP = 0,则忽略 FWU 如果 ULP = 1 且 FWU = 1:从低功耗模式退出时忽略 VREFINT 启动时间。当 VREFINT 重新就 绪时,通过 PWR_CSR 寄存器中的 VREFINTRDYF 标志加以指示。2 k/ I- D5 h$ X" _' F* T 如果 ULP = 1 且 FWU = 0:仅当 VREFINT 就绪(其启动时间后)时,才会从低功耗模式退) V1 `. [7 w) S; u& {8 o 出。通过复位 RCC_APB1RSTR 寄存器中的 PWRRST 位不会复位该位。2 y8 [2 _# N4 N4 L6 O, ^) m" p 0:仅当 VREFINT 就绪时,才会退出低功耗模式; g1 m7 O: F0 R$ `$ _( R 1:退出低功耗模式时忽略 VREFINT 启动时间 就是醒的时候不等待 VREFINT稳定,但是可能会影响ADC,这样在超低功耗模式下就能快速唤醒不丢第一个字节了 仅在9600下测试不会丢,其他未测* n4 X! k0 Q5 K$ O- j o 当然如果你不使能超低功耗模式,那就造吧。7 Z% h# C. W+ m- _ 最近一直在搞Linux,这个博客写了快一年了,都忘记了。有时间把RTC和LPTIM也更上。实测功耗在0.8uA左右。; D9 S' m* ]7 K7 K8 y0 F ! w( S0 o0 k+ N7 g) f( ~+ m / w) A/ h4 B: ?0 u' f* u, P |
微信公众号
手机版