跳转到主要内容

MM32F013x——RTC闹钟定时唤醒

demi 提交于

RTC可用于周期性从低功耗模式下唤醒MCU,RTC可选三个时钟源:

<ul><li>低功耗 32.768kHz 外部低速晶振 (LSE):该时钟源提供了一个低功耗且精确的时间基准。</li>

<li>低功耗内部低速振荡器 (LSI):使用该时钟源,节省了一个 32.768kHz 晶振的成本,但是精度没有外部晶振的精度高。</li>

<li>外部高速晶振(HSE)128分频:在某些低功耗模式中HSE被关闭会导致RTC无时钟源。</li></ul>

为了用 RTC 闹钟事件将系统从停机模式下唤醒,必须进行如下操作:

<ul><li>配置外部中断线 17 为上升沿触发。</li>

<li>配置 RTC 使其可产生 RTC 闹钟事件。</li></ul>

如果要从待机模式中唤醒, 不必配置外部中断线 17。

MM32F013x有三种低功耗模式:睡眠模式(Sleep Mode)、停机模式(Stop Mode)和待机模式(Standby Mode),三种低功耗模式的对比如下表所示:

<center><img width="600" src="http://mcu.eetrend.com/files/2021-03/wen_zhang_/100062491-124368-145.pn…; alt="MM32F013x的三种低功耗模式"></center><br>

从上表中可以看出,当MCU工作在停机模式时,可以通过任一外部中断事件来唤醒。MM32F013x低功耗模式下的功耗列表如下图所示:

<center><img width="600" src="http://mcu.eetrend.com/files/2021-03/wen_zhang_/100062491-124369-146.pn…; alt="MM32F013x低功耗模式下的功耗列表"></center><br>

MM32F013x有22个外部中断源,其中EXTI 17对应的是RTC闹钟事件,所以结合RTC闹钟的功能,本文将重点介绍如何在MM32F013x上通过内部RTC模块的闹钟事件来唤醒处于停机模式下的MCU。

<font color="blue"><strong>01、实现功能</strong></font>

通过内部RTC模块的闹钟事件(对应的是外部中断EXTI 17)来唤醒处于停机模式下的MCU。系统在进入停机模式时拉高GPIO端口,在恢复到正常运行状态时拉低GPIO端口。

<font color="blue"><strong>02、配置顺序</strong></font>

1)使能PWR和BKP时钟:

<pre style="overflow-x:auto; background-color:#e9e9e9;">RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);</pre>

2)使能后备寄存器访问:

<pre style="overflow-x:auto; background-color:#e9e9e9;">PWR_BackupAccessCmd(ENABLE);</pre>

3)配置RTC时钟源,使能RTC时钟,如果使用LSE,要打开LSE:

<pre style="overflow-x:auto; background-color:#e9e9e9;">RCC_LSEConfig(RCC_LSE_ON);
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);</pre>

4)设置RTC预分频系数:

<pre style="overflow-x:auto; background-color:#e9e9e9;">RTC_SetPrescaler();</pre>

5)开启相关中断:

<pre style="overflow-x:auto; background-color:#e9e9e9;">RTC_ITConfig(RTC_IT_ALR, ENABLE);</pre>

6)配置外部中断线:

<pre style="overflow-x:auto; background-color:#e9e9e9;">EXTI_StructInit(&EXTI_InitStructure);
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);</pre>

7)配置中断服务函数:

<pre style="overflow-x:auto; background-color:#e9e9e9;">NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);</pre>

8)部分操作要等待写操作完成和同步。

<font color="blue"><strong>03、参考代码</strong></font>

3.1 RTC初始化配置:使用外部32.768kHz的晶振源

