13-2修改主频&睡眠模式&停止模式&待机模式

修改主频

system_stm32f10x.c

1234567891011121314151617181920212223242526272829
1.  This file provides two functions and one global variable to be called from   *     user application:  *      - SystemInit(): Setups the system clock (System clock source, PLL Multiplier  *                      factors, AHB/APBx prescalers and Flash settings).   *                      This function is called at startup just after reset and   *                      before branch to main program. This call is made inside  *                      the "startup_stm32f10x_xx.s" file.  *  *      - SystemCoreClock variable: Contains the core clock (HCLK), it can be used  *                                  by the user application to setup the SysTick   *                                  timer or configure other parameters.  *                                       *      - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must  *                                 be called whenever the core clock is changed  *                                 during program execution.  *  * 2. After each device reset the HSI (8 MHz) is used as system clock source.  *    Then SystemInit() function is called, in "startup_stm32f10x_xx.s" file, to  *    configure the system clock before to branch to main program.  *  * 3. If the system clock source selected by user fails to startup, the SystemInit()  *    function will do nothing and HSI still used as system clock source. User can   *    add some code to deal with this issue inside the SetSysClock() function.  *  * 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depedning on  *    the product used), refer to "HSE_VALUE" define in "stm32f10x.h" file.   *    When HSE is used as system clock source, directly or through PLL, and you  *    are using different crystal you have to adapt the HSE value to your own  *    configuration.

SystemInit()这个函数用来配置时钟树,在main函数之前自动调用

SystemCoreClock表示主频频率的值,显示此变量,可以知道目前主频的值。

SystemCoreClockUpdate()更新SystemCoreClock,因为这个变量只要最开始的一次赋值,改变主频频率,该值不会跟着改变。

1234567891011
#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

想要修改主频值,解除注释。默认的主频是72000000(72M)

main.c

1234567891011121314151617181920
#include "stm32f10x.h"                  // Device header#include "Delay.h"#include "OLED.h" int main(void){	OLED_Init();	OLED_ShowString(1,1,"SYSCLK:");	OLED_ShowNum(1,8,SystemCoreClock,8);//显示当前的主频值,可以在system_stm32f10x.c中修改 	while(1)	{		//在默认的72M主频下,Running每500ms显示一次,修改主频,显示时间会变化,因为主频改变了。比如主频改成36M,Runing每1S显示一次。如果想要修改主频之后,Running仍500ms显示一次,需要修改Delay函数。可见不能随意修改主频。		OLED_ShowString(2,1,"Running");		Delay_ms(500);		OLED_ShowString(2,1,"         ");		Delay_ms(500);	}} 

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

因为主循环一直在运行,空闲时运行没有意义,还费电。
因此靠中断触发,没有中断就没作用的程序,可以加入低功耗模式。

由于程序需要使用串口USART硬件电路接收数据,只能使用睡眠模式,不能使用停止模式或待机模式,因为停止模式和待机模式下CPU和外设都不能运行,无法正常接收串口数据。

1234567891011121314151617181920212223242526272829
#include "stm32f10x.h"                  // Device header#include "Delay.h"#include "OLED.h"#include "Serial.h"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();//中断唤醒 		//__WFE();//事件唤醒	}}

通过串口给单片机发送数据,每发送一次数据,进入中断,单片机会被唤醒,Running闪烁一次。

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

对射式红外传感器计次使用外部中断触发唤醒,可以进入更省电的停止模式。
在停止模式下,1.8V区域时钟关闭,CPU和外设都没有时钟,但是外部中断的工作不需要时钟。

常用函数

1
void PWR_DeInit(void);

恢复PWR缺省配置

1
void PWR_BackupAccessCmd(FunctionalState NewState);

使能后备区域访问

1
void PWR_PVDCmd(FunctionalState NewState);

使能PVD功能

1
void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel);

配置PVD的阈值电压

1
void PWR_WakeUpPinCmd(FunctionalState NewState);

使能位于PA0位置的WKUP引脚,配合待机模式使用

1
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry);

进入停止模式

1
void PWR_EnterSTANDBYMode(void);

进入待机模式

1
FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG);

获取标志位

1
void PWR_ClearFlag(uint32_t PWR_FLAG);

清除标志位

main.c

1234567891011121314151617181920212223242526272829
#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);//开启PWR外设的时钟 	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();//配置时钟	}} 

待机模式 + 实时时钟

main.c

1234567891011121314151617181920212223242526272829303132333435363738
#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时钟  	OLED_ShowString(1,1,"CNT:");	OLED_ShowString(2,1,"ALR:");	OLED_ShowString(3,1,"ALRF:"); 	PWR_WakeUpPinCmd(ENABLE);//WKUP引脚唤醒 	uint32_t Alarm = RTC_GetCounter() + 10;	RTC_SetAlarm(RTC_GetCounter() + 10);	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); 		PWR_EnterSTANDBYMode();//进入待机模式	} } 

进入待机模式后,闹钟触发一次,程序从头开始执行。

🔍 ×