目录
待机唤醒
STM32的3种低功耗模式:
相关寄存器讲解
相关库函数介绍
待机唤醒配置步骤:
实验源码:
很多单片机有低功耗模式,STM32也不例外。在系统或者电源复位后,微控制器出于运行状态之下, HCLK为CPU提供时钟,内核执行代码。当CPU不需要继续运行时,可以利用多种低功耗模式来节省功耗,例如等待某个事件触发。
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.0GPIO_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
#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 ****/