修改主频&睡眠模式&停机模式&待机模式

低功耗模式

  1. PWR(Power Contro)电源控制简介

①PWR负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能.
②可编程电压监测器(PVD)可以监控VDD电源电压,当VDD下降到PVD阀值以下或上升到PVD阀值之上时,PVD会触发中断,用于执行紧急关闭任务.
③低功耗模式包括睡眠模式(Sleep)、停机模式(Stop)和待机模式(Standby),可在系统空闲时,降低STM32的功耗,延长设备使用时间.

  1. 低功耗模式
    在这里插入图片描述

  2. 模式选择
    在这里插入图片描述

三大模式

  1. 睡眠模式
    ①执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行.
    ②SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠.
    ③在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态.
    ④WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒.
    ⑤WFE指令进入睡眠模式,可被唤醒事件唤醒.

  2. 停止模式
    ①执行完WFI/WFE指令后,STM32进入停止模式,程序暂停运行,唤醒后程序从暂停的地方继续运行.
    1.8V供电区域的所有时钟都被停止,PLL(锁相环,用作倍频)、HSI和HSE被禁止,SRAM和寄存器内容被保留下来.
    ③在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态.
    当一个中断或唤醒事件导致退出停止模式时,HSI(8MHZ)被选为系统时钟.
    ⑤当电压调节器处于低功耗模式下,系统从停止模式退出时,会有一段额外的启动延时.
    ⑥WFI指令进入停止模式,可被任意一个EXTI中断唤醒.
    ⑦WFE指令进入停止模式,可被任意一个EXTI事件唤醒.

  3. 待机模式
    ①执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行.
    整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电.
    ③在待机模式下,所有的I/O引脚变为高阻态(浮空输入).
    WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位退出待机模式.

  4. 三大模式对比图
    在这里插入图片描述

修改主频&睡眠模式&停机模式&待机模式

修改主频

  • 接线图如下:
    在这里插入图片描述
  • 直接修改主频以测试,不用创建新的文件
    main.c代码:
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	
	OLED_ShowString(1,1,"SYSCLK:");
	OLED_ShowNum(1,8,SystemCoreClock,8);
	
	
	while (1)
	{
		OLED_ShowString(2,1,"RUNNING");
		Delay_ms(500);
		OLED_ShowString(2,1,"       ");
		Delay_ms(500);
	}
}

①在代码OLED_ShowNum(1,8,SystemCoreClock,8);的SystemCoreClock用来读取系统主频率.
②在系统文件system_stm32f10x.c中修改如下部分的代码:

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
 #define SYSCLK_FREQ_24MHz  24000000
#else
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz  24000000 */ 
/* #define SYSCLK_FREQ_36MHz  36000000 */
/* #define SYSCLK_FREQ_48MHz  48000000 */
/* #define SYSCLK_FREQ_56MHz  56000000 */
#define SYSCLK_FREQ_72MHz  72000000
#endif

从上述代码可以看出来#define SYSCLK_FREQ_72MHz 72000000系统默认为72MHZ的主频,将其注释掉,将#define SYSCLK_FREQ_36MHz 36000000解除注释(改为如下代码所示),则系统的主频变为36MHZ.

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
 #define SYSCLK_FREQ_24MHz  24000000
#else
/* #define SYSCLK_FREQ_HSE    HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz  24000000 */ 
#define SYSCLK_FREQ_36MHz  36000000
/* #define SYSCLK_FREQ_48MHz  48000000 */
/* #define SYSCLK_FREQ_56MHz  56000000 */
/* #define SYSCLK_FREQ_72MHz  72000000 */
#endif

睡眠模式+串口发送+接收

  • 接线图如下:
    在这里插入图片描述
  • 直接在主函数中测试
    main.c代码:
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"

