STM32(二十五)——修改主频、睡眠模式、停机模式、待机模式

一、修改主频

MCMSIS 系统时钟配置文件

对外暴露的核心接口
接口 类型 作用
SystemInit() 函数 复位后、进入 main() 前,由启动文件自动调用,完成系统时钟源、PLL 倍频、AHB/APBx 预分频器及 Flash 等待周期的配置
SystemCoreClock 全局变量 保存当前内核时钟(HCLK)频率值,用户可用于配置 SysTick 定时器或其他外设时钟
SystemCoreClockUpdate() 函数 当程序运行中动态修改内核时钟后,必须调用此函数来更新 SystemCoreClock 变量
关键使用提示
  • 调用时机SystemInit()startup_stm32f10x_xx.s 启动文件自动执行,无需用户在 main() 中手动调用
  • 时钟更新 :若在应用程序中动态修改了时钟配置(如切换 PLL 倍频),必须调用 SystemCoreClockUpdate() 来同步变量,否则基于 SystemCoreClock 的延时、定时器配置会出现偏差。
  • 兼容性:该文件是 STM32F1 系列标准 CMSIS 库的一部分,与 Keil MDK、IAR 等开发环境兼容。

更改主频

这个是已经修改过的了,原本是72MHZ,现在修改为36MHZ。

条件编译分支

  • 当芯片为 超值型(VL 系列)STM32F10X_LD_VL / MD_VL / HD_VL
    • 仅可启用 SYSCLK_FREQ_24MHz(24 MHz)、SYSCLK_FREQ_HSE(8MHz)
  • 其他型号(非 VL 系列):
    • 当前启用 SYSCLK_FREQ_36MHz(36 MHz)
    • 24/48/56/72 MHz 选项被注释,处于未启用状态
修改文件属性

如果文件上有个小钥匙的话,可以到文件存储地址中更改文件属性。

可右击文件,点击第五个Open Containing Folder,

右击文件,点击属性

取消只读

二、睡眠模式+串口收发

复制代码
uint8_t RxData;

int main(void)
{
	OLED_Init();
	OLED_ShowString(1, 1, "RxData:");
	
	Serial_Init();
	
	while (1)
	{
		if (Serial_GetRxFlag() == 1)
		{
			RxData = Serial_GetRxData();
			Serial_SendByte(RxData);
			OLED_ShowHexNum(1, 8, RxData, 2);
		}
		OLED_ShowString(2,1,"Running");
		Delay_ms(100);
		OLED_ShowString(2,1,"       ");
		Delay_ms(100);
		
		__WFI();
		
		
	}
	
}

__WFI():让 CPU 进入休眠,直到有中断来才唤醒

__WFE():让 CPU 进入休眠,直到有事件发生才唤醒

代码执行流程

  1. 初始化 OLED、串口
  2. 循环等待串口接收数据
  3. 收到数据后:
    • 回发给电脑(串口回环)
    • 在 OLED 上显示十六进制值
  4. 第二行闪烁显示 Running 表示程序正常运行
  5. 最后用 __WFI() 让单片机休眠等待中断,降低功耗

三、停机模式+对射式红外线传感器计次

复制代码
int main(void)
{
	
	OLED_Init();
	CountSensor_Init();
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	OLED_ShowString(1,1,"Count:");
	
	while(1)
	{
		
		OLED_ShowNum(1,7,CountSensor_Get(),5);
		
		OLED_ShowString(2,1,"Running");
		Delay_ms(100);
		OLED_ShowString(2,1,"       ");
		Delay_ms(100);
		
		PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
		SystemInit();
	}
	
}

一、程序执行流程

  1. 初始化 OLED 显示屏
  2. 初始化计数传感器(配置为外部中断引脚)
  3. 开启 PWR 电源时钟,为进入低功耗模式做准备
  4. 进入主循环,实时显示传感器计数值
  5. 运行状态闪烁提示后,进入 STOP 停止模式深度休眠
  6. 计数传感器触发外部中断,唤醒单片机
  7. 调用 SystemInit () 恢复系统时钟
  8. 回到主循环,继续显示计数并再次休眠

二、核心知识点

1. STOP 停机模式
  • STM32 深度低功耗模式,功耗达到 μA 级
  • 模式特性:所有时钟停止、内核停止运行
  • 数据保存:寄存器、RAM 数据全部保持,计数值不会丢失
  • 唤醒条件:只能由中断 / 事件唤醒
2. 唤醒方式
  • 本程序唤醒源:计数传感器外部中断
  • 通用规则:STOP 停机模式可通过任一外部中断唤醒
