PWR 电源控制-stm32入门

这一节我们来学习 STM32 的 PWR 电源控制。

其中,我们重点学习的主要就是 3 种低功耗模式:睡眠模式、停机模式和待机模式。

低功耗模式的目的呢?简单明了,就是省电,这对于一些使用电池供电,又需要长时间待机的设备,十分重要。

所以我们本节课的任务,就是学习电源控制部分,看看如何配置这些低功耗模式,让 STM32 在空闲时,能够尽可能地节省电量。

好,那先看一下本节最终的程序现象。本节总共有 4 个程序,分别是 13-1 修改主频;13-2 睡眠模式+串口发送+接收;13-3 停止模式+对射式红外传感器计次;13-4 待机模式+实时时钟。因为低功耗模式的代码都不是很多,所以多给大家演示几个。

那我们先看一下第一个程序,修改主频。修改主频不属于 3 种低功耗模式,但是也是降低 STM32 功耗的一种方法,这个代码非常简单,就是初始化显示一下 SystemCoreClock 这个变量,这个变量指示了当前主频频率,之后,主循环,以 1s 为周期,显示 Running,再清除。那我们看一下程序现象,目前可以看到,第一行 SCKCLK,系统主频,是 36 MHz;第二行,我们让它以 1s 为周期显示,但现在实际上是 2s 的周期,这是因为系统主频,正常情况下是 72 MHz,现在我们降频到 36 MHz 了,所以运行时间,就是原来的 2 倍。那这就是修改主频这个程序的现象,有关这个 system 文件的详细解释,还有配置主频的更多玩法,我们写程序的时候,再来介绍。

那在这个程序的哪个部分,我修改了主频呢?答案是在 system_stm32f10x.c 文件里,system 这个文件,里面就是用来配置时钟的,在 110 行这个位置,它给我们预留好了配置时钟的宏定义,我们只需要将其中一个宏定义解除注释,就能直接配置系统的主频,非常简单。目前看到,我是把 36 M 的宏解除注释了,所以目前主频就是 36 M,这个文件在我改之前默认是 72 M,如果我们把 72 M 解除注释,把 36 M 注释掉,这样系统主频就是 72 M 了,想配置为其他的频率,也是同理,先把原来的注释掉,再解除对应频率的注释即可,是不是非常简单。
我们编译下载看一下,可以看到,目前显示主频是 72 M,Running 闪烁的周期是 1s,这是默认主频 72M 的正常现象。

如果文件图标带有钥匙标志说明此文件为只读,必须先解除只读才能修改程序,解除只读的方法为:文件夹里找到文件 -> 右键 -> 属性 ->取消只读。

接着继续看第二个程序,睡眠模式 + 串口的发送和接收,那这个程序就是从串口那一节直接复制过来的,这个代码的功能就是,当收到一个字节时,中断触发,置标志位,主循环查询到标志位时,读取数据,并用串口发送出去,在这个功能后面,我又新加了一段代码,就是用来配置睡眠模式的,关键代码实际上就一句 __WFI(); 执行完这一句,芯片进入睡眠,睡眠的目的是如果 STM32 一直没收到数据,那这个主循环也会一直查询标志位,这是无意义的耗电操作,那不如我们就让它睡眠,收到数据后,自动退出睡眠模式,执行一遍任务后,继续睡眠,这样在空闲时,芯片一直在睡眠,可以降低系统功耗。那我们下载看一下程序现象,目前是串口发送加接收,我们按照串口那一节的接线接好串口,然后打开串口,随便发送一个数据,可以看到,STM32 成功接收,并回传了这个数据,这个现象和没使用睡眠模式的是一样的,但是,细节就在于,看一下第二行,只有在我们发送数据时刻,OLED 才会显示一次 Running,在空闲时,芯片一直都在睡眠,这样就是在不影响程序功能的前提下,使用睡眠模式节约电量,这就是这个程序的功能。

另外,还要重点提醒一下,芯片在 3 种低功耗模式下,是没法直接再下载程序的,你看现在是下载成功的,如果直接再点下载,就会提示报错,这是因为芯片现在在睡眠,不会理你调试端口了,解决方法也很简单,需要我们有一些操作:

  1. 第一步,我们按住复位键不放;
  2. 第二步,点下载按钮;
  3. 第三步,及时松开复位键。这样就能下载成功了。

在我们本节 3 种低功耗模式下,都需要这样下载程序,大家注意一下。另外,如果你不小心禁用了调试端口,其实也可以这样来解决。

接着继续看,第三个程序,停止模式 + 对射红外计次,这个程序是在之前外部中断那一节的代码基础上修改的,类似的操作,主循环中加入了 Running 的指示和最后进入停止模式的代码。那下载看一下程序现象,每遮挡一次,执行一次计次,也显示一下 Running,在没有外部中断信号时,STM32 处于停止模式,可以省电,这就是第三个程序的现象。

