鹅卵石m 发表于 2018-7-28 17:53:59

STM32L151 RTC 寄存器无法写入

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

鹅卵石m 发表于 2018-7-28 22:01:04

通过程序设置好RTC寄存器后,在读取RTC_GetWakeUpCounter()函数返回的值,一直显示没有变化,我的理解时RTC没有正常的工作。

x5y4z3 发表于 2018-8-2 09:25:44

进入待机模式后寄存器不让读了?!若不设置待机模式唤醒的这个功能再去读寄存器看看?!
喔!...我是瞎猜的!哈~~

feixiang20 发表于 2018-8-2 22:24:18

通过设置中断口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:唤醒后程序进入闹钟中断函数,然后再进入原来停机的位置继续运行。没有复位,单片机寄存器里的各种变量值仍然保留!!


waiman-156411 发表于 2018-8-4 10:33:58

访问RTC需要打开电源的时钟
还要允许RTC在低功耗状态下访问HAL_PWR_EnableBkUpAccess();

shuihehe 发表于 2018-8-4 11:02:54

鹅卵石m 发表于 2018-7-28 22:01
通过程序设置好RTC寄存器后,在读取RTC_GetWakeUpCounter()函数返回的值,一直显示没有变化,我的理解时R ...

看我的帖子 rtc wakeup 唤醒stop 模式   看看寄存器 有什么不宜一样
页: [1]
查看完整版本: STM32L151 RTC 寄存器无法写入