stm32f103 RTC周期性待机唤醒(一)
来源:互联网 发布:便宜好用的汽车 知乎 编辑:程序博客网 时间:2024/05/01 09:55
做一个低功耗的东西,搞了好几天,程序一直卡在一个地方(见下图),今天终于发现问题出在哪里了,对待机唤醒的问题做一个总结(只针对我遇到的问题,其他部分网上都有,基于stm32f103)
1、解决我遇到的问题
我的RTC初始化部分有个“保存在备份寄存器的RTC标志是否已经被配置过的判断”,如果已经配置过,则进入else部分,但是这个else部分没有“要使能电源时钟,使能备份时钟,取消后备区的写保护”这些配置语句,而待机唤醒后程序从主函数执行,会执行到else部分,因为没有那些配置语句,所以再次对闹钟赋值就会不成功,就会卡在那里。(那些配置语句在clock_ini函数里,有注释)
2、待机用不用加extiline17事件
如果把闹钟中断的服务程序放在void RTC_IRQHandler(void)里面处理的话,不需要extiline17事件也可以唤醒(亲测),如果闹钟中断的服务程序放在void RTCAlarm_IRQHandler(void)里面处理的话,需要extiline17事件
3、RTCAlarm_IRQn和RTC_IRQn优先级
我见到网上说要把RTCAlarm_IRQn的优先级设置比RTC_IRQn优先级高,但是把闹钟中断的服务程序放在void RTC_IRQHandler(void)里面处理的话,不用这样设置也可以。如果闹钟中断的服务程序放在void RTCAlarm_IRQHandler(void)里面处理的话需要设置优先级,最好根据情况先把优先级的问题解决清楚
4、下面是我的一些代码
void Clock_ini(void){ if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) //判断保存在备份寄存器的RTC标志是否已经被配置过 { printf("\r\n\n RTC not yet configured...."); RTC_Configuration();<span style="white-space:pre"></span>//RTC初始化 printf("\r\n RTC configured...."); Time_Adjust();//设置RTC 时钟参数 BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); //RTC设置后,将已配置标志写入备份数据寄存器 } else { if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET) //检查是否掉电重启 { printf("\r\n\n Power On Reset occurred...."); } else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET) //检查是否reset复位 { printf("\r\n\n External Reset occurred...."); } printf("\r\n No need to configure RTC...."); /***新加的,测试,待机唤醒后,程序不经过上面的if部分,所以没有这三步(两个语句),所以程序会卡,所以加上,果然***/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); /* 允许访问BKP区域 */ PWR_BackupAccessCmd(ENABLE);</span> RTC_WaitForSynchro(); //等待RTC寄存器被同步 RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中断 RTC_WaitForLastTask(); RTC_ITConfig(RTC_IT_ALR, ENABLE); //naozhong RTC_WaitForLastTask();<span style="white-space:pre"></span>//等待写入完成 } RCC_ClearFlag();//清除复位标志
void NVIC_Configuration(void){ NVIC_InitTypeDef NVIC_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* Enable the RTC Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;//配置外部中断源(秒中断) NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 7; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable the RTC Alarm Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;//配置外部中断源(闹钟中断) NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //闹钟中断接到第17线外部中断 EXTI_ClearITPendingBit(EXTI_Line17); EXTI_InitStructure.EXTI_Line = EXTI_Line17; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }
void RTC_Configuration(void){ /* 使能 PWR 和 BKP 的时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); /* 允许访问BKP区域 */ PWR_BackupAccessCmd(ENABLE); /* 复位BKP */ BKP_DeInit();#ifdef RTCClockSource_LSI /* 使能内部RTC时钟 */ RCC_LSICmd(ENABLE); /* 等待RTC内部时钟就绪 */ while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) { } /* 选择RTC内部时钟为RTC时钟 */ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); #elif definedRTCClockSource_LSE /* 使能RTC外部时钟 */ RCC_LSEConfig(RCC_LSE_ON); /* 等待RTC外部时钟就绪 */ while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) { } /* 选择RTC外部时钟为RTC时钟 */ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); #endif /* 使能RTC时钟 */ RCC_RTCCLKCmd(ENABLE);#ifdef RTCClockOutput_Enable /* Disable the Tamper Pin */ BKP_TamperPinCmd(DISABLE); /* To output RTCCLK/64 on Tamper pin, the tamper functionality must be disabled */ /* 使能在TAMPER脚输出RTC时钟 */ BKP_RTCCalibrationClockOutputCmd(ENABLE);#endif /* 等待RTC寄存器同步 */ RTC_WaitForSynchro(); /* 等待写RTC寄存器完成 */ RTC_WaitForLastTask(); /* 使能RTC naozhong中断 */ RTC_ITConfig(RTC_IT_ALR, ENABLE); /* 等待写RTC寄存器完成 */ RTC_WaitForLastTask(); /* 使能RTC秒中断 */ RTC_ITConfig(RTC_IT_SEC, ENABLE); /* 等待写RTC寄存器完成 */ RTC_WaitForLastTask(); /* 设置RTC预分频 */#ifdef RTCClockSource_LSI RTC_SetPrescaler(31999); /* RTC period = RTCCLK/RTC_PR = (32.000 KHz)/(31999+1) */#elif definedRTCClockSource_LSE RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */#endif /* 等待写RTC寄存器完成 */ RTC_WaitForLastTask();}
void RTCAlarm_IRQHandler(void){ RTC_WaitForSynchro(); if(RTC_GetITStatus(RTC_IT_ALR) != RESET) { //printf("mmmmmm"); EXTI_ClearITPendingBit(EXTI_Line17); RTC_WaitForLastTask(); if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET) {// 清除唤醒标志 PWR_ClearFlag(PWR_FLAG_WU);RTC_WaitForLastTask(); }RTC_ClearITPendingBit(RTC_IT_ALR);RTC_WaitForLastTask();printf("\nIt will wake up after %d s\n",standbytime);RTC_Enter_StandbyMode(standbytime);//standbytime秒后唤醒 }}
void RTC_Enter_StandbyMode(u32 s){RTC_WaitForLastTask(); RTC_SetAlarm(RTC_GetCounter()+s); RTC_WaitForLastTask(); // 进入待机模式, 此时所有1.8V域的时钟都关闭,HIS和HSE的振荡器关闭, 电压调节器关闭. // 只有WKUP引脚上升沿,RTC警告事件,NRST引脚的外部复位,IWDG复位./* Request to enter STANDBY mode (Wake Up flag is cleared in PWR_EnterSTANDBYMode function) */ PWR_EnterSTANDBYMode();}5、接下来几天我要研究一下停机模式和功耗问题
0 0
- stm32f103 RTC周期性待机唤醒(一)
- stm32f103 RTC周期性待机唤醒(一)
- stm32f103 RTC周期性待机唤醒(一)
- STM32L151C8周期性从待机模式唤醒(RTC Wakeup Timer)
- STM32,RTC周期性唤醒(wakeup)中断
- STM32F030使用RTC周期性唤醒STOP模式
- stm32f103 rtc日历
- STM32F103 SDIO(一)
- STM32之待机唤醒
- STM32 待机唤醒
- 11、待机唤醒实验
- Android待机唤醒机制
- STM32-待机唤醒实验
- 待机唤醒(亮屏灭屏)
- STM32之待机唤醒
- 待机和唤醒
- STM32F103(四) IIC实践--PFC8563 RTC 时钟调试成功
- 项目周期性总结(一)
- leetcode_065 Valid Number
- SVM-4-核函数
- windows SDK程序的模板
- 使用JsonP进行跨域请求
- Swap Nodes in Pairs
- stm32f103 RTC周期性待机唤醒(一)
- HDU 5646 DZY Loves Partition (数学)
- Oracle数据仓库创建教程
- 1000搬桌子问题 ACID 00729209
- C#拼音联想式选择
- 目标跟踪:背景建模重要博文
- opencv全屏显示
- Python 数学运算
- 汇编语言基础总结(一)