最后我们来看一下第四个程序,待机模式 + 实时时钟,这个程序是在实时时钟的基础上,加入了待机模式,目前这个程序,使用的是 LSE 外部低速时钟,如果你没有 RTC 晶振,或者 RTC 晶振不起振,也可以使用 LSI 内部低速时钟,LSI 在待机模式下,可以继续工作。然后在主循环中可以加入唤醒后要执行的功能,在进入待机模式之前,可以关闭各个外部连接的模块,以最大化省电,我目前是用 OLED_Clear(); 模拟了一下,那这个程序,会用实时时钟设定闹钟,每隔一段时间,会自动唤醒一次,这里我演示的是,每隔 10s 唤醒一次,唤醒之后,执行一遍程序任务,随后继续待机。那看一下程序现象,复位一下,可以看到 OLED 上显示了当前时间和闹钟,随后进入待机,然后等一会闹钟触发之后,自动唤醒一次,设定新的闹钟,执行程序功能,之后继续待机,等待下一次唤醒,这就是使用 RTC 和闹钟配合待机模式的自动唤醒程序。非常适合那种,需要每隔一段时间操作一次,空闲时间又需要最大化省电的设备。

好,那程序现象,我们就看到这里。接下来看一下 PWR 的理论部分。

1. PWR 理论部分

1.1 PWR 简介

PWR(Power Control,电源控制)

PWR 就是 Power 的缩写。

PWR 的作用:PWR 负责管理 STM32 内部的电源供电部分,可以实现 可编程电压监测器 和 低功耗模式 的功能。

PWR 有一部分是硬件的介绍,就是告诉你,内部供电电路的结构是啥样的,这些是设计硬件电路时要考虑的,暂时不涉及程序。涉及程序的功能,主要就是两个,一个是可编程电压监测器,另一个是低功耗模式。

可编程电压监测器(PVD)可以监控VDD电源电压,当 VDD 下降到 PVD 阀值以下或上升到 PVD 阀值之上时,PVD 会触发中断,用于执行紧急关闭任务。

这个功能预想的场景应该是,使用电池供电,或者对安全要求比较高的设备,如果供电电压在逐渐下降,在电压过低的情况下,可能会导致内部或者外部电路发送不确定的错误,为了避免不确定的因素,在电源电压低于设定的阈值时,我们可以主动出击,提前发出警告,并且关闭比较危险的设备,这是 PVD 的设计。不过 PVD 这个功能不是我们本节课的重点,我们暂时也不演示代码,大家了解即可,后续需要的话可以再研究。

低功耗模式* 包括睡眠模式(Sleep)、停机模式(Stop)和待机模式(Standby),作用就是:可在系统空闲时,降低STM32的功耗,延长设备使用时间。尤其是像一些用电池供电的设备,对空闲时候的耗电量是有极大要求的,比如数据采集设备,车钥匙,遥控器,报警器等等。

这些产品都有特点,就是在它们的生命周期里,绝大部分时间,都是空闲状态。但是我们知道,单片机程序一旦开始,正常运行的状态下,程序永远都不会停下来,所以主程序的最后,一般都是个死循环,即使需要空闲,让程序停下来,那也得来个空循环让程序一直转圈卡住。但是,程序运行就会耗电,空循环的耗电量也是很大的,比如遥控器,如果不用它的时候,程序一直空循环,那么用不到几天,电池就没电了,这显然是不行的。
所以说对于这些设备,我们需要这样的低功耗模式,在空闲状态时,关闭不必要的硬件,比如我直接把 CPU 断电,或者关闭时钟,这样程序自然就不会运行了。但是在低功耗模式下,我们也需要保留必要的唤醒电路,比如串口接收数据的中断唤醒、外部中断唤醒、RTC 闹钟唤醒,等等,在需要设备工作时,STM32 能够立刻重新投入工作,这样才行,如果你只考虑进入低功耗而不考虑唤醒,STM32 一睡不醒,那不就跟直接断电没区别了嘛。所以,低功耗模式,我们要考虑关闭哪些硬件,保留哪些硬件,以及如何去唤醒,当然关闭越多的硬件,设备越省电,唤醒就越麻烦,这也是这 3 种低功耗模式在设计时,所区分的地方。

这是本节的重点内容。英文大概记一下,前面两个应该都很熟悉,主要记一下 Standby,表示待机模式,这个在很多其他芯片里,都有出现。

那简介就看到这里,接着我们看一下电源框图。

1.2 电源框图

