STM32待机模式学习笔记

STM32待机模式学习笔记
     STM32内置低功耗模式,在系统或电源复位之后,微控制器处于运行状态,当CPU不需要继续运行时,可以利用多种低功耗模式来节省功耗。例如,等待某个外部事件,用户需要更具最低电源功耗,最快速启动时间和可用的唤醒源等条件,选定一个最佳的低功耗模式。

STM32F10xxx有三种低功耗模式:
    ●睡眠模式(Cortex™-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时 钟(SysTick)等仍在运行) 。
    ●停止模式(所有的时钟都已停止)
    ●待机模式(1.8V电源关闭) 
此外,在运行模式下,可以通过以下方式中的一种降低功耗:
    ●降低系统时钟
    ●关闭APB和AHB总线上未被使用的外设时钟。
表 1:低功耗模式一览表
STM32待机模式学习笔记_第1张图片
三种模式中,最低功耗的就是待机模式,在此模式下,最低只需要2uA左右的电流,其次是停机模式,大概需要20uA左右的电流,最后就是睡眠模式了,
STM32 的最低功耗模式-待机模式
    待机模式可实现系统的最低功耗。该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个  1.8V供电区域被断电。PLL、HSI和HSE振荡器也被断电。SRAM和寄存器内容丢失。只有备份 的寄存器和待机电路维持供电。
进入待机模式:
关于如何进入待机模式,详见表2: STM32待机模式学习笔记_第2张图片
表2:待机模式
可以通过设置独立的控制位,选择以下待机模式的功能:
● 独立看门狗(IWDG):可通过写入看门狗的键寄存器或硬件选择来启动IWDG。一旦启动了
独立看门狗,除了系统复位,它不能再被停止。 (可参考看门狗章节笔记)
● 实时时钟(RTC):通过备用区域控制寄存器(RCC_BDCR)的RTCEN位来设置。
● 内部RC振荡器(LSI RC):通过控制/状态寄存器(RCC_CSR)的LSION位来设置。
● 外部32.768kHz振荡器(LSE):通过备用区域控制寄存器(RCC_BDCR)的LSEON位设置。
退出待机模式
    从待机模式退出的方式共有4种:外部复位(NRST引脚)、IWDG复位、WKUP引脚上的上升沿或者RTC闹钟事件的上升沿发 生。
    从待机唤醒后,除了电源控制/状 态寄存器(PWR_CSR),所有寄存器被复位。
    从待机模式唤醒后的代码执行等同于复位后的执行(采样启动模式引脚、读取复位向量等)。电源 控制/状态寄存器(PWR_CSR)将会指示内核由待机状态退出。
    根据表2可以知道,配置过程中需要两个寄存器,即电源控制寄存器(PWR_CR)和电源控制/状态寄存器(PWR_CSR)。
    下表是对这两个寄存器简介:
电源控制寄存器(PWR_CR) :
地址偏移:0x00
复位值:0x0000 0000 (从待机模式唤醒时清除)
STM32待机模式学习笔记_第3张图片
STM32待机模式学习笔记_第4张图片

通过设置PWR_CR的PDDS位,使CPU进入深睡眠时进入待机模式,CWUF位是清除唤醒位。
电源控制/状态寄存器(PWR_CSR) :
地址偏移:0x04  
复位值:0x0000 0000 (从待机模式唤醒时不被清除) 
与标准的APB读相比,读此寄存器需要额外的APB周期
STM32待机模式学习笔记_第5张图片
STM32待机模式学习笔记_第6张图片
通过设置 PWR_CSR的 EWUP位,设置为WKUP引脚用于唤醒,可用从WUF位来检测是否被唤醒

/*******进入待机模式,以及wkup唤醒设置步骤**************
1.使能电源时钟
2.设置 WK_UP 引脚作为唤醒源
3.设置 SLEEPDEEP 位,设置 PDDS 位,执行 WFI 指令,进入待机模式
4.最后编写 WK_UP 中断函数
********************************************************/

/**
  ******************************************************************************
  * @file    wkup.c
  * @author  zhangkeyan
  * @version V1.0
  * @date    2014-09-03
  * @brief   待机唤醒 驱动代码		
  ******************************************************************************
  * @attention
  * 
  ******************************************************************************
  */
