使用
STM32L151进入待机模式,想利用RTC进行唤醒,根据官方示例编写程序,程序如下
void RTC_Configura
tion(void)
{
RTC_InitTypeDef RTC_InitStructure;
RTC_TimeTypeDef RTC_TimeStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// RTC_DeInit();
// PWR_DeInit();
// RTC_WakeUpCmd(DISABLE);
/* Enable the PWR clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/* Allow access to RTC */
PWR_RTCAccessCmd(ENABLE);
/* Enable the LSI OSC */
RCC_LSICmd(ENABLE);
/* Wait till LSI is ready */
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
/* Calendar Configuration */
RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
RTC_InitStructure.RTC_SynchPrediv = 0x120; /* (37KHz / 128) - 1 = 0x120*/
RTC_InitStructure.RTC_Hou
RFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
/* EXTI configuration *******************************************************/
EXTI_ClearITPendingBit(EXTI_Line20);
EXTI_InitStructure.EXTI_Line = EXTI_Line20;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable the RTC Wakeup Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Configure the RTC WakeUp Clock source: CK_SPRE (1Hz) */
RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
RTC_SetWakeUpCounter(0x05);
/* Enable the RTC Wakeup Interrupt */
RTC_ITConfig(RTC_IT_WUT, ENABLE);
/* Enable Wakeup Counter */
RTC_WakeUpCmd(ENABLE);
}
发现
单片机进入了待机模式后无法唤醒。刚开始一直以为程序有问题,看了好多相关资料后没有找到问题。采用单步调试发现RTC的寄存器输入无法写入。调试情况见 调试截图。各位大神看看,这个到底是程序有问题呢还是什么原因。
喔!...我是瞎猜的!哈~~
借阅一个例程给你参考
低功耗里主要研究的是STM32的待机模式和停机模式。让单片机进入的待机模式和停机模式比较容易,实验中通过设置中断口PA1来响应待机和停机模式。
void EXTI1_IRQHandler(void)
{
if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1))
{
delay_ms(10);
while(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1));
if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1))
{
EXTI_ClearITPendingBit(EXTI_Line1);
RTC_SetAlarm(RTC_GetCounter()+4); //设置4S后闹钟唤醒
RTC_ITConfig(RTC_IT_ALR, ENABLE);//使能闹钟中断.
RTC_WaitForLastTask();//等待上一次写RTC任务完成
Standby(); //进入待机(停机)状态
}
}
}
void Standby()
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR , ENABLE);//开电源管理时钟PWR_Regulator_LowPower
PWR_WakeUpPinCmd(ENABLE);//使能唤醒引脚,默认PA0
PWR_EnterSTANDBYMode();//进入待机
//PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI|PWR_STOPEntry_WFE);//进入停机
}
进入的待机模式和停机模式很简单,基本一样。那么问题来了。
主要问题有:
1:如何对他们进行唤醒?
2:唤醒的闹钟中断能否执行?
2:唤醒后的程序入口在哪?
通过各种实验和查资料,得到了如下结论:(本实验通过设定RTC_SetAlarm(RTC_GetCounter()+4); 为设置4S后进行闹钟唤醒,并开启闹钟中断,手册中可以查到闹钟中断能产生唤醒,故用闹钟中断进行实验)
先研究待机模式下的唤醒,在闹钟中断函数如下:
void RTCAlarm_IRQHandler(void)
{
if(RTC_GetFlagStatus(RTC_IT_ALR))
{
RTC_ClearITPendingBit(RTC_IT_ALR);
RTC_WaitForLastTask();
EXTI_ClearITPendingBit(EXTI_Line17);
if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
{
PWR_ClearFlag(PWR_FLAG_WU);
}
GPIO_WriteBit(GPIOA, GPIO_Pin_5, 0);//LED指示
}
}
实验结果:PA5的LED不指示,并且从其他LED灯的指示可以知道程序又重新开始运行。也就是被复位。
因此待机模式下的唤醒结论如下:
1:唤醒形式直接产生闹钟中断就能唤醒。
2:唤醒后不会进入闹钟中断函数
3:唤醒后程序复位,重新执行
再研究停机模式下的唤醒,停机模式唤醒和待机唤醒差别很大,开始还以为两者相同,停机唤醒相对复杂些,中途调试了很长时间,才明白了停机唤醒的过程,贴上闹钟中断程序如下:
char Wakeflag=0;
void RTCAlarm_IRQHandler(void)
{
if(RTC_GetFlagStatus(RTC_IT_ALR))
{
EXTI_ClearITPendingBit(EXTI_Line17);
RTC_ClearITPendingBit(RTC_IT_ALR);
RTC_WaitForLastTask();
EXTI_ClearITPendingBit(EXTI_Line7);
EXTI_ClearITPendingBit(EXTI_Line1);//对于程序可能产生的标志位必须的清除干净,不清除会出现唤醒失灵现象!!
if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
{
PWR_ClearFlag(PWR_FLAG_WU);//一般没用
}
SystemInit();//重要,由于停机下对所有时钟关闭,所以唤醒需要重新配置时钟!!
Wakeflag=!Wakeflag;
GPIO_WriteBit(GPIOA, GPIO_Pin_5, Wakeflag);//LED灯指示
}
}
相比待机的闹钟中断是不复杂了很多,停机模式下的唤醒的中断函数需要注意这两点(能得到这两点,耗费了大量时间,终于还是搞定了,嗨皮!!):
1:重要,对于程序可能产生的标志位必须的清除干净,不清除会出现唤醒失灵现象!!
2:重要,由于停机下对所有时钟关闭,所以唤醒需要重新配置时钟!!
实验现象:LED可以产生开通与关断的效果。并且从其他LED的指示可以看到程序没有被复位,而是继续原来运行。
因此停机模式下的唤醒结论如下:
1:唤醒形式产生闹钟中断不一定就唤醒,需要对任何可能的标志位清楚,并且时钟要重新配置。
2:唤醒后进入闹钟中断函数
3:唤醒后程序进入闹钟中断函数,然后再进入原来停机的位置继续运行。没有复位,单片机寄存器里的各种变量值仍然保留!!
看我的帖子 rtc wakeup 唤醒stop 模式 看看寄存器 有什么不宜一样
一周热门 更多>