PWR 电源控制-stm32入门_第1张图片
这个图就是 STM32 内部的供电方案。其中有些部分我们之前也已经了解过,现在再来看看。整体上看,这个图可以分为 3 个部分。

  1. 最上面是模拟供电,叫做 VDDA(VDD Analog)。VDDA 供电区域,主要负责模拟部分的供电,其中包括 AD 转换器、温度传感器、复位模块、PLL 锁相环,这些电路的供电正极是 VDDA,负极是 VSSA。其中 AD 转换器还有两根参考电压的供电脚,叫做 VREF+ 和 VREF-,这两个脚在引脚多的型号里会单独引出来。在引脚少的型号,比如我们这个 C8T6,VREF+ 和 VREF- 在内部就已经分别接到了 VDDA 和 VSSA 了。

  2. 中间是数字部分供电,包括两块区域,VDD 供电区域和 1.8V 供电区域。左边部分是 VDD 供电区域,其中包括 IO 电路、待机电路、唤醒逻辑和独立看门狗;右边部分是 VDD 通过电压调节器,降压到 1.8V,提供给后面这一块的 1.8V 供电区域,1.8V 区域包括 CPU 核心、存储器和内置数字外设。可以看出,STM32 内部的大部分关键电路,CPU、存储器和外设,其实都是以 1.8V 的低电压运行的,当这些外设需要与外界进行交流时,才会通过 IO 电路转换到 3.3V;所以我们从外部看好像 STM32 内部全是 3.3V,但实际上它内部的 CPU、外设等,都是以 1.8V 供电运行,使用低电压运行的主要目的是降低功耗,电压越低,内部电路运行的功耗就相对越低。
    当然我们其实也不用了解这么多,主要是记住,CPU 核心、存储器和数字外设,都属于 1.8V 供电区域;而待机电路,唤醒逻辑等,属于 VDD 供电区域,它们的位置要清楚。然后电压调节器它的作用是给 1.8V 区域供电,因为后面我们会提到这个 1.8V 区域和电压调节器,你要知道是啥。

  3. 下面是后备供电,叫做 VBAT(V Battery)。VBAT 后备供电区域其中包括 LSE 32K 晶体振荡器、后备寄存器、RCC BDCR 寄存器和 RTC。RTC BDCR 是 RCC 的寄存器,叫备份域控制寄存器,也是和后备区域有关的寄存器,所以也可以由 VBAT 供电。然后上面有个低电压检测器,可以控制开关,VDD 有电时,由 VDD 供电;VDD 没电时,由 VBAT 供电。

好,那这些就是电源框图的介绍了。大家需要了解的是,STM32 内部有哪几部分供电区域,以及每部分供电区域里都有啥,这就是这个框图的内容。

然后继续看下两个图,分别是上电复位和掉电复位还有可编程电压监测器。这两个内容了解即可,快速介绍一下。

1.3 上电复位和掉电复位

PWR 电源控制-stm32入门_第2张图片
首先是上电复位和掉电复位。这个的意思是,当 VDD 或者 VDDA 电压过低时,内部电路直接产生复位,让 STM32 复位住,不要乱操作,这个复位和不复位的界限之间,设置了一个 40 mV 迟滞电压,大于上限 POR(Power On Reset)时解除复位,小于下限 PDR(Power Down Reset)时复位。这是一个典型的迟滞比较器,设置两个阈值的作用,就是防止电压在某个阈值附近波动时,造成输出也来回抖动。下面的复位信号 Reset,是低电平有效的,所以在前面和后面,电压过低时,是复位的,中间电压正常的时候,不复位。

那这个电压上限和下限,具体是多少 V 呢,还有这里解除复位,还有个滞后时间,是多久呢,这些参数,可以看一下 STM32 数据手册,在 5.3.3 内嵌复位和电源控制模块特性里有个表,这里写了上电或掉电复位阈值,下降沿,也就是 PDR 掉电复位的阈值下限,典型值是 1.88V;上升沿,也就是 PDR 上电复位的阈值上限,典型值是 1.92V;1.92 - 1.88 V 就是迟滞的阈值,40 mV,所以如果忽略迟滞的话,简单来说,就是大于 1.9V 上电,低于 1.9V 掉电。然后最后一行,就是 TRSTTEMPO 复位持续时间,典型值是 2.5 ms,这就是这个上电复位和掉电复位。知道一下就行,也不需要我们操作啥的。

1.4 可编程电压监测器

PWR 电源控制-stm32入门_第3张图片
然后下面这个是可编程电压监测器,简称 PVD。它的工作流程和上面那个上电复位和掉电复位差不多,都是监测 VDD 和 VDDA 的供电电压。但是 PVD 的区别就是,首先它这个阈值电压是可以使用程序指定的,可以自定义调节,调节的范围可以看一下数据手册,在内嵌复位和电源控制模块特性的表的上面就是 PVD 的阈值,配置 PLS 寄存器的 3 个位,可以选择右边这么多的阈值,因为这里也同样是迟滞比较,所以有两个阈值,可选范围是 2.2V 到 2.9V 左右,PVD 上限和下限之间的迟滞电压是 100 mV。可以看到,PVD 的电压是比上电掉电复位的电压要高的。

画个图就是 3.3V 是正常的供电,当这个电压降低在 2.9V 到 2.2V 之间,属于 PVD 监测的范围,可以通过 PVD 设置一个警告线,之后再降低到 1.9V,就是复位电路的监测范围,低于 1.9V,直接复位住,不让动了,这是这两个电压监测的工作任务。那当然,PVD 触发之后,芯片还是能正常工作的,只不过是电源电压过低,该提醒一下用户了。