#include "wkup.h"
#include "led.h"
#include "delay.h"
/*******进入待机模式,以及wkup唤醒设置步骤**************
1.使能电源时钟
2.设置 WK_UP 引脚作为唤醒源
3.设置 SLEEPDEEP 位,设置 PDDS 位,执行 WFI 指令,进入待机模式
4.最后编写 WK_UP 中断函数
********************************************************/
void SYS_StandBy(void)
{
  NVIC_SystemLPConfig(NVIC_LP_SLEEPDEEP,ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE); //使能PWR和BKP外设时钟 
  PWR_WakeUpPinCmd(ENABLE);  //使能唤醒管脚功能

  PWR_EnterSTANDBYMode();  //进入待命(STANDBY)模式 
}
//系统进入待机模式
void SYS_Enter_StandBy(void)
{			 
	RCC_APB2PeriphResetCmd(0X01FC,DISABLE);
	SYS_StandBy();
}
//检测WKUP脚的信号
//返回值1:连续按下3s以上
//      0:错误的触发
u8 Check_WKUP(void)
{
  u8 counter = 0;
  u8 counter_num = 0;  //记录松开的次数

  LED0 = 0;  //点亮 DS0
  while(1)
  {
   if(WKUP_KD)
   {
      counter ++;
      counter_num = 0;
   }
   else
   {
      counter_num ++;  //超过300ms内没有WKUP信号
      if(counter_num > 3)
      {
        LED0 = 1;
        return 0;
      }
   }
   delay_ms(30);
   if(counter >100)  //3s之后WKUP_KD信号一直存在
   {
      LED0 = 0;
      return 1;
   }
  }
}

//中断,检测到PA0脚的一个上升沿.	  
//中断线0线上的中断检测
void EXTI0_IRQHandler(void)
{ 		    		    				     		    
	EXTI->PR=1<<0;  //清除LINE10上的中断标志位		  
	if(Check_WKUP())//关机?
	{		  
		SYS_Enter_StandBy();  
	}
} 
/********PA0 WKUP唤醒初始化**********/
void WKUP_Init(void)
{	
  GPIO_InitTypeDef  GPIO_InitStructure;  		  
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPD;//上拉输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);
        //使用外部中断方式
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
        EXTI_InitStructure.EXTI_Line = EXTI_Line0;	         //设置按键所有的外部线路
 	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;      //设外外部中断模式:EXTI线路为中断请求
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
 	EXTI_Init(&EXTI_InitStructure);	

	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;           //使能按键所在的外部中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //先占优先级2级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;         //从优先级2级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //使能外部中断通道
	NVIC_Init(&NVIC_InitStructure);                            //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	if(Check_WKUP()==0) SYS_StandBy();    //不是开机,进入待机模式  
}


/**
  ******************************************************************************
  * @file    wkup.h
  * @author  zhangkeyan
  * @version V1.0
  * @date    2014-09-03
  * @brief   待机唤醒 驱动代码		
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */
#ifndef __WKUP_H
#define __WKUP_H	 
#include "sys.h"
					    
#define WKUP_KD PAin(0)           //PA0 检测是否外部WK_UP按键按下
	 
u8    Check_WKUP(void);            //检测WKUP脚的信号
void  WKUP_Init(void);             //PA0 WKUP唤醒初始化
void  SYS_Enter_StandBy(void);     //系统进入待机模式

#endif

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "rtc.h"
#include "wkup.h"
       
const u8 *COMPILED_DATE=__DATE__; 
const u8 *COMPILED_TIME=__TIME__; 
/*************主函数*************/
int main(void)
{
  delay_init(72);          	  
  NVIC_Configuration();   
  uart_init(9600);
  LED_Init();              //LED初始化
  LCD_Init();
  RTC_Init();
  WKUP_Init();
  POINT_COLOR = RED;        //设置字体颜色为红色
  LCD_ShowString(60,130," WKUP TEST");
  LCD_ShowString(60,150,"zhangkeyan");
  LCD_ShowString(60,170,"2014-9-5"); 
  
  while(1)
  {
    LED0 = !LED0;
    delay_ms(250);
  }
}






















    

你可能感兴趣的:(STM32)