整理:MilerShao 有人使用STM32F072芯片開發(fā)電子產(chǎn)品,產(chǎn)品需要用到STOP休眠模式,希望用RTC的周期性自動喚醒功能來喚醒芯片。他發(fā)現(xiàn)芯片進入STOP后根本無法通過RTC定時喚醒MCU。查看ST的官方相關(guān)估計庫,似乎并沒有關(guān)于RTC 定時喚醒的參考項目。 我大致找了下,ST官方好像是沒有現(xiàn)存的關(guān)于32F0芯片 RTC定時喚醒的例程。這里一起交流下RTC 定時喚醒話題。 其實,實現(xiàn)這個RTC 定時喚醒還是比較簡單的。這里有個可編程的可自動重裝的向下計數(shù)器,按照相應的時鐘頻率賦予適當?shù)闹担慨斚蛳掠嫈?shù)到0時便產(chǎn)生一個喚醒標志,如果此時使能了相應的定時喚醒中斷,它就可以把MCU從低功耗模式喚醒。需做如下四項基本的準備工作。 1、確定RTC時鐘,即RTCCLK.可以是LSE、LSI、HSE/32其中一個。下面的例程中選用LSI. 2、為自動喚醒定時計數(shù)器選擇合適的時鐘源。可以是RTCCLK的2,4,8,16分頻后的某一個,或者使用RTCCLK經(jīng)過預分頻后的秒時鐘CK_SPRE。下面例程中選用RTCCLK/16作為喚醒計時器【RTC_WUTR】的時鐘源。 
3、結(jié)合上面選定的喚醒定時器的時鐘和需要STOP休眠的時間,計算出將賦給喚醒定時器【RTC_WUTR】的重載值。比方這里以LSI/16作為定時器的計數(shù)時鐘,假設定時1S,LSI的頻率按40K算的話,那40k/16=2500,16進制即0x9c4. 那如果定時1S的話,賦值應該就是0X9C4.【LSI有波動,定時可能誤差】 4、做好RTC周期性定時喚醒的中斷配置,即NVIC配置。RTC喚醒事件是連接到EXTI 20號線。 
下面是我做測試RTC 定時喚醒功能的一個簡單例程,需要時可以參考。其中主程序MAIN()內(nèi)容比較簡單,無限循環(huán)里的內(nèi)容就是LED燈先滅,進入STOP模式,1S左右后被RTC 喚醒定時器喚醒,喚醒后LED亮一會,然后再進入下一輪循環(huán)。
/*************************************************************/ int main(void) { GPIO_Config(); GPIO_SetBits(GPIOA, GPIO_Pin_5); RTC_Config(); /* RTC Configuration */ WKUP_NVIC_Config(); /* EXTI LINE 20 CONFIG */ while(1) { GPIO_ResetBits(GPIOA, GPIO_Pin_5); PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); GPIO_SetBits(GPIOA, GPIO_Pin_5); /* LED1 On after wake up by RTC*/ Delay(); //LED ON for a while } } /*************************************************************/ static void RTC_Config(void) { /* Enable the PWR clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* Allow access to RTC */ PWR_BackupAccessCmd(ENABLE); RCC_LSICmd( ENABLE); //啟動LSI
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) { } /* Wait till LSi is ready */ /* Select the RTC Clock Source */ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//選擇LSI作為RTC時鐘源 /* Enable the RTC Clock */ RCC_RTCCLKCmd(ENABLE);//啟動RTC RTC_WakeUpCmd(DISABLE); //關(guān)閉RTC 喚醒定時器!!! RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);//喚醒定時器時鐘 RTC_SetWakeUpCounter( 0x9c4); //給RTC WAKE UP TIMER賦重裝值 RTC_WakeUpCmd( ENABLE); //啟動RTC 喚醒定時器
} /********RTC wake up interrupt NVIC ********/ void WKUP_NVIC_Config(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
/* Configure EXTI line 20 (connected to the RTC wakeup event) */ 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); /* NVIC configuration */ NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
/* Enable peirodic wakeup interrupt */ RTC_ITConfig(RTC_IT_WUT, ENABLE); // /* Clear the wakeup Pending Bit */ RTC_ClearITPendingBit(RTC_IT_WUT); } /****** RTC periodic wake up interrupt service routine*******/ void RTC_IRQHandler(void) { if (RTC_GetITStatus(RTC_IT_WUT) != RESET) { /* Clear RTC wake up interrupt pending bit */ RTC_ClearITPendingBit(RTC_IT_WUT); /* Clear EXTI line20 pending bit */ EXTI_ClearITPendingBit(EXTI_Line20); } } 這里要提醒下,上面測試代碼中的RTC_Config()配置函數(shù)里的紅色語句代碼經(jīng)常有人漏掉,這2行對于操作RTC后備域寄存器時是必需的。 另外,RTC_WakeUpCmd(DISABLE); 這句也是必須的,否則就沒法對喚醒定時器進行時鐘配置和喚醒定時器賦值。 |