uint8_t RxData;

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	Serial_Init();

	
	while (1)
	{
		//判断是否出现了USART_FLAG_RXNE,即该取数据了
		//不用清除标志位,下一次读数据时自动清除标志位
		if(Serial_GetRxFlag() == 1)
		{
			RxData = Serial_GetRxData();
			Serial_SendByte(RxData);
			OLED_ShowHexNum(1,1,RxData,2);
		}
		
		OLED_ShowString(2,1,"RUNNING");
		Delay_ms(100);
		OLED_ShowString(2,1,"       ");
		Delay_ms(100);
		
		//睡眠模式(中断事件唤醒)
		__WFI();	
	}
}

①在睡眠模式中,不用开启PWR的电源控制,直接在程序(一般是死循环里)最后一行调用__WFI();函数,可以直接使程序进入睡眠模式.OLED屏幕上的RUNNING不在闪烁直到串口接收新的数据会闪烁一下,之后再次进入睡眠模式.
睡眠模式中,使用__WFI()函数时,任意中断就可以将设备唤醒.
③设备在执行 __WFI()指令进入睡眠模式后,一旦被唤醒,程序会紧接着从 __WFI()指令之后的下一条代码继续执行,在此代码中也就是回到主循环开头继续向下执行.

  • 代码执行流程图:

停止模式+对射式红外传感器计次

  • 接线图如下:
    在这里插入图片描述
  • 直接在主函数中测试
    main.c代码:
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"

int main(void)
{
	OLED_Init();
	CountSensor_Init();
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	
	OLED_ShowString(1,1,"Count:");
	OLED_ShowString(2,1,"Level:");
		
	while(1)
	{
		OLED_ShowNum(1,7,Count(),5);
		OLED_ShowNum(2,7,GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14),1);
		
		OLED_ShowString(3,1,"RUNNING");
		Delay_ms(100);
		OLED_ShowString(3,1,"       ");
		Delay_ms(100);
		
		PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);
		SystemInit();
	}
}

①在停止模式中,需要对PWR函数(电源控制函数)的操作,首先要初始化电源控制函数 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);,电源控制时APB1总线上的设备.
②之后在函数末尾(本代码是循环末尾)加上PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);表示进入停止模式,其参数详解如下图:
在这里插入图片描述
③使用SystemInit();使得函数在被唤醒后从初始化函数开始执行,这样做的目的是使唤醒后的设备使用72MHZ的频率,而不是使用HSI的8MHZ作为时钟主频率,从而保证了OLED上的RUNNING闪烁频率在停机前后的闪烁频率不变.

  • 代码运行流程:

待机模式+实时时钟

  • 接线图如下:
    在这里插入图片描述
  • 直接在主函数中测试
    main.c代码:
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"


int main(void)
{
	OLED_Init();
	MyRTC_Init();
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	
	PWR_WakeUpPinCmd(ENABLE);

	OLED_ShowString(1,1,"CNT:");
	OLED_ShowString(2,1,"ALAR:");
	OLED_ShowString(3,1,"ALRF:");
	
	uint32_t Alarm = RTC_GetCounter() + 10;
	RTC_SetAlarm(Alarm);
	
	OLED_ShowNum(2,6,Alarm,10);

	while (1)
	{
		MYRTC_ReadTime();
		
		OLED_ShowNum(1,5,RTC_GetCounter(),10);
		OLED_ShowNum(3,6,RTC_GetFlagStatus(RTC_FLAG_ALR),1);
		
		OLED_ShowString(4,1,"RUNNING");
		Delay_ms(100);
		OLED_ShowString(4,1,"       ");
		Delay_ms(100);
		
		OLED_ShowString(4,9,"STANDBY");
		Delay_ms(1000);
		OLED_ShowString(4,9,"       ");
		Delay_ms(100);
		
		OLED_Clear();
		
		PWR_EnterSTANDBYMode();
	}
}

①在待机模式下,先要使能PWR(电源控制):RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);,
②在函数需要待机的地方(此代码是死循环末尾)加上PWR_EnterSTANDBYMode();表示进入待机模式,此函数没有形参.
从待机模式唤醒相当于一次硬件复位。程序不会从 PWR_EnterSTANDBYMode()后面继续执行,而是从 main函数的第一行代码重新开始执行。这就是为什么唤醒后所有硬件都需要重新初始化。

  • 代码执行流程:
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

必胜的思想钢印

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值