【STM32+cubemx】0014 HAL库开发:电源控制(三种低功耗模式:sleep、stop、standby)

本节我们来讲一讲stm32的电源控制,也就是低功耗模式。

1)stm32的低功耗模式简介

stm32有三种低功耗模式,功耗依次降低:

睡眠模式(sleep mode),停止模式(stop mode),待机模式(standby mode)。

睡眠模式:只有内核时钟关闭,外设仍在运行;可以通过任意一个中断或唤醒事件唤醒;唤醒后回到睡眠的位置向后执行。

停止模式:关闭内核时钟、外设时钟,保留内核1.8V供电,寄存器和RAM中的数据可以保持,IO口状态也可保持;可以通过任意一个外部中断唤醒;唤醒后可回到停止的代码处向后执行,但要重新初始化时钟和外设。

待机模式:关闭所有时钟,关闭内核1.8V供电,寄存器和RAM数据不能保持(除了电源控制/状态寄存器(PWR_CSR)、备份寄存器,其他数据都丢失);可通过唤醒引脚(PA0)上升沿、RTC闹钟中断,或者复位唤醒;唤醒后相当于复位,从复位地址开始执行。

三种模式的特性汇总如下表:

当stm32执行WFI(等待中断)或WFE(等待事件)指令后,即进入低功耗模式,这是两条汇编指令,实际使用时,HAL库已经为我们封装好了函数,只需要调用相应的C语言函数即可。

2)低功耗模式的使用

我们仍然以串口的工程为基础,在它上面添加设置,如下图,先设置外部中断:

再设置RTC:

注意添加的有:

RTC中,勾选active clock source、勾选active calendar;

勾选RTC alarm interrupt through EXTI line 17中断,这里注意一下,有的cubemx版本起初这个RTC alarm中断显示不出来,需要选一下上面的RTC OUT,选为输出,然后这个中断就显示出来了,之后再选择为无输出也还在;

选上PA0为唤醒引脚、PA1为外部中断1。

低功耗模式本身不需要特殊设置,生成HAL库工程文件时都会自带;这里选上RTC alarm中断、唤醒引脚、外部中断1,都是为了之后试验将cpu从低功耗模式中唤醒。

生成工程代码,在keil中打开。Stm32的hal库中已经封装好了低功耗模式的函数,但是为了便于使用我们自己需要的唤醒功能、实现我们需要的功耗控制,一般会把函数再封装一次。

a)sleep模式的使用

先看sleep模式的使用,进入sleep模式的代码如下:

因为所有的中断都能唤醒sleep模式,所以在进入sleep模式前,需要关闭systick中断,因为systick每1ms会产生一次中断,如果不关闭,则sleep模式会很快自动退出来;

接着是调用HAL库函数,进入sleep模式;

最后是恢复systick中断,这一步是为了在sleep模式被唤醒后,恢复原有的系统systick节拍。

之后,就可以调用这个函数,来进入sleep模式了。

由于sleep模式只是内核时钟关闭,外设是仍然在运行的,所以唤醒后系统的状态还和进入低功耗模式前一样。

b)stop模式的使用

stop模式使用时,进入stop模式的代码如下:

这里我们设置使用PA0为唤醒引脚,所以先清除它的中断标志;再调用HAL库函数进入stop模式。

之后就可以调用它来进入stop模式了。

但是要注意的一点是,stop模式被唤醒后,时钟默认使用的是内部RC振荡器,外设的时钟也被关闭了,所以要重新初始化时钟和外设,这部分功能,我们编写一个函数来实现:

(这里为了实现简单,把main函数初始化的一部分拷贝过来了,实际上有些函数可以简化)

这样,需要进入stop模式时,我们直接如下调用者两个函数即可:

enter_stop_mode();

exit_stop_mode();

enter_stop_mode()函数进入stop模式,设置PA0作为唤醒功能;被唤醒后,回到exit_stop_mode()处执行,恢复内核与外设时钟,再执行后面的其他程序。

c)standby模式的使用

standby模式使用时,进入standby模式的代码如下:

与stop模式是类似的,也是设置使用PA0为唤醒引脚,所以先清除它的中断标志;再调用HAL库函数进入standby模式。

由于standby模式被唤醒后,会从程序起始处开始执行,相当于复位,main函数的初始化程序都会再执行一遍,所以不用对退出standby模式作处理。使用时直接调用enter_standby_mode()函数即可。

此外,可以通过在程序起始时,判断电源控制/状态寄存器(PWR_CSR)的状态,来识别是从standby模式被唤醒的,还是系统被复位了,主要的代码如下:

3)低功耗和唤醒试验

现在我们来试验一下这几种低功耗模式的进入和唤醒。

在这之前,我们先编写一个RTC alarm的函数,使得可以方便地设置RTC闹钟时间,使用RTC唤醒,代码如下:

这个函数实现的功能是,先读取当年前的RTC时间,再将闹钟时间设置到当前时间加nsecond秒之后,然后启动RTC alarm中断,这样就能方便地设置到nsecond秒后产生RTC alarm中断。

在Main函数的主循环中添加如下测试sleep模式的代码:

先设置10s后RTC alarm中断,然后进入sleep模式;由于在生成工程时,我们还设置了外部中断PA1;所以,只要RTC计时达到10s、或者PA1上有下降沿,都会触发中断,退出sleep模式;退出之后,还进行了关闭RTC alarm中断的操作。程序运行结果如下图所示:

再试验stop模式,添加如下代码:

同样是开启10s后RTC中断,之后进入stop模式;退出stop模式后,也进行了关闭RTC alarm中断的操作。

这段程序运行时,stop模式也是能被RTC alarm、PA1(外部中断1)唤醒的,同时,由于我们设置了唤醒引脚PA0,在PA0上的上升沿也能唤醒。程序运行如下:

Standby模式试验,代码如下:

注意standby模式下,唤醒之后是类似复位,到程序的起始地址去执行了;

printf("fail to standby mode\t%d\r\n",count++);这一句,正常情况下是执行不到这里的。

这段代码运行的结果如下,可以看到,从standby模式中被唤醒后,没有执行之后的语句,而是“复位”了:

4)stm32的低功耗使用注意事项

a)程序起始时建议延时几秒再进入低功耗模式,否则一进入就不能使用下载口了,程序下载会很不方便;设置延时几秒再进,在上电之后几秒内完成下载就不会有问题;或者SWD接口之外,再连上复位线;

b)不用的IO口设置为模拟输入态最省电;cubemx里可以如下图设置,进入定低功耗模式前,将特殊的几个单独设置一下;

c)中断输入的引脚如果有上下拉,则会消耗电流;

d)如果外部晶振不使用,必须将引脚配置为输入上拉、下拉或者输出低电平,配置为浮空输入会消耗极大的电流(200uA);

e)输入引脚,如果高阻状态端口是高电平,就设成上拉输入,如果高阻状态是低电平,设成下拉输入,如果高阻是中间状态,设成模拟输入;输出引脚会耗电,如果可以尽量不用;

f)进入stop模式前,不要将pwr的clk关闭,实际测试关闭能用,也能唤醒,但是电流会增加10uA;实际上stop模式会关闭外设和内核时钟,不用单独去关闭其他外设的时钟;

g)在运行模式下、或者sleep模式下,由于时钟是还在的,降低时钟可以降低功耗。

欢迎关注我的公众号,可留言“资料”获取相关资料和代码:

posted @ 2021-11-23 01:50  xiaobaibai_2021  阅读(3518)  评论(0编辑  收藏  举报