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

相关推荐
bubiyoushang8883 小时前
STM32F103C8T6+DM9051以太网功能实现方案
stm32·单片机·嵌入式硬件
IT_阿水4 小时前
基于STM32河流水质检测
stm32·单片机·嵌入式硬件
黑白园4 小时前
STM32定时器中断
stm32·单片机·嵌入式硬件
weixin_456808385 小时前
【沁恒蓝牙开发】ADC DMA定时采样、转化
单片机·嵌入式硬件
华普微HOPERF6 小时前
MCU+BLE射频+丰富外设,BLE SoC如何高效传输数据?
单片机·嵌入式硬件
振南的单片机世界6 小时前
时钟开关:不用的外设,把它的时钟关掉,省电!
stm32·单片机·嵌入式硬件
金色光环6 小时前
SCPI添加错误码
stm32·scpi
iCxhust7 小时前
将8088 BootLoader分拆烧写到8086 ROM中
stm32·单片机·嵌入式硬件·51单片机·微机原理
国科安芯7 小时前
商业航天电机控制领域抗辐射 MCU 芯片应用研究
网络·单片机·嵌入式硬件·安全性测试
charlie1145141918 小时前
嵌入式C++工程实践第20篇:GPIO 输入模式内部电路 —— 芯片是如何“听“到外部信号的
开发语言·c++·stm32·单片机