CH32的RTC闹钟中断

工程中经常用到了STM32的闹钟中断,去唤醒停机或者待机模式下的系统,但是RTC闹钟中断与RTC秒中断一样,是RTC外设的中断,看唤醒条件:

 都是外部事件,所以是需要开启EXTI映射功能,停止模式用事件中断都可以唤醒,而待机只能用事件唤醒。

一、配置

1.停止模式下配置。

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//开启PWR时钟

if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET)//判断是不是wake up复位
{
printf("\r\n Standby wake up reset \r\n");
}
else
{
printf("\r\n Power on reset \r\n");
PWR_WakeUpPinCmd(ENABLE);//使能wake up引脚唤醒
 PWR_EnterSTOPMode_RAM_LV(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);;//进入停止模式,第二个参数与外部中断唤醒与事件唤醒相匹配。

}

EXTI配置:

/* GPIOA ----> EXTI_Line0 */

EXTI_InitStructure.EXTI_Line = EXTI_Line17;//此处为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);

//EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;上述是这个事件,下面的中断函数与中断配置皆可不要。

NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;//开启闹钟外部中断,其实是EXTI17 RTC
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

//编写中断函数

void RTCAlarm_IRQHandler(void)

{

...

}

2.待机模式下配置:

//由于待机模式唤醒后会复位,不执行中断函数,中断配置都不需要,待机模式配置比较简单

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

if(PWR_GetFlagStatus(PWR_FLAG_WU) == SET)
{
printf("\r\n Standby wake up reset \r\n");
}
else
{
printf("\r\n Power on reset \r\n");
PWR_WakeUpPinCmd(ENABLE);
PWR_EnterSTANDBYMode();
}

EXTI_InitStructure.EXTI_Line = EXTI_Line17;//此处为EXTI_Line17
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;此处只能为事件
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

二、与RTC中断的共同处理

 CH32的中断函数RTCAlarm_IRQHandler() 唤醒,并没有用到RTC全局中断RTC_IRQHandler() 

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

原因如下:
产生闹钟中断的前一瞬间,一定产生了秒中断,那么会先执行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() 。

posted @ 2024-07-01 11:51  WCH_CH32  阅读(87)  评论(0编辑  收藏  举报