您的位置:首页 > 其它

STM32待机模式学习笔记

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

STM32F10xxx有三种低功耗模式:
●睡眠模式(Cortex™-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时 钟(SysTick)等仍在运行)

●停止模式(所有的时钟都已停止)
●待机模式(1.8V电源关闭)
此外,在运行模式下,可以通过以下方式中的一种降低功耗:
●降低系统时钟
●关闭APB和AHB总线上未被使用的外设时钟。

表 1:低功耗模式一览表





三种模式中,最低功耗的就是待机模式,在此模式下,最低只需要2uA左右的电流,其次是停机模式,大概需要20uA左右的电流,最后就是睡眠模式了,
STM32 的最低功耗模式-待机模式
待机模式可实现系统的最低功耗。该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个 1.8V供电区域被断电。PLL、HSI和HSE振荡器也被断电。SRAM和寄存器内容丢失。只有备份的寄存器和待机电路维持供电。
进入待机模式:
关于如何进入待机模式,详见表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 (从待机模式唤醒时清除)







通过设置PWR_CR的PDDS位,使CPU进入深睡眠时进入待机模式,CWUF位是清除唤醒位。
电源控制/状态寄存器(PWR_CSR) :
地址偏移:0x04
复位值:0x0000 0000 (从待机模式唤醒时不被清除)
与标准的APB读相比,读此寄存器需要额外的APB周期





通过设置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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: