STM32的RTC闹钟中断 总算整明白了

2019-07-21 07:11发布

现在用到了STM32的闹钟中断 去唤醒停机模式下的系统
看STM32的demo 里边写的明明白白的 到我的例程上就是不行

后来总结出来了 呵呵 STM32的Demo只是用到了闹钟中断函数RTCAlarm_IRQHandler() 并没有用到RTC全局中断RTC_IRQHandler()    好 那么我的问题就出在这里了

如果两个中断函数同时使用的话,我们必须这样设置才不会有漏洞  RTCAlarm_IRQHandler() 函数的优先级一定要高于RTC_IRQHandler()  

为什么?

原因如下:
1,产生闹钟中断的前一瞬间,一定产生了秒中断,那么会先执行RTC_IRQHandler() 中断函数, 在RTC_IRQHandler() 执行的过程中,闹钟中断标志又被挂起,

由于RTC_IRQHandler()是全局中断函数,必须清除所有的中断标志,程序才能退出该函数, 假如RTC_IRQHandler()  和RTCAlarm_IRQHandler() 是同样的优先级,

要想让程序退出RTC_IRQHandler() 函数,那么你必须清除闹钟中断标志(如果不清除闹钟中断标志,程序会死在RTC_IRQHandler() ), 这样问题又出现了,清除闹钟中断标志后,程序就不会进入RTCAlarm_IRQHandler(),那么RTCAlarm_IRQHandler()函数永远也不会被执行。

我们只有这样做
设置闹钟中断函数RTCAlarm_IRQHandler() 的优先级高于全局中断函数RTC_IRQHandler(),
 在执行全局中断函数RTC_IRQHandler() 的时候,如果产生闹钟中断,那么中断嵌套去执行RTCAlarm_IRQHandler(),执行完毕RTCAlarm_IRQHandler()后,再去执行RTC_IRQHandler() 。

代码如下:

static void RTC_NVIC_Config(void)
{ /*尼玛  闹钟中断的优先级必须必秒中断高
 闹钟中断和秒中断几乎同时到来 秒中断的处理函数 是RTC_IRQHandler()
 如果进入这个函数 那么要想从RTC_IRQHandler()退出  则必须清除所有中断标志
    (包括闹钟中断), 这样 闹钟中断标志被清除 则RTCAlarm_IRQHandler()函数肯定是进不去了
 如果不清楚闹钟中断标志 那么程序会死在RTC_IRQHandler()里边
 综上所述 那种中断必须能打断秒中断的执行 这样程序才能执行到RTCAlarm_IRQHandler()里边
   */
    NVIC_InitTypeDef NVIC_InitStructure;
 NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;  //RTC全局中断
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; 
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //使能该通道中断
 NVIC_Init(&NVIC_InitStructure);    NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;  //闹钟中断
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //比RTC全局中断的优先级高
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; 
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
 NVIC_Init(&NVIC_InitStructure);
}
static void RTC_Alarm_EXIT(void)
{
 EXTI_InitTypeDef EXTI_InitStructure;
 EXTI_ClearITPendingBit(EXTI_Line17);
 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Line = EXTI_Line17;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
 EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure); }


void RTC_IRQHandler(void)
{
     if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
    {
    }
    RTC_ClearITPendingBit(RTC_IT_SEC);
  RTC_WaitForLastTask();

}

void RTCAlarm_IRQHandler(void)
{     if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
      {

      }
     EXTI_ClearITPendingBit(EXTI_Line17);
  RTC_WaitForLastTask();
  RTC_ClearITPendingBit(RTC_IT_ALR);
  RTC_WaitForLastTask();
 }

按照我理解的,就应该是这样,我也实际测试了,结果和预期的一样,呵呵 如果有不对的地方,欢迎拍砖。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
41条回答
wwjdwy
2019-07-21 16:56
回复【楼主位】langwanglx:
---------------------------------
我这两天也遇到一个问题,先设置RTC基本配置,然后开启秒中断,之后开启闹钟中断,在设置闹钟值时候:
    RTC_ClearFlag(RTC_FLAG_SEC);
    while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);
    RTC_SetAlarm(RTC_GetCounter() + 5);
    RTC_WaitForLastTask();

最后一句程序就跑死了: RTC_WaitForLastTask();,
单独跑秒中断日历都是正常的,晶振也起振OK的。楼主有啥指导意见不?

一周热门 更多>