所以看一下下面这个 PVD 输出,这个是正逻辑,电压过低时为 1,电压正常时为 0,这个信号,可以去申请中断,在上升沿或者下降沿时,触发中断,以此提醒程序进行适当的处理。另外,这个 PVD 的中断申请是通过外部中断实现的,我们可以看一下外部中断这一节的 EXTI 基本结构图,可以看到,PVD 输出的信号是跑到这里来了,所以如果要使用 PVD 的话,记得要配置外部中断。然后下面这里还有 RTC,这个是 RTC 的闹钟信号,也有借道外部中断,其实 RTC 自己是有中断的,那为啥还要借道外部中断呢?因为低功耗模式设计的是,只有外部中断可以唤醒停止模式,其他这些设备,也想唤醒停止模式的话就可以通过借道外部中断来实现。其中后面这两个 USB 和 ETH,也都只有它们的 WeakUp,唤醒信号接过来了,目的,也是为了唤醒停止模式,这个了解一下。

好,这两个电压监测的内容,就介绍这么多。

接着,我们来看本节的重点,低功耗模式。

1.5 低功耗模式

PWR 电源控制-stm32入门_第4张图片
这个表,是低功耗模式一览,其中对 3 种模式进行了详细的对比。

我们看一下,第一列就是有哪几种模式;第二列是如何配置,才能进入我们想要的模式;第三列是对于这些模式,进入之后,如何去唤醒,也就是模式的退出,毕竟我们肯定也不想让它一睡不醒,该干活的时候,还是要醒来干活的;最后三列,是每种模式对电路的操作,关闭了哪些东西,就是哪些电路不能用了,保留了哪些东西,就是哪些电路还是正常工作的,这些我们要清楚,那依次来看一下。

首先,低功耗模式有 3 种:睡眠、停机和待机。这 3 种模式,从上到下,关闭的电路越来越多,对应的,从上到下,是越来越省电,同时,从上到下,也是越来越难唤醒的,这符合我们的常识,睡得越深,关的越多,越省电,越难叫醒。

  1. 首先看一下睡眠模式,这是浅睡眠,相当于打了个盹。如何进入呢?这里写了,直接调用 WFI 或者 WFE,即可进入,这两个东西是内核的指令,对应库函数里,也有对应的函数,直接调用函数即可。其中 WFI 的意思是 Wait For Interrupt,等待中断,意思就是,我先睡了,如果有中断发生的话,再叫我起来,所以对应的唤醒条件是任一中断,调用 WFI 进入的睡眠模式,任何外设发生任何中断时,芯片就会立刻醒来,因为中断发生了,所以醒来之后的第一件事,一般就是处理中断函数;然后下面 WFE,意思是 Wait For Event,等待事件,对应的唤醒条件是,唤醒事件,这个事件可以是外部中断配置为事件模式,也可以是使能了中断,但是没有配置 NVIC,调用 WFE 进入的睡眠模式,产生唤醒事件时,会立刻醒来,醒来之后,一般不需要进中断函数,直接从睡的地方继续运行,这就是 WFI 和 WFE 的作用。相同点是,调用任意一个之后,芯片都进入睡眠,不同点是,WFI 进入的得用中断唤醒,WFE 进入的得用事件唤醒。
    之后看一下睡眠模式对电路的影响,对 1.8V 区域时钟的影响是,CPU 时钟关,对其他时钟和 ADC 时钟无影响;对 VDD 区域时钟的影响是,无;对电压调节器的操作是,开。所以睡眠模式对电路的影响就是只把 CPU 时钟关了,对其他电路没有任何操作。CPU 时钟关了,程序就会暂停,不会继续运行了,CPU 不运行,芯片功耗就会降低。
    好,睡眠模式,我们就清楚了,它关的东西很少,就只是把 CPU 时钟关了。程序暂停运行,寄存器的数据都还在。它的唤醒条件也是比较宽松,任何的风吹草动,CPU 都会醒来,开始干活。所以睡眠模式,相当于大脑打了个盹,身体还在工作,在省电程度上,评级为“一般省电”。

