stm32 13 - 2 PWR 电源控制,代码部分 80例题 1 修改主频以及补充81例题 2 睡眠模式串口发送接收#includestm32f10x.h// Device header#includeDelay.h// 调用延时头文件#includeOLED.h#includeSerial.huint8_tRxData;intmain(void){OLED_Init();// 初始化OLED屏幕OLED_ShowString(1,1,RxData:);Serial_Init();while(1){if(Serial_GetRxFlag()1)//if成立就说明收到数据了{RxDataSerial_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(); //事件唤醒配置比较麻烦/*不开启睡眠模式时循环会不断执行开启睡眠模式后循环只在中断唤醒发生后执行*/// 睡眠的执行流程原理 // 任意中断唤醒 cpu 后会接着 __WFI(); 执行。但因为有串口接收中断所以会先响应串口接收中断// 再回到 while 关键字处执行等再次到达 __WFI(); 时 cpu 再次失去时钟而睡眠。}}82例题 3 停止模式对射式红外传感器计次为啥外部中断可以唤醒停机模式其的 cpu 时钟与外设时钟都停止了因为使用 exti 根本不需要时钟。以下是 pwr 的库函数voidPWR_DeInit(void);//恢复缺省配置voidPWR_BackupAccessCmd(FunctionalState NewState);//使能后备区域的访问voidPWR_PVDCmd(FunctionalState NewState);//使能 PVD 功能先指定阈值再使能开启pvd 即可voidPWR_PVDLevelConfig(uint32_tPWR_PVDLevel);//配置 PVD 的阈值电压voidPWR_WakeUpPinCmd(FunctionalState NewState);//使能位于 PA0 位置的 WKUP 引脚配合待机模式使用voidPWR_EnterSTOPMode(uint32_tPWR_Regulator,uint8_tPWR_STOPEntry);//进入停止模式调用这个函数就可以进入停止模式voidPWR_EnterSTANDBYMode(void);//进入待机模式FlagStatusPWR_GetFlagStatus(uint32_tPWR_FLAG);//获取标志位voidPWR_ClearFlag(uint32_tPWR_FLAG);//清除标志位uint8_tKeyNum;intmain(void)// 对射式红外传感器{OLED_Init();// 初始化 OLED 屏幕CountSensor_Init();RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//开启 PWR 的外设时钟控制//如果不开时钟那么写入寄存器是无效的读取寄存器也将都是 0.// 寄存器 PWR_CR PWR_CSR 这俩寄存器如对 1.8V 电源的低功耗配置OLED_ShowString(1,1,Count:);// 在1行3列显示字符串while(1){OLED_ShowNum(1,7,CountSensor_Get(),5);//将中断次数显示到 OLED 屏幕上OLED_ShowString(2,1,Running);Delay_ms(100);OLED_ShowString(2,1, );Delay_ms(100);PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);//第一个参数开启电压调节器在停止模式里的状态WFI 模式进入停止SystemInit();/*我们的程序默认在 SystemInit 函数里的配置是使用的 HSE 外部高速时钟通过PLL倍频得到 72MHz 主频 但是进入停止模式后PLL 和 HSE 都停止了而且在退出停止模式时它并不会再自动帮我们开启 PLL 和 HSE 而是默认用 HSI 的 8MHz直接作为主频所以说如果忽略了这个问题 那么就会出现一个现象程序刚上电是 72MHz 的主频但是进入停止模式再唤醒之后就变成 8MHz 的主频了。 所以我们一般在唤醒后第一时间就是重启 HSE 配置主频为 72MHz这个操作也不麻烦配置函数已经写好了我们只需要再调用 SystemInit 就行。*/}}83例题 4待机模式实时时钟:#includestm32f10x.h// Device header#includeDelay.h// 调用延时头文件#includeOLED.h#includeMyRTC.huint8_tKeyNum;intmain(void)// 本程序有3 步启用 RTC 2 进入待机模式 3 用 RTC 唤醒待机模式{OLED_Init();// 初始化 OLED 屏幕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);// WAKEUP 上升沿唤醒待机PA0 引脚// 这里不用再额外配置 GPIO 引脚了// 本函数对 PWR_CSR- EWUP bit8 的配置就会主动去设置 PA0 位下拉输入了。uint32_tAlarmRTC_GetCounter()10;// 因为闹钟值寄存器 RTC_ALRH、RTC_ALRL 是只写的写进去读不出来所以用一个变量存一下RTC_SetAlarm(Alarm);// 设置闹钟值为当前的 10 秒后本例没有使用闹钟中断 RTCOLED_ShowNum(2,6,Alarm,10);// 显示闹钟值// 停机模式唤醒后要自己再次初始化时钟否则就使用了 HSI// 但待机模式停时钟停电。 RTC 唤醒后代码会彻底从头执行从汇编到 main()所以不用自己初始化时钟了// 所以这里只设置一次 RTC 闹钟就可以实现循环进入待机模式了。while(1)// 在待机模式里是不会进行多次循环的不使用 while 也是可以的{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(100);OLED_ShowString(4,9, );Delay_ms(100);OLED_Clear();//模拟 OLED 进入待机模式// 手动关掉模块一起省电。关掉显示屏电机等需要电路的实现配置PWR_EnterSTANDBYMode();//STM 进入待机模式前应当让其他外设先进入待机模式// 本函数以后的代码是不会再被执行的因为 RTC 闹钟唤醒后项目程序会再次从头开始执行。}}实验结果参考程序的最终版本的实验现象84老师的实验验证85谢谢