修改主频
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 | /* #define SYSCLK_FREQ_HSE HSE_VALUE */ /* #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 */ |
想要修改主频值,解除注释。默认的主频是72000000(72M)
main.c
1234567891011121314151617181920 | 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 | 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 | 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 | 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();//进入待机模式 } } |
进入待机模式后,闹钟触发一次,程序从头开始执行。