整理:MilerShao
有人使用STM32F072芯片開發(fā)電子產(chǎn)品,產(chǎn)品需要用到STOP休眠模式,希望用RTC的周期性自動(dòng)喚醒功能來(lái)喚醒芯片。他發(fā)現(xiàn)芯片進(jìn)入STOP后根本無(wú)法通過(guò)RTC定時(shí)喚醒MCU。查看ST的官方相關(guān)估計(jì)庫(kù),似乎并沒有關(guān)于RTC 定時(shí)喚醒的參考項(xiàng)目。
我大致找了下,ST官方好像是沒有現(xiàn)存的關(guān)于32F0芯片 RTC定時(shí)喚醒的例程。這里一起交流下RTC 定時(shí)喚醒話題。
其實(shí),實(shí)現(xiàn)這個(gè)RTC 定時(shí)喚醒還是比較簡(jiǎn)單的。這里有個(gè)可編程的可自動(dòng)重裝的向下計(jì)數(shù)器,按照相應(yīng)的時(shí)鐘頻率賦予適當(dāng)?shù)闹担慨?dāng)向下計(jì)數(shù)到0時(shí)便產(chǎn)生一個(gè)喚醒標(biāo)志,如果此時(shí)使能了相應(yīng)的定時(shí)喚醒中斷,它就可以把MCU從低功耗模式喚醒。需做如下四項(xiàng)基本的準(zhǔn)備工作。
1、確定RTC時(shí)鐘,即RTCCLK.可以是LSE、LSI、HSE/32其中一個(gè)。下面的例程中選用LSI.
2、為自動(dòng)喚醒定時(shí)計(jì)數(shù)器選擇合適的時(shí)鐘源。可以是RTCCLK的2,4,8,16分頻后的某一個(gè),或者使用RTCCLK經(jīng)過(guò)預(yù)分頻后的秒時(shí)鐘CK_SPRE。下面例程中選用RTCCLK/16作為喚醒計(jì)時(shí)器【RTC_WUTR】的時(shí)鐘源。

3、結(jié)合上面選定的喚醒定時(shí)器的時(shí)鐘和需要STOP休眠的時(shí)間,計(jì)算出將賦給喚醒定時(shí)器【RTC_WUTR】的重載值。比方這里以LSI/16作為定時(shí)器的計(jì)數(shù)時(shí)鐘,假設(shè)定時(shí)1S,LSI的頻率按40K算的話,那40k/16=2500,16進(jìn)制即0x9c4.
那如果定時(shí)1S的話,賦值應(yīng)該就是0X9C4.【LSI有波動(dòng),定時(shí)可能誤差】
4、做好RTC周期性定時(shí)喚醒的中斷配置,即NVIC配置。RTC喚醒事件是連接到EXTI 20號(hào)線。

下面是我做測(cè)試RTC 定時(shí)喚醒功能的一個(gè)簡(jiǎn)單例程,需要時(shí)可以參考。其中主程序MAIN()內(nèi)容比較簡(jiǎn)單,無(wú)限循環(huán)里的內(nèi)容就是LED燈先滅,進(jìn)入STOP模式,1S左右后被RTC 喚醒定時(shí)器喚醒,喚醒后LED亮一會(huì),然后再進(jìn)入下一輪循環(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); //啟動(dòng)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時(shí)鐘源
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);//啟動(dòng)RTC
RTC_WakeUpCmd(DISABLE); //關(guān)閉RTC 喚醒定時(shí)器!!!
RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);//喚醒定時(shí)器時(shí)鐘
RTC_SetWakeUpCounter( 0x9c4); //給RTC WAKE UP TIMER賦重裝值
RTC_WakeUpCmd( ENABLE); //啟動(dòng)RTC 喚醒定時(shí)器
}
/********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);
}
}
這里要提醒下,上面測(cè)試代碼中的RTC_Config()配置函數(shù)里的紅色語(yǔ)句代碼經(jīng)常有人漏掉,這2行對(duì)于操作RTC后備域寄存器時(shí)是必需的。
另外,RTC_WakeUpCmd(DISABLE); 這句也是必須的,否則就沒法對(duì)喚醒定時(shí)器進(jìn)行時(shí)鐘配置和喚醒定時(shí)器賦值。
| 歡迎光臨 (http://www.denmoz.com/bbs/) | Powered by Discuz! X3.1 |