另外这里还可以看出,关闭电路通常有两个做法:一个是关闭时钟,另一个是关闭电源。关闭时钟,所有的运算和涉及时序的操作都会暂停,但是寄存器和存储器里面保存的数据还可以维持,不会消失;关闭电源,就是电路直接断电,电路的操作和数据都会直接丢失。所以,关闭电源,比关闭时钟更省电,这个表里的第 4、5 这两列,就是对 1.8V 区域和 VDD 区域的时钟控制;然后这个电压调节器,刚才看了,它实际上就是 1.8V 区域的电源,如果电压调节器关,就代表直接把 1.8V 区域断电,这个了解一下。

  1. 然后继续看第二个,停机模式。如何进入停机模式呢?首先 SLEEPDEEP 为设置为 1,告诉 CPU,你可以放心的睡,进入深度睡眠模式;另外,PDDS 这一位,用来区分它是停机模式还是下面的待机模式,PDDS = 0,进入停机模式,PDDS = 1,进入待机模式,所以想要进入停机模式,PDDS 要事先设置为 0;之后,LPDS 用来设置最后这个电压调节器,是开启,还是进入低功耗模式,LPDS = 0,电压调节器开启,LPDS = 1,电压调节器进入低功耗。最后,当我们把这些位提前设置好了,最后再调用 WFI 或者 WFE,芯片就可以进入停止模式了。然后停止模式的唤醒,因为这个模式下,芯片睡得更深,关的东西更多,所以唤醒条件就苛刻一些,是任一外部中断。刚才睡眠模式是任一中断,所有外设的中断都行,现在停止模式,要求就是只有外部中断才能唤醒了,其他中断唤醒不了。刚才我们还提到了,PVD、RTC 闹钟、USB 唤醒、ETH 唤醒,借道了外部中断,所以这 4 个信号,也可以唤醒停止模式,另外这里并没有区分 WFI 和 WFE,其实也可以想象得到,WFI 要用外部中断的中断模式唤醒,WFE 要用外部中断的事件模式唤醒,这是对应的。
    之后看,停止模式对电路有哪些操作呢?首先,关闭所有 1.8V 区域的时钟,这意思就是,不仅 CPU 不能运行了,外设也运行不了,定时器,正在定时的,会暂停,串口,收发数据,也会暂停;不过由于没关闭电源,所以 CPU 和外设的寄存器数据都是维持原状的。之后下一个,HSI 和 HSE 的振荡器关闭,既然 CPU 和外设时钟都关了,那这两个高速时钟,显然也没用了,所以 HSI 内部高速时钟和 HSE 外部高速时钟,会关闭;当然,它没提到的 LSI 内部低速时钟和 LSE 外部低速时钟,这两个并不会主动关闭,如果开启过这两个时钟,还可以继续运行。最后,电压调节器,这里可以选择是开启,或者处于低功耗模式,刚才说了,这个电压调节器是由这个 LPDS 位控制的,这个开启和低功耗模式有啥区别呢?其实区别不大,电压调节器无论是开启还是低功耗,都可以维持 1.8V 区域寄存器和存储器的数据内容。区别就是,低功耗模式更省电一些,同时,低功耗模式在唤醒时,要花更多的时间;相反,电压调节器开启的话,就是更耗电一些,唤醒更快了。
    那这些就是停止模式的介绍。主要操作就是,把运行的高速时钟都关了,CPU 和外设,都暂停工作,但是电压调节器并没有关,存储器和寄存器数据可以维持原样。它的唤醒条件比较苛刻,只能通过外部中断唤醒,所以停止模式,相当于整个人都罢工了,脑子不工作,身体也不工作,只有有人用外部中断过来敲我,我才会醒来干活。在省电程度上,评级为“非常省电”。

  2. 最后我们看第三种,待机模式。进入的话,和停机模式差不多,首先 SLEEPDEEP 也是置 1,即将深度睡眠,然后 PDDS 置 1,表示即将进入待机模式,最后调用 WFI 或者 WFE,就可以进入待机模式了。然后看一下唤醒条件,普通外设的中断和外部中断,都无法唤醒待机模式,待机模式,只有这几个指定的信号才能唤醒:第一个是 WKUP 引脚的上升沿,WKUP 引脚,可以看一下引脚定义表,里面 PA0-WKUP 指示了 WKUP 引脚的位置就是 PA0 的位置。之后继续,第二个是 RTC 闹钟事件,这个我们的示例代码和上一节 RTC 提到过,RTC 闹钟可以唤醒待机模式,应用场景就是,芯片每隔一段时间自动工作一次。第三个,是 NRST 引脚上的外部复位,意思就是按一下复位键,它也是能唤醒的。最后一个,IWDG 独立看门狗复位,这个了解一下就行,看门狗我们之后介绍。好,可以看出,待机模式只有这指定的 4 个信号能唤醒,其他信号都唤醒不了,唤醒条件最为苛刻。之后待机模式,对电路的操作,基本上是能关的全都关了,1.8V 区域的时钟关闭,两个高速时钟关闭,电压调节器关闭,这个意味着 1.8V 区域的电源关闭,内部的存储器和寄存器的数据全部丢失。但是和停止模式一样,它并不会主动关闭 LSI 和 LSE 两个低速时钟,因为这两个时钟还要维持 RTC 和独立看门狗的运行,所以不会关闭。这就是待机模式的介绍,主要操作就是把能关的全都关掉,只保留几个唤醒的功能,当然,配合 RTC 和独立看门狗的低速时钟,也可以正常工作。所以待机模式,相当于这个人直接下班回家睡觉了,没有指定的这几个事,它是不会轻易回来工作的。在省电程度上,待机模式评级为“极为省电”。

好,以上就是这 3 种低功耗模式的详细介绍以及它们之间的区别,相信大家对这几种模式已经有了大概的了解了吧,接下来我们对这里的一些细节问题再额外补充和总结一下。

