STM32 拓展 低功耗案例3:待机模式 (register)
需求描述
寄存器操作进入待机模式。待机模式的唤醒方式比较有限。我们这次使用WKUP引脚的上升沿唤醒。PA0就是WKUP引脚。
当然PA0仍然需要工作在下拉输入模式,只有这样当按键按下的时候才会有一个上升沿。
由于我们电路中PA0已经连接了LED1,所以要产生上升沿需要先用杜邦线连接GND(拉低),然后再连接3.3V电源即可(拉高)。
另外也可以使用NRST引脚实现唤醒。
思路
首先用杜邦线连接GND和PA0,然后设置PA0 位下拉输入模式,继续设置stm32进入待机模式,最后用杜邦线连接3V3和PA0,产生上升沿,进行唤醒。
相关寄存器
PA0需要开启唤醒功能
PDDS位配置
SLEEPDEEP位配置
main.c
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
void enter_standby_mode(void);
int main(void)
{
// 初始化
USART_Init();
LED_Init();
KEY_Init();
printf("尚硅谷低功率实验:待机模式...\n");
// 1. 开启LED灯,延时2s,模拟正常程序执行过程
LED_On(LED_2);
Delay_s(2);
while (1)
{
// 2. 进入待机模式
printf("正常代码执行完毕,3s后进入待机模式...\n");
Delay_s(3);
printf("进入待机模式,请接线唤醒...\n");
Delay_ms(1); // 引入延时,确保发送信息成功
enter_standby_mode();
// 4. 以下代码不会执行
printf("从待机模式中唤醒...\n");
Delay_s(2);
}
}
// 定义进入睡眠模式的函数
void enter_standby_mode(void)
{
// 1. 设置深睡眠模式
SCB->SCR |= SCB_SCR_SLEEPDEEP;
// 2. 开启PWR模块时钟
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
// 3. 配置PDDS = 1,表示待机模式
PWR->CR |= PWR_CR_PDDS;
// 4. 使能 PA0 的唤醒功能
PWR->CSR |= PWR_CSR_EWUP;
// 5. 使用WFI指令,进入待机模式
__WFI();
}
问题1:运行完之后会发现,不断的唤醒。
查看寄存器发现,唤醒标志位没有清0操作。重点时WUF唤醒标志位。
添加代码:
// 开启PWR模块时钟
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
// 判断是否有标志位,如果有就直接清除
if (PWR->CSR & PWR_CSR_SBF)
{
printf("从待机模式唤醒!\n");
PWR->CR |= PWR_CR_CSBF;
}
if (PWR->CSR & PWR_CSR_WUF)
{
printf("发生了唤醒事件!\n");
PWR->CR |= PWR_CR_CWUF;
}
main.c(完整版)
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
void enter_standby_mode(void);
int main(void)
{
// 初始化
USART_Init();
LED_Init();
KEY_Init();
// 开启PWR模块时钟
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
// 判断是否有标志位,如果有就直接清除
if (PWR->CSR & PWR_CSR_SBF)
{
printf("从待机模式唤醒!\n");
PWR->CR |= PWR_CR_CSBF;
}
if (PWR->CSR & PWR_CSR_WUF)
{
printf("发生了唤醒事件!\n");
PWR->CR |= PWR_CR_CWUF;
}
printf("尚硅谷低功率实验:待机模式...\n");
// 1. 开启LED灯,延时2s,模拟正常程序执行过程
LED_On(LED_2);
Delay_s(2);
while (1)
{
// 2. 进入待机模式
printf("正常代码执行完毕,3s后进入待机模式...\n");
Delay_s(3);
printf("进入待机模式,请接线唤醒...\n");
Delay_ms(1); // 引入延时,确保发送信息成功
enter_standby_mode();
// 4. 以下代码不会执行
printf("从待机模式中唤醒...\n");
Delay_s(2);
}
}
// 定义进入待机模式的函数
void enter_standby_mode(void)
{
// 1. 设置深睡眠模式
SCB->SCR |= SCB_SCR_SLEEPDEEP;
// 3. 配置PDDS = 1,表示待机模式
PWR->CR |= PWR_CR_PDDS;
// 4. 使能 PA0 的唤醒功能
PWR->CSR |= PWR_CSR_EWUP;
// 5. 使用WFI指令,进入待机模式
__WFI();
}