目录
待机唤醒
STM32的3种低功耗模式:
相关寄存器讲解
相关库函数介绍
待机唤醒配置步骤:
实验源码:
待机唤醒
很多单片机有低功耗模式,STM32也不例外。在系统或者电源复位后,微控制器出于运行状态之下, HCLK为CPU提供时钟,内核执行代码。当CPU不需要继续运行时,可以利用多种低功耗模式来节省功耗,例如等待某个事件触发。
STM32的3种低功耗模式:
1.睡眠模式:内核停止,外设如NVIC,系统时钟Systick仍运行。
2.停止模式:所有时钟都已停止。1.8V内核电源工作。PLL,HIS和HSE RC振荡器功能禁止。寄存器和SRAM内容保留。
3.待机模式: 1.8V内核电源关闭。只有备份寄存器和待机电路维持供电。寄存器和SRAM内容全部丢失。实现最低功耗。
在运行模式下,可以通过下面方式降低功耗:
1.降低系统时钟。2.关闭APB和AHB总线上未被使用的外设时钟、
待机模式下的输入/输出端口状态
在待机模式下,所有的I/O引脚处于高阻态,除了以下引脚:
1.复位引脚(始终有效)
2.当被设置为防侵入或校准输出时的TAMPER引脚
3.被使能的唤醒引脚
待机模式理想状态下,只需要2uA电流。停机模式下典型电流为20uA。
相关寄存器讲解
PWR_CR电源控制寄存器
1.设置PDDS位进入深度睡眠时进入待机模式。
2.设置CWUF位,清除之前的WUF唤醒位。
PWR_CSR电源控制/状态寄存器
1.设置EWUP,使能WKUP引脚用于待机模式唤醒。
2.WUF唤醒标志,用来判断是否发生唤醒事件。
相关库函数介绍
void PWR_EnterSTOPMode();//进入停机模式
void PWR_EnterSTANDBYMode(void);//进入待机模式
void PWR_WakeUpPinCmd(FunctionalState NewState);//使能Wakeup引脚唤醒
FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG);
void PWR_ClearFlag(uint32_t PWR_FLAG);
待机唤醒配置步骤:
1.使能电源时钟。
因为要配置电源控制寄存器,所以必须先使能电源时钟。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
2.设置WK_UP引脚作为唤醒源。
设置PWR_CSR的EWUP位,使能WK_UP用于将CPU从待机模式唤醒。
PWR_WakeUpPinCmd(ENABLE); //使能唤醒管脚功能
3.设置SLEEPDEEP位,设置PDDS位,执行WFI指令,进入待机模式。
void PWR_EnterSTANDBYMode(void);
实验源码:
1.首次下载程序进去会执行Gpio,Rcc初始化程序,当进入Wkup_Init初始化时配置了外部中断最后判断如果按键没有按下3秒执行待机模式。(注意待机模式中断不会关)
2.此时在按下唤醒按键CPU是马上重新从main函数开始跑的,初始化到Wkup_Init按下3s就不会进入待机状态,程序正常跑,否则继续待机。
3.正常模式下,按下按键会进入中断里面按下3s会执行待机(注意正常跑的时候是配好了外部中断的所以进入待机的时候按下CUP又会执行2步骤)
/**
******************************************************************************
* @file : user_rcc_config.c
* @brief : V1.00
******************************************************************************
* @attention
*
******************************************************************************
*/
/* Include 包含---------------------------------------------------------------*/
#include "user_rcc_config.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define 定义----------------------------------------------------------------*/
/* Macro 宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/
/* Constants 常量--------------------------------------------------------------*/
/* Function 函数--------------------------------------------------------------*/
/*!
\brief RCC配置
\param[in] none
\param[out] none
\retval none
*/
void Rcc_config(void)
{
/*使能UART1时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
/*使能GPIOA*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
/*复用功能时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
}
/************************************************************** END OF FILE ****/
/**
******************************************************************************
* @file : user_gpio.c
* @brief : V1.00
******************************************************************************
* @attention
*
******************************************************************************
*/
/* Include 包含---------------------------------------------------------------*/
#include "user_gpio.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define 定义----------------------------------------------------------------*/
/* Macro 宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/
/* Constants 常量--------------------------------------------------------------*/
/* Function 函数--------------------------------------------------------------*/
/*!
\brief GPIO初始化函数
\param[in] none
\param[out] none
\retval none
*/
void Gpio_Init(void)
{
/*GPIO结构体*/
GPIO_InitTypeDef GPIO_InitTypeDefstruct;
/*UART1发送引脚配置*/
GPIO_InitTypeDefstruct.GPIO_Mode = GPIO_Mode_AF_PP;//推挽复用输出
GPIO_InitTypeDefstruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitTypeDefstruct.GPIO_Speed = GPIO_Speed_10MHz;
/*写入结构体到GPIOA*/
GPIO_Init(GPIOA,&GPIO_InitTypeDefstruct);
/*UART1接收引脚配置*/
GPIO_InitTypeDefstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitTypeDefstruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitTypeDefstruct.GPIO_Speed = GPIO_Speed_10MHz;
/*写入结构体到GPIOA*/
GPIO_Init(GPIOA,&GPIO_InitTypeDefstruct);
/*唤醒引脚初始化*/
GPIO_InitTypeDefstruct.GPIO_Pin =GPIO_Pin_0; //PA.0
GPIO_InitTypeDefstruct.GPIO_Mode =GPIO_Mode_IPD;//上拉输入
GPIO_InitTypeDefstruct.GPIO_Speed = GPIO_Speed_10MHz;
/*写入结构体到GPIOA*/
GPIO_Init(GPIOA, &GPIO_InitTypeDefstruct);
}
/************************************************************** END OF FILE ****/
/**
******************************************************************************
* @file : user_pwr.c
* @brief : V1.00
******************************************************************************
* @attention
*
******************************************************************************
*/
/* Include 包含---------------------------------------------------------------*/
#include "user_pwr.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define 定义----------------------------------------------------------------*/
/* Macro 宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/
/* Constants 常量--------------------------------------------------------------*/
/* Function 函数--------------------------------------------------------------*/
/*!
\brief 待机函数
\param[in] none
\param[out] none
\retval none
*/
void Sys_Standby(void)
{
/*使能PWR外设时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/*使能唤醒管脚功能*/
PWR_WakeUpPinCmd(ENABLE);
/*进入待机(STANDBY)模式*/
PWR_EnterSTANDBYMode();
}
/*!
\brief 进入待机函数
\param[in] none
\param[out] none
\retval none
*/
void Sys_Enter_Standby(void)
{
/*复位所有IO*/
RCC_APB2PeriphResetCmd(0X01FC,DISABLE);
/*正式进入待机模式*/
Sys_Standby();
}
/*!
\brief 判断是否是3秒
\param[in] none
\param[out] none
\retval 1表示按下3秒,0表示不足3秒
*/
uint8_t Check_Wkup(void)
{
/*记录时间*/
u8 t=0;
while(1)
{
if(PAin(0)) //按键检测
{
t++; //已经按下了
delay_ms(30);
if(t>=100) //按下超过3秒钟
{
return 1; //按下3s以上了
}
}else
{
return 0; //按下不足3秒
}
}
}
/*!
\brief 唤醒初始化
\param[in] none
\param[out] none
\retval none
*/
void Wkup_Init(void)
{
/*中断控制器结构体*/
NVIC_InitTypeDef NVIC_InitStructure;
/*外部中断线结构体*/
EXTI_InitTypeDef EXTI_InitStructure;
/*选择GPIOA.0为外部中断源*/
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);
if(Check_Wkup() == 0)
{
/*待机模式*/
Sys_Standby();
}
}
/*!
\brief EXTI0_IRQHandler
\param[in] none
\param[out] none
\retval none
*/
void EXTI0_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line0); // 清除LINE10上的中断标志位
if(Check_Wkup())
{
Sys_Enter_Standby();
}
}
/************************************************************** END OF FILE ****/
/**
******************************************************************************
* @file : user_uart.c
* @brief : V1.00
******************************************************************************
* @attention
*
******************************************************************************
*/
/* Include 包含---------------------------------------------------------------*/
#include "user_uart.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define 定义----------------------------------------------------------------*/
/* Macro 宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/
extern uint16_t USART_RX_STA;
extern uint8_t USART_RX_BUF[200];
/* Constants 常量--------------------------------------------------------------*/
/* Function 函数--------------------------------------------------------------*/
#if 1
#pragma import(__use_no_semihosting)
/*实现Printf代码*/
struct __FILE
{
int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
#endif
/*!
\brief UART1初始化
\param[in] none
\param[out] none
\retval none
*/
void Uart1_Init(u32 bound)
{
/*UART结构体*/
USART_InitTypeDef USART_InitTypeDefstruct;
/*UART结构体配置*/
USART_InitTypeDefstruct.USART_BaudRate = bound; //波特率
USART_InitTypeDefstruct.USART_HardwareFlowControl =USART_HardwareFlowControl_None; //不使用硬件流
USART_InitTypeDefstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//发送接收使能
USART_InitTypeDefstruct.USART_Parity = USART_Parity_No; //不使用奇偶校验
USART_InitTypeDefstruct.USART_StopBits = USART_StopBits_1; //1个停止位
USART_InitTypeDefstruct.USART_WordLength = USART_WordLength_8b; //8个数据位
/*写入USART1*/
USART_Init(USART1,&USART_InitTypeDefstruct);
/*使能串口1*/
USART_Cmd(USART1,ENABLE);
}
/*!
\brief UART1中断服务函数
\param[in] none
\param[out] none
\retval none
*/
void USART1_IRQHandler(void)
{
}
/************************************************************** END OF FILE ****/
/**
******************************************************************************
* @file : user_mian.h
* @brief : V1.00
******************************************************************************
* @attention
*
******************************************************************************
*/
/* Include 包含---------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdbool.h>
#include "user_gpio.h"
#include "user_delay.h"
#include "user_rcc_config.h"
#include "user_uart.h"
#include "user_pwr.h"
/* Typedef 类型----------------------------------------------------------------*/
/* Define 定义----------------------------------------------------------------*/
/* Macro 宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/
//最多一次接收200个字节
uint8_t USART_RX_BUF[200];
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
uint16_t USART_RX_STA=0; //接收状态标记
/* Constants 常量--------------------------------------------------------------*/
/* Function 函数--------------------------------------------------------------*/
int main(void)
{
/*配置系统中断分组为2位抢占2位响应*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*延时函数初始化*/
delay_init();
/*RCC配置*/
Rcc_config();
/*GPIO初始化*/
Gpio_Init();
/*初始化Wkup*/
Wkup_Init();
/*USART1初始化*/
Uart1_Init(9600);
/*死循环*/
while(1){
printf("正常运行\r\n");
}
}
/************************************************************** END OF FILE ****/