STM32L4R5 低功耗模式及唤醒
本帖最后由 cruelfox 于 2018-3-2 01:01 编辑前一个帖子 https://www.stmcu.org.cn/module/forum/thread-614926-1-1.html 我已经列出了 Nucleo-L4R5 在2MHz下的运行和Sleep模式下的电流测量结果。下面测试内容是更低功耗的模式:Stop, Standby 和 Shutdown.
进入 Sleep 模式之外的省电模式,需要设置 Cortex-m4 的 SCB_SCR 寄存器 SLEEPDEEP 位,也就是启用深度睡眠模式。对于 STM32L4R5, 再根据 PWR_CR1 寄存器中 LPMS 位的设置来确定是哪一个低功耗模式。最后再用 WFI/WFE 方法进入休眠模式,代码也不复杂。例如要到 Stop 1模式,可以这么设置:
SCB->SCR|=1<<SCB_SCR_SLEEPDEEP_Pos;
tmp=PWR->CR1;
tmp &= ~ PWR_CR1_LPMS_Msk;
PWR->CR1 = tmp|PWR_CR1_LPMS_STOP1;
然后在想休眠时执行 __WFI(); 或者是 __WFE(); 就可以了。
注意,在 Stop 0/1/2 模式下,所有寄存器都是保持的,SRAM1, SRAM2 内容也是保持的,SRAM3 是否保持是可选的。但是在 Standby 和 Shutdown 模式下,绝大部分寄存器内容都丢失了,SRAM除了可以在Standby模式下选择保持之外也是要掉电的,唤醒之后系统是复位过程。保持现场是要付出功耗的代价的。
我的测试程序中使用了一个局部变量来记录唤醒次数,堆栈在SRAM3中。在 Stop2 模式下,若不启用SRAM3内容保持,堆栈中的数据就丢掉了,于是可以看到程序打印出的数值是随机变化的。当 PWR_CR1 设置 RRSTP=1 后,记录的唤醒次数才正常。
串口收到的字符出现乱码我怀疑是从 stop 模式唤醒后 MSI 振荡器频率还没有稳定,导致串口波特率误差大引起的。
电流测试结果:(都没有开启 LSE, LSI等时钟)
低功耗模式 电流
Stop 0250µA
Stop 194µA
Stop 22.70µA
Stop2 + SRAM3保持4.34µA
Standby0.11µA
Standby + SRAM2保持0.53µA
Shutdown0.02µA
我的万用表分辨率最小只有 0.02µA,所以 Shutdown 模式的电流只能看个大概了。
在 Stop 模式下,可以开启 LSI 或者 LSE 振荡器,给RTC或者LPUART1等设备用,应该会增加一些电流消耗,顺便测一下:
Stop 2Stop 2 + LSE Stop 2 + LSI
2.69µA3.07µA 2.95µA
启用 LSE 增加大约0.3uA的电流消耗,和手册上数据差不多,这是要使用RTC所需要的。LSI能省一点电,但是作为时钟就不精确了。
开启LSE, 并启用RTC之后,电流又增加了一些。对比手册第一页上的"420nA Standby mode with RTC"来说,我的这个测试电流大了不少。
Stop 2 +RTCStandby + RTC Shutdown +RTC
3.28µA 0.75µA0.66µA
奇怪了,我又仔细核对了手册中的表格数据,明白是怎么回事了:420nA那个说明是RTC部分大约带来了0.3µA 的消耗,但是没有算32k晶体振荡器的功耗;P所以带上晶体一起算,按照最低的Shutdown模式看也需要0.66µA 的电流才行。我猜如果是为了定时唤醒的话,用LSI+IWDG功耗更省吧。
测试一下从 Stop 模式唤醒的时间吧。
Nucleo板子有一个现成的用户按钮,在L4R5这个板子上按钮是接在 PC13 脚的。用 EXTI 可以检测这个引脚的上升或下降沿,产生中断或者事件,用来唤醒CPU. 我用的是事件方式,这样少处理ISR函数,简单一点。休眠时用 __WFE(); 等待事件即可。
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
EXTI->EMR1 = 1<<13; // unmask event
EXTI->RTSR1 = 1<<13; // rising edge
SYSCFG->EXTICR = SYSCFG_EXTICR4_EXTI13_PC; // use PC13 EXTI
以上代码是配置了EXTI13这条外部请求线,并选择了PORTC为输入,上升沿触发。
从程序里面串口输出可以看唤醒次数。为了测量唤醒时间。需要请出我的数字示波器了。
示波器一个通道测按钮上的电压,另一个通道测一个随便选的GPIO,在程序中当唤醒之后立即将这个GPIO设成高电平,而在休眠之前设成低电平。
先看下Sleep模式(2MHz)的:5个微秒多,好象有点长了。
可能跟运行频率有关系?那用4MHz试一下,大约是缩短了一半。
这个是Stop 0模式(进入前、唤醒后是2MHz运行)的,比Sleep模式的唤醒时间长了。
奇怪的是 Stop 1模式居然唤醒时间还短一点。
Stop 2模式比Stop 1模式的唤醒时间稍长一点(忘了保存截图了)。其实这个情况 Stop 0/1/2 的差别算小的了。
下面是改变了唤醒之后运行频率的,4MHz时,Stop 2模式的唤醒时间缩短,但是没缩到2MHz的一半。
选择唤醒后使用HSI16作为时钟,比MSI 4MHz短了一些。看来系统的准备时间限制住了。
但是从standby和Shutdown模式不能用EXTI来唤醒了,因为中断系统已经不能用。PC13这个引叫还有 WKUP2 功能,应该还有办法来唤醒的。
我发现在 PWR 里面把 WKUP2 唤醒功能打开就可以从 standby 唤醒了:
PWR->CR3 |= PWR_CR3_EWUP2;
不过,不过,和从 Sleep/Stop 模式唤醒不一样,MCU并不执行 WFE 指令之后的程序,而是——复位了,从ResetHandler开始运行的。:lol
这个情况在我的意料之中。现在暂且想办法测一下唤醒时间吧,那就在初始化过后就把 GPIO 设一下,让示波器抓。
这个唤醒时间就比Stop模式长了很多了,而且运行频率2MHz/4MHz的差别也不大。Shutdown模式也是同理的,都是上电重启动了。
如果要在 Standby/Shutdown 模式唤醒后接着 WFI/WFE 指令后面开始运行,需要软件上做技术处理。也没必要一定跳转到上次的位置执行,只要程序初始化时识别出是唤醒过程而非其它原因的复位,并且能恢复之前保存的软件状态,接着做唤醒之后该做的任务就好了。用Standby模式的话,可以把SRAM2的数据保留。如果还嫌功耗大,就只能用 32 个backup register来保存最重要的变量了。
总结,STM32L4R5 (以及以前的一些STM32L4型号,我没这么测过)的低功耗模式是挺省电的,几个到几十个微秒的唤醒时间,可以应付很多情况了。
厉害{:3_41:} 不错的文章,谢谢分享!已汇总到
https://www.stmcu.org.cn/module/forum/thread-614299-1-1.html
并且也会汇总到3月技术原创中~~ 感谢分享
页:
[1]