<pre style="overflow-x:auto; background-color:#e9e9e9;">void RTC_Configure(void)
{
uint16_t BKP_Value = 0x5A5A;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

/* Enable PWR Clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

/* Enable Access To The RTC & Backup Registers */
PWR_BackupAccessCmd(ENABLE);

if(BKP_ReadBackupRegister(BKP_DR1) != BKP_Value)
{
BKP_DeInit();

/* Enable LSE Clock Source */
RCC_LSEConfig(RCC_LSE_ON);

/* Wait LSI Clock Source Ready */
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

/* Config RTC Clock Source : LSE */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

/* Enable RTC Clock */
RCC_RTCCLKCmd(ENABLE);

/* Wait For Synchronization */
RTC_WaitForSynchro();
/* Wait Until Last Write Operation On RTC REG Has Finished */
RTC_WaitForLastTask();

/* Set The RTC Prescaler Value */
RTC_SetPrescaler(32767);
/* Wait Until Last Write Operation On RTC REG Has Finished */
RTC_WaitForLastTask();
/* Enable RTC Alarm Interrupt */
RTC_ITConfig(RTC_IT_ALR, ENABLE);
/* Wait Until Last Write Operation On RTC REG Has Finished */
RTC_WaitForLastTask();
/* Exit From The RTC Configuration Mode */
RTC_ExitConfigMode();
BKP_WriteBackupRegister(BKP_DR1, BKP_Value);
/* Wait Until Last Write Operation On RTC REG Has Finished */
RTC_WaitForLastTask();
}
else
{
/* Wait For Synchronization */
RTC_WaitForSynchro();
/* Enable RTC Alarm Interrupt */
RTC_ITConfig(RTC_IT_ALR, ENABLE);
/* Wait Until Last Write Operation On RTC REG Has Finished */
RTC_WaitForLastTask();
}
/* Clear EXTI Line17 Flag */
EXTI_ClearITPendingBit(EXTI_Line17);

/* Configure EXTI Line17(RTC Alarm) To Generate An Interrupt On Rising Edge */
EXTI_StructInit(&EXTI_InitStructure);
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);

/* Config RTC NVIC */
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}</pre>

3.2 RTC闹钟中断函数

<pre style="overflow-x:auto; background-color:#e9e9e9;">void RTC_BKP_IRQHandler(void)
{
if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
{
GPIO_WriteBit(LED_GPIO, LED_PIN, Bit_RESET);

/* Clear EXTI Line17 Flag */
EXTI_ClearITPendingBit(EXTI_Line17);

/* Check If The Wake-Up Flag Is Set */
if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
{
/* Clear Wake Up Flag */
PWR_ClearFlag(PWR_FLAG_WU);
}
/* Clear Alarm Flag */
RTC_ClearITPendingBit(RTC_IT_ALR);

/* Wait Until Last Write Operation On RTC REG Has Finished */
RTC_WaitForLastTask();
}
}</pre>

3.3 设置RTC闹钟时间,系统进入STOP模式

<pre style="overflow-x:auto; background-color:#e9e9e9;">void RTC_EntryStopMode(void)
{
/* Wait till RTC Second event occurs */
RTC_ClearFlag(RTC_FLAG_SEC);
while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);

/* Set The RTC Alarm Value */
RTC_SetAlarm(RTC_GetCounter() + 3);

/* Wait Until Last Write Operation On RTC REG Has Finished */
RTC_WaitForLastTask();

GPIO_WriteBit(LED_GPIO, LED_PIN, Bit_SET);

/* Enter Stop Mode */
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
}</pre>

<font color="blue"><strong>04、运行结果</strong></font>

编译软件工程无误后下载代码,调用RTC_EntryStopMode()函数使系统进入到停机模式,等待RTC闹钟事件3S后唤醒停机模式下的MCU,唤醒后继续执行程序,通过观察GPIO的电平状态来查看运行结果:

<center><img width="600" src="http://mcu.eetrend.com/files/2021-03/wen_zhang_/100062491-124372-147.pn…; alt=""></center><br>

用户可以结合上一篇万年历功能设置在某年某月某时某刻定时唤醒MCU功能,万年历的具体实方式可以参考上一篇<a href="http://mcu.eetrend.com/content/2021/100061944.html"><u></u&gt;《MM32F013x——万年历》</a>。

转自:<a href="https://mp.weixin.qq.com/s/ZFWgRrxEXF44Pxec2xTEaw"><u>灵动微电子</u></a&gt;