STM32L151 RTC寄存器不能写入

2019-07-18 17:22发布

使用STM32L151进入待机模式,想利用RTC进行唤醒,根据官方示例编写程序,程序如下
void RTC_Configuration(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_HouRFormat = 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的寄存器输入无法写入。调试情况见 调试截图。各位大神看看,这个到底是程序有问题呢还是什么原因。


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
5条回答
yqyuqy
1楼-- · 2019-07-18 19:23
通过程序设置好RTC寄存器后,在读取RTC_GetWakeUpCounter()函数返回的值,一直显示没有变化,我的理解时RTC没有正常的工作。
shuqingli
2楼-- · 2019-07-18 20:22
进入待机模式后寄存器不让读了?!若不设置待机模式唤醒的这个功能再去读寄存器看看?!
喔!...我是瞎猜的!哈~~
cnm7
3楼-- · 2019-07-19 01:42
通过设置中断口PA1来响应待机和停机模式。

借阅一个例程给你参考

低功耗里主要研究的是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:唤醒后程序进入闹钟中断函数,然后再进入原来停机的位置继续运行。没有复位,单片机寄存器里的各种变量值仍然保留!!
初级少校
4楼-- · 2019-07-19 01:57
 精彩回答 2  元偷偷看……
60user51
5楼-- · 2019-07-19 03:51
yqyuqy 发表于 2019-6-11 12:16
通过程序设置好RTC寄存器后,在读取RTC_GetWakeUpCounter()函数返回的值,一直显示没有变化,我的理解时RTC没有正常的工作。

看我的帖子 rtc wakeup 唤醒stop 模式   看看寄存器 有什么不宜一样

一周热门 更多>