实验现象
1、修改主频
修改主频不属于三种低功耗模式,但是也是降低STM32功耗的一种方法。
修改主频,在system_stm32f10.c这个文件。system_stm32f10.c用来配置时钟的,在文件里面程序预留了配置时钟的宏定义,将其中的宏定义解除注释,就能直接配置时钟的主频。


2、睡眠模式+串口发送+接收
这个代码的功能就是当收到一个字节时,中断触发,置标志位,主循环查询到标志位时读取数据,并用串口发送数据,在这个功能后面,又新加了一段代码,这个就是用来配置睡眠模式的代码,执行芯片就进入睡眠,睡眠的目的是,如果STM32一直没收到数据,那这个主循环也会一直查询标志位,让它睡眠,收到数据后自动退出睡眠模式,执行一遍任务后继续睡眠,这样在空闲时芯片一直在睡眠,可以降低系统功耗。
芯片在三种低功耗模式下,是没法直接下载程序的,如果直接点下载,就会提示报错,不会理你调试端口了。
解决方法,第一步我们按住复位键不放,第二步点下载按钮,第三步及时松开复位键,这样就能下载成功了。在我们本节三种低功耗模式下,都需要这样下载程序。注意一下,另外如果你不小心禁用了调试端口,其实也可以这样来解决。
只有在我们发送数据时刻,OLED才会显示一次running,在空闲时芯片一直都在睡眠,这样就是在不影响程序功能的前提下,使用睡眠模式节约电量。

3、停止模式+对射式红外传感器计次
下载的操作是:按住复位键不放,点击下载,在松手。每次遮挡一次,执行一次记次,也显示一下running。在没有外部中断信号时,STM32处于停止模式,可以省电。

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


在低功耗模式下,也需要保留必要的唤醒电路,比如串口接收数据的中断唤醒,外部中断唤醒,RTC闹钟唤醒等,在需要设备工作时,STM32能够立刻重新投入工作。如果你只考虑进入低功耗,而不考虑唤醒STM32,那不就跟直接断电没区别了吗,所以低功耗模式我们要考虑关闭哪些硬件,保留哪些硬件以及如何去唤醒,当然关闭越多的硬件设备越省电,唤醒就越麻烦。

最上面是模拟部分供电,叫做VDDA,中间是数字部分供电,包括两块区域,VDD供电区域和1.8v供电区域,下面是后备供电,叫做VBAT。


最下面:VBAT后备供电区域,其中包括LSE 32K晶体振荡器、后备寄存器,RCC BDCR计寄存器和RTC。
RCC BDCR是RTC的寄存器,叫做备份域控制寄存器,也是和后备区域有关的寄存器,所以也可以有VBAT供电。
低电压检测器,可以控制这个开关,VDD有电时,由VDD供电,VDD没电时,由VBAT供电。
首先是上电复位和掉电复位,这个意思是当VDD或者VDDA电压过低时,内部电路直接产生复位,让STM32复位住,不要乱操作。

这个复位和不复位的界限之间,设置了一个40mv的迟滞电压,大于上限POR,时解除复位,小于下限PDR时,复位。这是一个典型的迟滞比较器,设置两个阈值的作用,就是防止电压在某个阈值附近波动时,造成输出也来回抖动。
下面的复位信号reset是低电平有效,所以在前面和后面,电压过低时是复位的,中间电压正常的时候不复位。

电压上限和下限具体是多少伏:还有这里解除复位,还有个滞后时间是多久呢。
查看STM32数据手册,在5.3.3内嵌复位和电源控制模块特性里有这个表。:


然后下面这个是可编程电压监测器,简称PVD,他的工作流程也是监测VDD和,VDDA的供电电压。
但是PVD的区别就是,首先它这个阈值电压是可以使用程序指定的,可以自定义调节,调节的范围可以看一下数据手册。
在这个表的上面就是PVD的阈值,配置PLS寄存器的3个位,因为这里也同样是迟滞比较,所以有两个阈值,可选范围是2.2V到2.9V左右,PVD上限和下限之间的迟滞电压是100毫伏。


可以看到PVD的电压是比,上电掉电复位的电压要高的,画个图就是3.3伏是正常的供电,当这个电压降低在2.9伏到2.2伏之间,属于PVD监测的范围,可以通过PVD设置一个警告线,之后再降低到1.9伏,就是复位电路的检测范围,低于1.9伏直接复位住不让动,就是这两个电压监测的工作任务。

那当然PVD触发之后,芯片还是能正常工作的,只不过是电源电压过低,该提醒一下用户了。
所以看,下面这个PVD输出,这个是正逻辑,电压过低时为1,电压正常值为0,这个信号可申请中断,在上升沿或者下降沿时触发中断,提醒程序进行适当的处理,另外这个PVD的中断申请,是通过外部中断实现的。

,