1.5.1 模式选择

首先是模式选择的问题。刚才上面的表述,出现了很多寄存器的位。其中这些模式,又有一些更细的划分,比如睡眠模式有 SLEEP-NOW 和 SLEEP-ON-EXIT 的区别;停机模式有电压调节器开启和低功耗的区别。我们如何配置才能指定某个模式呢?那看这个图,就比较清晰了。
PWR 电源控制-stm32入门_第5张图片
当然这些寄存器,实际上库函数已经帮我们封装好了,不用我们自己配置的。但是多了解一些,对我们理解程序还是有很大帮助的。

首先有一句:执行 WFI(Wait For Interrupt,等待中断)或者 WFE(Wait For Event,等待事件)指令后,STM32进入低功耗模式。就是说这两个指令是最终开启低功耗模式的触发条件,配置其他的寄存器,都要在这两个指令之前。

看一下这个图,首先,一旦 WFI 或者 WFE 执行了,芯片咋知道他要进入哪种低功耗模式呢?那它就会按照这个流程来判断。

首先看看 SLEEPDEEP 位是 1 还是 0,如果 SLEEPDEEP = 0,就是浅睡眠,对应的就是睡眠模式;如果 SLEEPDEEP = 1,表示要进入深度睡眠模式,对应的是停机或者待机模式,停机和待机,都可以叫做深度睡眠模式。在普通的睡眠模式下,还有个细分的功能,通过 SLEEPONEXIT 位来决定,这一位等于 0 时,无论程序在哪里调用 WFI/WFE,都会立刻进入睡眠;这一位等于 1 时,执行 WFI/WFE 之后,它会等待中断退出,等所有中断处理完成之后,再进入睡眠,这个可能考虑到中断还有一些紧急的任务,最好不要被睡眠打断了,所以先等等也无妨。当然这两种细分模式,我们一般可以不用管,只要我们不在中断函数里调用 WFI/WFE,那其实它们的效果是一样的;我们 WFI/WFE 可以放在主程序里,如果主程序执行到了,自然也代表中断处理完成了;如果你想在中断函数里调用 WFI/WFE,并且想中断结束后再睡眠,才需要考虑下面这个模式。

然后继续看,进入深度睡眠模式,它会继续判断 PDDS 这一位,如果 PDDS = 0,就进入的是停机模式;如果 PDDS = 1,就进入的是待机模式。在停机模式下,它会继续判断 LPDS 位,如果 LPDS = 0,就是停机模式且电压调节器开启;如果 LPDS = 1,就是停机模式且电压调节器低功耗,电压调节器低功耗的特性就是:更省电,但是唤醒延迟更高。

那这些,就是模式选择的一个判断流程。通过这个图,看的应该就比较清晰了。最后我们再分别总结一些这三种模式的一些特性。

1.5.2 睡眠模式

首先是睡眠模式。

  • 执行完 WFI/WFE 指令后,STM32 进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行。

一般我们可以在主循环的最后,执行一下 WFI/WFE。主循环执行一遍,就睡眠;然后唤醒后,主循环又执行一遍,再睡眠;每唤醒一次,主循环执行一遍。

  • SLEEPONEXIT 位决定 STM32 执行完 WFI 或 WFE 后,是立刻进入睡眠,还是等 STM32 从最低优先级的中断处理程序中退出时进入睡眠。

  • 在睡眠模式下,所有的 I/O 引脚都保持它们在运行模式时的状态

比如,如果你在程序里进行点灯,灯点亮了,再进入睡眠,灯仍然是亮的,GPIO 引脚的高低电平在睡眠时是维持原样的。

  • WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒
  • WFE指令进入睡眠模式,可被唤醒事件唤醒

这个唤醒事件还是有些复杂的。可以看一下手册,在手册睡眠模式这一节,有对睡眠模式的唤醒事件描述,其中说了,唤醒事件可以通过下述方式产生。

  1. 第一种,在外设控制寄存器中使能一个中断,而不在 NVIC 中使能;并且,还要在内核的系统控制寄存器中使能 SEVONPEND(Send Event On Pend)位,这样才能产生唤醒事件,并且唤醒后,要及时清除挂起位才行。
  2. 第二种,就是配置 EXTI 为事件模式,这个直接配置即可。

所以看到,这个事件唤醒还是有点麻烦的,你要是觉得麻烦,直接使用中断唤醒的方式,也是可以的,还简单一些。这就是事件唤醒的一些描述。

那睡眠模式总结的一些知识点就这么多。

1.5.3 停止模式

接下来看停止模式。

  • 执行完 WFI/WFE 指令后,STM32 进入停止模式,程序暂停运行,唤醒后程序从暂停的地方继续运行

和睡眠模式一样。因为睡眠模式和停止模式存储器和寄存器的内容都可以维持,所以唤醒后,程序可以直接在暂停的地方继续运行。

  • 1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下来。

这个刚才那个一览表介绍过。CPU 和外设的时钟都停止,但是没有断电,SRAM 和寄存器的数据还可以维持。

  • 在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态

