STM32 拓展 低功耗案例3:待机模式 (register)

发布于:2025-02-11 ⋅ 阅读:(93) ⋅ 点赞:(0)

需求描述

寄存器操作进入待机模式。待机模式的唤醒方式比较有限。我们这次使用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();
}


网站公告

今日签到

点亮在社区的每一天
去签到