3. 唤醒后必须调用 SystemInit ()
  • 进入 STOP 前:系统时钟为配置频率(如 72MHz)
  • 退出 STOP 后:硬件自动将时钟切换为 HSI 8MHz
  • 不执行该函数后果:时钟错乱,延时、OLED、串口等外设工作异常
4. 开启 PWR 电源时钟
  • 必备操作:RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  • 作用:只有开启该时钟,单片机才能进入 STOP 等低功耗模式
5. 进入 STOP 停机模式函数

PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);

  • PWR_Regulator_ON:稳压器保持开启,唤醒速度更快
  • PWR_STOPEntry_WFI:休眠方式为等待中断唤醒

四、待机模式+实时时钟

复制代码
int main(void)
{
	RCC_BackupResetCmd(ENABLE);
	RCC_BackupResetCmd(DISABLE);
	
	
	OLED_Init();
	MyRTC_Init();
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
	OLED_ShowString(1,1,"CNT:");
	OLED_ShowString(2,1,"ALR:");
	OLED_ShowString(3,1,"ALRF:");
	
	PWR_WakeUpPinCmd(ENABLE);
	uint32_t Alarm = RTC_GetCounter() + 10;
	RTC_SetAlarm(Alarm);
	OLED_ShowNum(2,6,Alarm,10);
	
	while(1)
	{
		OLED_ShowNum(1,6,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();
	}
	
}

一、程序执行流程

  1. 备份域复位,初始化 RTC 时钟
  2. 初始化 OLED 显示屏
  3. 开启 PWR 电源时钟
  4. 使能 WKUP 唤醒引脚,设置 10 秒后 RTC 闹钟
  5. 循环显示 RTC 计数值、闹钟值、闹钟标志
  6. 状态提示后,清屏并进入 STANDBY 待机模式
  7. 唤醒源触发(RTC 闹钟 / WKUP 引脚),单片机复位重启
  8. 程序从头开始执行,重新初始化并运行

二、核心知识点

1. STANDBY 待机模式
  • STM32 最低功耗模式,功耗接近 0(nA 级)
  • 模式特性:内核、所有时钟、RAM、寄存器全部断电
  • 数据保存:仅备份域(RTC)保持运行,普通数据全部丢失
  • 唤醒条件:唤醒后相当于系统复位,程序从头执行
2. 唤醒方式
  • 本程序唤醒源:RTC 闹钟中断 + WKUP(PA0)引脚上升沿
  • 通用规则:STANDBY 待机模式只能由指定唤醒源唤醒(WKUP 引脚上升沿、RTC 闹钟、复位等)
3. 唤醒后无需调用 SystemInit ()
  • 进入 STANDBY 后,单片机完全断电复位
  • 唤醒后程序从头运行,启动文件会自动执行 SystemInit ()
  • 无需手动调用时钟初始化函数
4. 开启 PWR 电源时钟
  • 必备操作:RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  • 作用:只有开启该时钟,单片机才能进入 STANDBY 低功耗模式
5. 进入 STANDBY 待机模式函数

PWR_EnterSTANDBYMode();

  • 无参数,直接进入最深低功耗模式
  • 进入后,内核停止,外设断电,仅 RTC 和唤醒电路保持工作

注这里的RTC的晶振使用的外部的LSE,如果不起振,可切换为内部晶振LSI

相关推荐
BackCatK Chen2 小时前
2026年STM32新品密集发布:C5系列量产上市,低功耗无线MCU同步迭代
stm32·单片机·嵌入式硬件·stm32c5·mcu新品·stm32wl3r
沐欣工作室_lvyiyi2 小时前
智能家居环境监测系统的设计与实现(论文+源码)
stm32·毕业设计·智能家居·环境监测
最概然2 小时前
单片机也能玩依赖注入?
单片机·嵌入式硬件
bing_feilong3 小时前
ubuntu22.04: 安装ROS2并测试
嵌入式硬件·机器人
若风的雨3 小时前
【deepseek】Prefetchable的bar是否需要自己处理缓存一致性
嵌入式硬件
学嵌入式的小杨同学4 小时前
STM32 进阶封神之路(十六):PWM 波深度实战 —— 定时器输出 + LED 调光 + 电机调速(库函数 + 寄存器)
stm32·单片机·嵌入式硬件·mcu·硬件架构·硬件工程·智能硬件
世微 如初4 小时前
探秘 AP8660:电流模式升压 DC - DC,高转换与精密基准的完美融合
单片机·芯片·led电源驱动
ShiMetaPi4 小时前
从帧触发到事件驱动:RGB+EVS多模态融合下的无人机识别重构
嵌入式硬件·计算机视觉·嵌入式开发·无人机避障·事件相机
优信电子4 小时前
ESP32开发板单向点对点ESP-NOW无线通信
单片机·嵌入式·arduino