这个和睡眠模式一样。GPIO 在进入睡眠或者停止模式时暂停,并且高低电平维持暂停前一刻的状态。

  • 当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟

这一条是涉及编程的注意事项。我们的程序,默认在 SystemInit 函数里的配置,是使用的 HSE 外部高速时钟,通过 PLL 倍频,得到 72 MHz 主频;但是进入停止模式后,PLL 和 HSE 都停止了,而且在退出停止模式时,它并不会再自动帮我们开启 PLL 和 HSE,而是默认用 HSI 的 8 MHz,直接作为主频,所以如果你忽略了这个问题,那么就会出现一个现象,你程序刚上电,是 72 MHz 的主频,但是进入停止模式,再换醒之后,就变成了 8 MHz 的主频了,这是一个问题。所以我们一般在停止模式唤醒后,第一时间就是重新启动 HSE,配置主频为 72 MHz,这个操作也不麻烦,配置的函数它都帮我们写好了,我们只需要再调用一下 SystemInit 就行,这是这个问题。

  • 当电压调节器处于低功耗模式下,系统从停止模式退出时,会有一段额外的启动延时

这个就是刚才电压调节器开启和低功耗模式的区别了。电压调节器低功耗,更省电,但是从停止模式退出时,会有一段额外的启动延时。

  • WFI指令进入停止模式,可被任意一个EXTI中断唤醒
  • WFE指令进入停止模式,可被任意一个EXTI事件唤醒

最后两条是 WFI 和 WFE 的区别。停止模式,只能通过 EXTI 唤醒。中断模式唤醒 WFI,事件模式唤醒 WFE。

那以上就是停止模式的相关知识点。

1.5.4 待机模式

最后,我们看一下待机模式。

  • 执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行

这个和上面两个模式就有些区别了。待机模式下唤醒,程序是从头开始运行的,因为待机模式把内部大部分电路的电源直接断了,数据都丢失了。唤醒之后,程序也无法继续,只能从头开始。

  • 整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电

能断的都断掉,不过备份寄存器和待机电路还是可以维持供电的。

在待机模式下,所有的I/O引脚变为高阻态(浮空输入)

对于输出来说,既不输出高电平,也不输出低电平,呈现高阻态。对于输入来说,不上拉也不下拉,呈现浮空输入状态。实际上 GPIO 在配置里没有高阻态这个配置,它其实就是浮空输入配置,浮空输入,对于输出而言,就是高阻态。所以说,如果你提前点了个灯,进入待机模式后,无论这个灯是高电平点亮还是低电平点亮,它都会熄灭,GPIO 对外不输出高低电平,也不流过电流。

  • WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式。

这 4 个是待机模式的唤醒条件,刚才也说过。

那这些,就是待机模式的一些描述。

到这里,我们这个知识点,就介绍完了。

1.6 数据手册和参考手册

最后,我们分别看一下数据手册和参考手册。

1.6.1 数据手册

首先看一下数据手册。刚才我们说了,睡眠模式是一般省电,停止模式是非常省电,待机模式是极为省电。说了这么多省电,到底有多省呢?我们看一下数据手册,用数据说话。在手册这里,5.3.5 供电电流特征,有介绍,这里测试条件比较多,表也比较多,另外耗电量在不同工作条件下都是不同的,做产品的话,具体值还是以实测为准,现在我们就大概看一下官方给的一些测试表,看一下各个模式的耗电范围。首先这个表是从 Flash 运行,正常运行模式下的供应电流,条件是外部时钟,使能所有外设和关闭所有外设,然后各个主频下的电流消耗,在右边,可以看到,耗电电流区间是几到几十,单位是 mA,最高是 50mA 左右,最低是 7mA 左右。上下对比,使能所有外设,比关闭所有外设更耗电,所以,为了省电,不需要的外设,我们可以把它的时钟关掉;另外,对于频率来说,降低主频,对于省电,也是很划算的,降低主频后,耗电电流,下降也很明显。所以,如果你需要设备连续运行,并且对于主频和性能没那么高要求的话,降低主频也是一个不错的选择,这就是这个表的数据。

然后下面这个,是从 RAM 运行的耗电数据。整体上来看,比上面这个表低一些,但是差别不大。然后下面这个图里,可以看出主频、温度和耗电的关系,主频和耗电大概上是一个正比的关系,72M,耗电 40mA 左右,频率降低一半,36M,耗电大概也降低一半,20mA 左右,36M 再降低一半,是 18M,可以看到这个相近的 16M,差不多电流也降低了一半,16M 再降低一半,8M,电流继续降低一半,所以主频越低,耗电越低,主频每降低一半,耗电大概就也降低一半,当然只是大概一半的关系,并不是严格对应的;然后再看温度,温度升高,耗电量也是升高的,当然影响并不是很大。这就是这个图可以看出来的特征。