看一下外部中断这里,可以看到PVD输出的信号是跑到这里来了,所以如果要使用PVD的话,记得要配置外部中断。
然后下面有RTC,是RTC的闹钟信号,也有接到外部中断,其实RTC自己是有中断的,那为啥还要借到外部中断:因为低功耗模式设计的是,只有外部中断可以唤醒停止模式。
后面这两个USB和ETH,也都只有他们的wake up唤醒信号接过来了,目的也是为了唤醒停止模式。

首先看一下睡眠模式,这是浅睡眠,进入浅睡眠,直接调用WFI或者WFE即可进入。
WFI的意思是wait for interrupt等待中断(意思是我先睡了,如果有中断发生的话再叫我起来),所以对应的唤醒条件是任意中断,调用WIFI进入的睡眠模式,任何外设发生任何中断时,芯片都会立刻醒来。
WFE,意思是wait for event等待事件,对应的唤醒条件是唤醒事件,这个事件可以是外部中断配置为事件模式,也可以是使能中断,但是没有配置NVIC。
调用WFE进入的睡眠模式,产生唤醒事件时会立刻醒来,醒来之后一般不需要进中断函数,直接从睡的地方继续运行,这是WFI和WFE的作用。
WFI/WFE区别相同点是调用任意一个之后,芯片都进入睡眠,不同点是WFI进入的得用中断唤醒,WFE进入的得用事件唤醒。
睡眠模式对电路的影响,只把CPU时钟关了,对其他电路没有任何操作,CPU时钟关了,程序就会暂停,不会继续运行了,CPU不运行芯片功耗就会降低。
关闭电路通常有两个做法:一个是关闭时钟,另一个是关闭电源。关闭时钟,所有的运算和涉及时序的操作都会暂停,但是寄存器和存储器里面保存的数据还可以维持不会消失。
关闭电源就是电路直接断电,电路的操作和数据都会直接丢失,所以关闭电源比关闭时钟更省电。
这个电压调节器,实际上是1.8V区域的电源,如果电压调节器关,就代表直接把1.8V区域断电。

第二个停机模式,进入停机模式,首先sleepdeep位设置为1,告诉CPU你可以放心的睡进入深度睡眠模式。

第三种待机模式,首先sleep deep也是置1即将深度睡眠。然后PDDS置1表示即将进入待机模式,最后调用WFI或者WFE就可以进入待机模式了。

当执行WFI等待中断或者WFE等待事件指令后,STM32进入低功耗模式,就说这两个指令是最终开启低功耗模式的触发条件,配置其他的寄存器都要在这两个指令之前。
看这个图,首先一旦WFI或者WFE执行了,会按照这个流程来判断,首先看看sleep deep位是1还是0,如果sleep deep=0 ,就是浅睡眠,对应的就是睡眠模式;如果sleep deep=1,表示要进入深度睡眠模式,对应的是停机或者待机模式。
在普通的睡眠模式,通过SLEEPONEXIT位来决定,这一位等于0时,无论程序在哪里调用WFI或WFE都会立刻进入睡眠,这位等于1时,执行WFI或WFE之后,它会等待中断退出,等所有中断处理完成之后再进入睡眠这个可能考虑到中断还有一些紧急的任务,最好不要被睡眠打断了,所以先等等也无妨。当然这两个细分模式我们一般可以不用管,只要我们不在中断函数里调用WFI或WFE,那其实它们的效果是一样的,我们WFI、WFE可以放在主程序里,如果主程序执行到了,自然也代表中断处理完成了,如果你想在中断函数里调用WFI、WFE,并且想中断结束后再睡眠,才需要考虑下面这个等待中断退出模式。
然后继续,进入深度睡眠模式,它会继续判断PDDS这一位,如果PDDS0,就进入的是停机模式,如果PDDS等于1,就进入的是待机模式。
在停机模式下,它会继续判断LPDS位,如果LPDS=0,就是停机模式且电压调节器开启,如果LPDS=1,就是停机模式且电压调节器低功耗。
电压调节器低功耗的特性就是更省电,但是唤醒延迟更高,那这些就是模式选择的一个判断流程。
睡眠模式

GPIO引脚的高低电平在睡眠模式下是维持原样的。
事件唤醒

停止模式

当一个中断或唤醒事件导致退出停止模式时,HSI被选为系统时钟:
我们的程序默认在SystemInit函数里的配置,是使用的HSE外部高速时钟,通过PLL倍频得到72MHz主频,但是进入停止模式后,PLL和HSE都停止了,而现在退出停止模式时,它并不会再自动倍速时钟,通过PLL倍频得到8MHz直接作为主频,所以如果你忽略了这个问题,那么就会出现一个现象,你程序刚上电是72MHz的主频,但是进入停止模式,在唤醒之后就变成8MHz的主频了,
解决办法:所以一般在停止模式唤醒后,第一时间就是重新启动HSE,配置主频为72MHz,这个操作也不麻烦,配置的函数他都帮我们写好了,我们只需要再调用下SystemInit就行。
**
**




主频越低,耗电越低,温度升高,耗电量也升高。
睡眠模式下供应电流

停机/待机模式供应电流

参考手册:



