rockt-210467 发表于 2017-9-14 14:42:15

stm32f072 通过RTC闹钟唤醒STOP睡眠模式问题

我通过设置RTC时钟定时每一分钟唤醒MCU一次进行一些查询检测工作。但会偶尔发现无法唤醒MCU,感觉RTC无法产生中断,应该是RTC的问题,现在就是不知道是硬件引起的还是软件引起的。因为有的机子从来没有问题,有的偶尔会有,但不是每次都出现,有的用了很久也没有出现过。很困扰。以下是RTC的处理代码,有哪位大侠搞过RTC闹钟唤醒睡眠的,帮看看有没有问题。

/******************************************************************************
**函数名: Init_RTC
**入      口:
**返      回:
**功          能: RTC配置初始化
*******************************************************************************/
void Init_RTC(void)
{
        RTC_Config();
        GetRTCTime();
        Set_RTC_Alarm_Minute();        //设置闹钟时间

}




/******************************************************************************
**函数名:RTC_Config
**入      口:
**返      回:
**功          能: RTC配置,24小时的时间格式
*******************************************************************************/
void RTC_Config(void)
{
        RTC_InitTypeDef RTC_InitStructure;
       
        RCC_APB1PeriphClockCmd( RCC_APB1Periph_PWR, ENABLE );   /* Enable the PWR clock */
        PWR_BackupAccessCmd( ENABLE );                            /* Allow access to RTC */

        if( RTC_ReadBackupRegister( RTC_BKP_DR0 ) != RTC_BKP_VALUE )//如果掉电了,则重新初始化时间
            {
                  RCC_LSEConfig( RCC_LSE_ON);    /* Enable the LSE OSC */
                  while( RCC_GetFlagStatus( RCC_FLAG_LSERDY ) == RESET );   /* Wait till LSE is ready */
          
                  RCC_RTCCLKConfig( RCC_RTCCLKSource_LSE );   /* Select the RTC Clock Source */
          
                  RCC_RTCCLKCmd( ENABLE );      /* Enable the RTC Clock */
                  RTC_WaitForSynchro();         /* Wait for RTC APB registers synchronisation */

                  //设置RTC时钟分频,1秒
                  RTC_InitStructure.RTC_AsynchPrediv = 127;
                  RTC_InitStructure.RTC_SynchPrediv = 255;//255
                  RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24; //24小时的时间格式
                    if( RTC_Init( &RTC_InitStructure ) == ERROR )
                      {
                      /* 此处作设置失败处理 */   
                      }

                    //设置默认的时间:2017-1-1- 12:30:00
                    SetCalendarTime( DEFAULT_HOUR, DEFAULT_MIN, DEFAULT_SEC);        //时间
                    SetCalendarDate(3,DEFAULT_YEAR,DEFAULT_MON,DEFAULT_DAY);                //日期

                    bPowerDown = TRUE;//系统掉电,又重新上电
                    bSynchronizeTime = TRUE;
           
            }
        else
            {
                    RTC_WaitForSynchro();                   /* Wait for RTC APB registers synchronisation */
                    RTC_ClearFlag( RTC_FLAG_ALRAF );      /* Clear the RTC Alarm Flag */
            }
}


/******************************************************************************
**函数名:Set_RTC_Alarm_Minute
**入           口:
**返           回:
**功           能: 设置RTC报警时间,单位为分钟
*******************************************************************************/
void Set_RTC_Alarm_Minute(void)
{
        RTC_AlarmTypeDef RTC_AlarmStructure;
        unsigned char hour = 0;
        unsigned char min = 0;
//        unsigned char sec = 0;

        //GetRTCTime();                //获取系统时间
       
        hour = RTC_Time;
        min = RTC_Time;

        min += 1;
       
        if(min >= 60)
        {
                min = 0;
                hour += 1;
                if(hour >= 24) hour = 0;
        }

        RTC_ITConfig( RTC_IT_ALRA, DISABLE );    /* Enable the RTC Alarm A Interrupt */       
        RTC_AlarmCmd( RTC_Alarm_A, DISABLE );   /* Disable the Alarm A */

        RTC_AlarmStructure.RTC_AlarmTime.RTC_H12 = RTC_H12_AM;
        RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours = hour;
        RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = min;
        RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = 0;

/* Set the Alarm A */
        RTC_AlarmStructure.RTC_AlarmDateWeekDay = 31;
        RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
        RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;

        RTC_SetAlarm( RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure ); /* Configure the RTC Alarm A register */

        RTC_ITConfig( RTC_IT_ALRA, ENABLE );    /* Enable the RTC Alarm A Interrupt */

        RTC_AlarmCmd( RTC_Alarm_A, ENABLE );    /* Enable the alarmA */

       
}


/******************************************************************************
**函数名:GetRTCTime
**入           口:
**返           回:
**功           能: 读取RTC时间
*******************************************************************************/
void GetRTCTime(void)
{
        unsigned char Getweek = 0;

        GetCalendarTime(&RTC_Time,&RTC_Time,&RTC_Time);
        GetCalendarDate(&Getweek,&RTC_Time,&RTC_Time,&RTC_Time);

}


/******************************************************************************
**函数名:RTC_IRQHandler
**入      口:
**返      回:
**功          能: 日历报警中断
*******************************************************************************/
void RTC_IRQHandler( void )
{
        if( RTC_GetITStatus( RTC_IT_ALRA ) != RESET )
            {
                   
                if((gStatus != G_POWER_OFF)&&(gStatus != G_MODE_CHARGE))
                {
                        GprsConnectInTime++;
                }
                else
                {
                        GprsConnectInTime = 0;
                }

                bOneMinuteFlg = TRUE;//一分钟时间到
                bBatTest1Min = TRUE; //一分钟测量一次电量
                                                       
                RTC_ClearITPendingBit( RTC_IT_ALRA );
            }
           
            EXTI_ClearITPendingBit(EXTI_Line17);
           
}


                      }
            }
}

/******************************************************************************
**函 数 名:
**入      口:
**返      回:
**功      能:
*******************************************************************************/
void NVIC_Configuration(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
        EXTI_InitTypeDef EXTI_InitStructure;
       
        //RTC时钟中断
        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);

        NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        RTC_ClearITPendingBit( RTC_IT_ALRA );
        EXTI_ClearITPendingBit(EXTI_Line17);
}

/******************************************************************************
**函数名:main
**入      口:
**返      回:
**功          能: 系统主程序
*******************************************************************************/
int main(void)
{        
      .............
        Init_RTC();                        //日历时间初始化
       ................
      NVIC_Configuration();        //系统中断配置初始化
       
        while(1)
        {
            //每分钟检测一次
           if(bOneMinuteFlg == TRUE)
          {
                bOneMinuteFlg = FALSE;
                GetRTCTime();                        //获取系统时间
                Set_RTC_Alarm_Minute();        //设置闹钟中断时间

          }
          ..........................
          SleepMode();
          ............................
       
}


MrJiu 发表于 2017-9-14 14:52:42

哇,这种少量事件很难处理。。。有的行,有的不行。。。不能唤醒只的是,会漏掉一分钟?还是说一睡不醒?

rockt-210467 发表于 2017-9-14 15:06:04

睡不醒了一样,通过按键中断唤醒后,又正常了

kylongmu 发表于 2017-9-14 15:17:10

你的RTC时钟是外部还是内部?外部的话,Crystal的质量是否可靠,负载电容是否合适?

rockt-210467 发表于 2017-9-14 15:26:18

使用的外部晶振32.768K。我要先确认如果软件没有问题再去排查硬件问题

发表于 2017-9-14 16:32:15

RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;这个把秒也加上
另外,如果是一分钟唤醒一次,不如使用RTC WakeUp,这个简单方便。

发表于 2017-9-14 16:33:00

1分钟唤醒一次,这样只开分就可以了。把日、小时、秒都关了。

rockt-210467 发表于 2017-9-14 18:01:54

如果不关会有问题吗

发表于 2017-9-15 08:36:46

如果不关,他是要等到时分秒都匹配了才会唤醒。下面是我使用时分唤醒的配置:
RTC_AlarmStructure.RTC_AlarmMask             = RTC_AlarmMask_Seconds | RTC_AlarmMask_DateWeekDay;

rockt-210467 发表于 2017-9-15 09:03:32

安 发表于 2017-9-15 08:36
如果不关,他是要等到时分秒都匹配了才会唤醒。下面是我使用时分唤醒的配置:
RTC_AlarmStructure.RTC_Ala ...

hour = RTC_Time;
      min = RTC_Time;

      min += 1;
      
      if(min >= 60)
      {
                min = 0;
                hour += 1;
                if(hour >= 24) hour = 0;
      }

          RTC_ITConfig( RTC_IT_ALRA, DISABLE );    /* Enable the RTC Alarm A Interrupt */      
          RTC_AlarmCmd( RTC_Alarm_A, DISABLE );   /* Disable the Alarm A */

          RTC_AlarmStructure.RTC_AlarmTime.RTC_H12 = RTC_H12_AM;
          RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours = hour;
          RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = min;
          RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = 0;

你说的这个我也会试试。不过以上我是根据每次当前时间设置下一次闹钟时间的,就是下一次分钟闹钟,我觉得这个也没有什么问题。
页: [1] 2
查看完整版本: stm32f072 通过RTC闹钟唤醒STOP睡眠模式问题