接着继续,我们看睡眠模式,这是睡眠模式下的供应电流,它的耗电也是 mA 级别的,从几 mA 到几十 mA 不等。但是整体上来看,比正常运行的耗电是低一些的,比如正常运行的情况下,最大刚才看了是 50mA 左右;在睡眠模式下,这个最大电流,降低到了 30mA 左右,会省一些电,但是耗电也是 mA 级别的,只能算是一般省电。

之后继续,我们看下一个表,这是停机模式下的供应电流和待机模式下的供应电流,这些是测试条件,大家可以仔细看看。那看右边的数据呢?首先,这个电流的单位是 μA 级别,在停机模式下,3.3V 供电时耗电电流典型值是 14~24 μA,这个就非常省电了;在待机模式下,电流会进一步降低,典型值是 2~3 μA 左右,可以算是极为省电了。举个例子呢?为了方便计算,我近似取个值,假设正常运行电流是 30mA,停机模式电流是 30μA,待机模式是 3μA,那么对应一个 300mAh 的电池来说,正常运行能用 10 个小时,停机模式能用 1 万个小时,待机模式能用 10 万个小时,这个对比,差别就比较大了吧。所以如果你的产品使用了电池供电,低功耗模式,还是要考虑用一下的。

最后我们看到,备份区域的供应电流,也非常低,RTC 开启的情况下,也只需要 1.4 μA,所以备用电池接上一个,基本不用担心没电的。

那有关 STM32 各个状态下的电量消耗,我们就看到这里。剩下的一些表格和数据,大家可以自己再看看。

最后,我们还是照例,看一下参考手册。

1.6.2 参考手册

我们本节介绍的内容,位于参考手册第 4 节,电源控制 PWR。

看一下,首先是整体的电源框图,内部电源有哪些区域,通过哪些引脚供电,这个了解一下;下面有一些详细的解释,比如独立的 AD 转换器供电和参考电压,这些是 VDDA 和 VREF 相关引脚的介绍,100 脚和 144 脚封装有单独的 VREF,64 脚或更少的封装,没有 VREF,它们在芯片内部与 ADC 的电源相联;之后下面是电池备份区域的,这里有一些警告和建议,这个我们上一节讲 RTC 电路的时候说过。

当然这里还有一个注,写的是因为模拟开关只能通过少量的电流(3mA),在输出模式下使用 PC13~PC15 的 I/O 口功能是有限制的,速度必须限制在 2MHz 以下,最大负载为 30pF;而且这些 I/O 口绝对不能当作电流源,如驱动 LED。
它这里特意强调了,PC13~PC15 端口绝对不能驱动 LED。但有意思的是,我们这个最小系统板,它上面有两个 LED,一个是电源指示灯,另一个是接在 GPIO 口的测试灯,并且,这个接在 GPIO 口的测试灯,它就正好位于 PC13,所以说,我们这个最小系统板的电路设计,违背了这条注意事项。不过好在,这个贴片的小 LED,电流并不是很大,目前也没有什么问题。但是它要是真的导致 GPIO 损坏,你也不能怪它没提醒你,所以,我们在做产品之前,还是要仔细阅读手册,知道的越多,就越不容易犯错。

然后继续,下面是电压调节器,有 3 种模式,正常运转、低功耗和停止供电。再看下面,这是上电复位和掉电复位的介绍,这个图和功能,我们也讲过。下面是可编程电压监测器,大家可以看一下。

之后,就是低功耗模式的介绍了,低功耗一览表,总共有睡眠、停机、待机,三种模式。下面是一些省电建议,首先就是降低系统时钟,降频后,功耗会明显降低,刚才通过那个数据手册也看过;然后是外部时钟的控制,不需要的外设,我们可以把时钟给关掉,以减少功耗;另外,在睡眠之前,也可以关闭所有外设的时钟来省电,不过这样,睡眠模式下的外设,就干不了活了。

然后下面是睡眠模式,执行 WFI 或 WFE 进入睡眠,可以选择立刻睡眠,或者等中断结束后再睡眠;退出睡眠呢,在这里也有介绍,和我们介绍的一样。

接着是停止模式,如何进入,如何退出,以及一些注意事项,大家可以自己再看看。

然后是待机模式,这些介绍也可以再看看。

最后这里有个低功耗模式下的自动唤醒,这里的意思就是,使用 RTC 可以在停止模式或待机模式下定期唤醒芯片,也就是我们第四个示例代码演示的现象。

然后下面就是一些寄存器描述了。控制寄存器,里面是一些控制位,比如 BKP 位,取消后备区域写保护;PLS,选择 PVD 电平;PDDS,选择是停止模式还是待机模式;LPDS,选择停止模式下电压调节器是开始还是低功耗;这些位就是在这里定义的。

然后,控制/状态寄存器,里面是一些控制位和标志位。比如使能 WKUP 引脚和一些标志位。最后就是寄存器总表了,寄存器不多,总共就两个。

好,那到这里,本节 PWR 的知识点我们就介绍完了。我们下一小节,来学习低功耗模式的相关代码。

你可能感兴趣的:(stm32,stm32,单片机,嵌入式硬件)