背景:想要做一个用两节5号干电池供电的闹钟,想着不能耗电太大,频繁更换电池,于是就开始学习了STM32的低功耗模式。
首先看了STM32的参考文档,写着低功耗模式有三种,典型的一张图:
同时也写了一点文字描述:
如何理解这三种模式呢?
1.对睡眠模式理解:大白话说就是,内核停止读写指令,可以理解成就是进入while(1); 然后没有任何程序在那空循环这个时候就可以进入睡眠模式,设置过的外设不受影响,比如timer还在计数,IO的输出状态不变,碰到了有中断可以进入中断函数处理。
比如main.c文件中
#include "stm32f10x.h"
int main()
{
port_init();
timer_init();
nvic_init();
while(1)
{
}//enter sleep mode
}
2.对停机模式的理解:内核停止运行了,所有设置过的外设也都停止了,timer不计了,当然设置过的IO状态还是不变的,就是所有需要时钟驱动的东西都停止了(RTC还可以计),只剩下供电了。
3.对待机模式的理解:时钟都停止了,供电也没了(除了一些关键部分的电路),因为供电都没了,设置过的寄存器也都恢复复位了,比如IO也不输出了。唤醒之后就相当于重新上电了,程序从头开始执行。(通过供电可以大概区分出停机和待机的区别,虽然不严谨但是理解起来比较形象)
4.除了以上三种模式,我觉得可以再加一种就是主频分频变低频率,参考文档上的图:
比如将主频变成1Mhz也就0.9mA。
(PS:1.如果对时钟精度没有太严要求选用HSI(芯片内部的RC振荡器)要比选用HSE更加省电。
2.文档上的参数是准确的,如果实验过程发现跟文档对不上那么配置的肯定有问题,比如切换成了HSI后要把HSE disable以及PLLdisable。
3.
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);//HSI作为系统时钟
RCC_HSEConfig(RCC_HSE_OFF);
RCC_PLLCmd(DISABLE);//ʹÄÜPLL
RCC_HCLKConfig(RCC_SYSCLK_Div8);
)
另外,文档虽然写的默认是HSI,但测试发现一上来就有20mA左右,debug之后发现启动文件中
SystemInit这个东西会重新配置成PLL,需要重新配置一下,或者宏定义一下。
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit //这个东东!!!!!!//
BLX R0
LDR R0, =__main
BX R0
ENDP
void SystemInit (void)
{
.....
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
#endif
/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
/* Configure the Flash Latency cycles and enable prefetch buffer */
SetSysClock();//@@@@@@@@@@@@@那个东东里面有这个东东@@@@@@@@@@@
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
static void SetSysClock(void) //@@@@@@@就是这个东东@@@@@@@@@@
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
#endif
/* If none of the define above is enabled, the HSI is used as System clock
source (default after reset) */
}
经过测试发现还是不用那三种低功耗了,用降频的方法更好用一些,相比于十几颗LED做的数码管显示降频也就是多用了半颗LED而已。
贴上进入低功耗的函数
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);//使能电源时钟和备份域时钟
PWR_WakeUpPinCmd(ENABLE); //使能唤醒管脚功能
PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFE);//进入stop模式
//PWR_EnterSTANDBYMode(); //进入待机模式