实验目的
本章学习STM32的低功耗控制,掌握如何进入低功耗状态以及如何从此状态唤醒,数据手册请参看第四章电源控制PWR中的内容
实验简介
现在很多MCU都有低功耗控制,当需要系统省电时,就需要进入适当的低功耗模式来降低系统的功耗,尤其当MCU用在电池供电的设备上时,低功耗尤为重要,下面我们介绍STM32的3种低功耗以及唤醒条件。
睡眠模式:进入睡眠模式时,内核时钟停止,从睡眠模式中恢复不需要任何特殊的序列,但要重新使能ARM内核的时钟。在睡眠模式下,指令的执行被中止直至复位或中断出现。外设在CPU内核处于睡眠模式期间继续运行,并可产生中断使处理器恢复执行指令。睡眠模式下,处理器内核自身,存储器系统,有关控制器及内部总线停止工作,因此这些器件的动态功耗会降低,只要出现任何使能的中断,CPU内核就会从睡眠模式中唤醒。
停止模式:在停止模式下电压调节器可运行在正常或低功耗模式。此时在1.8V供电区域的所有时钟都被停止,PLL,HSI,和 HSE RC振荡器的功能被禁止,SRAM和寄存器内容被保留下来。在停止模式下,所有I/O引脚都保持他们在运行模式时的状态。
停止模式进入和退出
待机模式:待机模式可实现系统的最低功耗。该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个1.8V供电区域被断开。PLL ,HSI 和 HSE 振荡器也被断电。SRAM和寄存器内容丢失。只有备份的寄存器和待机电路维持供电。
待机模式的进入和退出
这三种模式最低功耗的是待机模式,其只需要2uA左右的电流,停机模式是次低功耗的,其典型的电流消耗在20uA左右。最后就是睡眠模式了。
代码
待机模式
main.c
#include "MyIncludes.h"
u16 sys_cnt = 0;
void systick_isr(void)
{
if(sys_cnt <100)
sys_cnt++;
else
{
sys_cnt = 0;
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5);
}
}
void Key_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__GPIOC_CLK_ENABLE();
//使能c时钟
GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_3 ;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;//输入
GPIO_InitStruct.Pull = GPIO_NOPULL;//上拉
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;//高速
HAL_GPIO_Init(GPIOC,&GPIO_InitStruct);
}
int main(void)
{
System_Init();
LED_Init();
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_RESET);
delay_ms(2000);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_SET);
delay_ms(1000);
SysTick_Init(systick_isr);
Key_Init();
LowPWR_Init();
//低功耗初始化
while(1)
{
while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_3) == GPIO_PIN_RESET )
{
}
//等待按键松开
delay_ms(50);
if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_3) ==GPIO_PIN_RESET )
{
printf("Enter StandbyMode\r\n");
StandbyMode_Enter();
}
}
}
pwr.h
#ifndef __PWR_H_
#define __PWR_H_
#include "stm32f1xx.h"
#include "stm32_types.h"
#include "stm32f1xx_hal.h"
void LowPWR_Init(void);
//低功耗初始化
void StandbyMode_Enter(void);
//系统进入待机模式
//STM32F1的PA0可用作唤醒引脚WKUO
void StopMode_Enter(void);
//系统进入停止模式
void StopMode_Exit(void);
//系统退出停止模式
void SleepMode_Exit(void);
//退出休眠模式
#endif
pwr.c
#include "pwr.h"
PWR_PVDTypeDef sConfigPVD;
void LowPWR_Init(void)
//低功耗初始化
{
__HAL_RCC_PWR_CLK_ENABLE();
//使能PWR时钟
}
void StandbyMode_Enter(void)
//系统进入待机模式
//STM32F1的PA0可用作唤醒引脚WKUP,上升沿唤醒
//待机唤醒等同于复位操作
{
if( __HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET )
//检查并处理系统是否从待机模式恢复
{
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
//清除标志
}
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
//禁止PA0作为唤醒引脚
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
//清除唤醒标志
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
//使能PA0作为唤醒引脚,PA0的上升沿唤醒
HAL_SuspendTick();
//禁止SysTick中断,防止唤醒系统
HAL_PWR_EnterSTANDBYMode();
//进入待机模式
}
void StopMode_Enter(void)
//系统进入停止模式
{
HAL_SuspendTick();
//禁止SysTick中断
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI);
//进入停止模式,低功耗调压器开启
}
void StopMode_Exit(void)
//退出停止模式
{
__HAL_RCC_HSE_CONFIG(RCC_HSE_ON);
//使能HSE
while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET);
//等待HSE准备就绪
__HAL_RCC_PLL_ENABLE();
//使能PLL
while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
//等待PLL准备就绪
{
}
__HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_PLLCLK);
// 选择PLL作为系统时钟源
while(__HAL_RCC_GET_SYSCLK_SOURCE() != 0x08)
//等待PLL被选择为系统时钟源
{
}
}
void SleepMode_Enter(void)
//系统进入睡眠模式
{
HAL_SuspendTick();
//禁止SysTICK中断,防止唤醒系统
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON,PWR_SLEEPENTRY_WFI);
//进入睡眠模式
}
void SleepMode_Exit(void)
//退出休眠模式
{
HAL_ResumeTick();
//唤醒SYSTICK
//初始化外设
}
void PVD_IRQHandler(void)
//中断服务函数
{
HAL_PWR_PVD_IRQHandler();
}
void HAL_PWR_PVDCallback(void)
//中断回调函数
{
}