stm32f103 RTC週期性待機喚醒(一)
做一個低功耗的東西,搞了好幾天,程式一直卡在一個地方(見下圖),今天終於發現問題出在哪裡了,對待機喚醒的問題做一個總結(只針對我遇到的問題,其他部分網上都有,基於stm32f103)
1、解決我遇到的問題 我的RTC初始化部分有個“儲存在備份暫存器的RTC標誌是否已經被配置過的判斷”,如果已經配置過,則進入else部分,但是這個else部分沒有“要使能電源時鐘,使能備份時鐘,取消後備區的防寫”這些配置語句,而待機喚醒後程序從主函式執行,會執行到else部分,因為沒有那些配置語句,所以再次對鬧鐘賦值就會不成功,就會卡在那裡。(那些配置語句在clock_ini函式裡,有註釋)
2、待機用不用加extiline17事件 如果把鬧鐘中斷的服務程式放在void RTC_IRQHandler(void)裡面處理的話,不需要extiline17事件也可以喚醒(親測),如果鬧鐘中斷的服務程式放在void RTCAlarm_IRQHandler(void)裡面處理的話,需要extiline17事件
3、RTCAlarm_IRQn和RTC_IRQn優先順序 我見到網上說要把RTCAlarm_IRQn的優先順序設定比RTC_IRQn優先順序高,但是把鬧鐘中斷的服務程式放在void RTC_IRQHandler(void)裡面處理的話,不用這樣設定也可以。如果鬧鐘中斷的服務程式放在void RTCAlarm_IRQHandler(void)裡面處理的話需要設定優先順序,最好根據情況先把優先順序的問題解決清楚
4、下面是我的一些程式碼
-
void Clock_ini(void)
-
{
-
if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) //判斷儲存在備份暫存器的RTC標誌是否已經被配置過
-
{
-
printf("\r\n\n RTC not yet configured....");
-
RTC_Configuration(); <span style="white-space:pre"> </span>//RTC初始化
-
printf("\r\n RTC configured....");
-
Time_Adjust(); //設定RTC 時鐘引數
-
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); //RTC設定後,將已配置標誌寫入備份資料暫存器
-
}
-
else
-
{
-
if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET) //檢查是否掉電重啟
-
{
-
printf("\r\n\n Power On Reset occurred....");
-
}
-
else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET) //檢查是否reset復位
-
{
-
printf("\r\n\n External Reset occurred....");
-
}
-
printf("\r\n No need to configure RTC....");
-
/***新加的,測試,待機喚醒後,程式不經過上面的if部分,所以沒有這三步(兩個語句),所以程式會卡,所以加上,果然***/
-
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
-
/* 允許訪問BKP區域 */
-
PWR_BackupAccessCmd(ENABLE); </span>
-
RTC_WaitForSynchro(); //等待RTC暫存器被同步
-
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能秒中斷
-
RTC_WaitForLastTask();
-
RTC_ITConfig(RTC_IT_ALR, ENABLE); //naozhong
-
RTC_WaitForLastTask(); <span style="white-space:pre"> </span>//等待寫入完成
-
}
-
RCC_ClearFlag(); //清除復位標誌
-
void NVIC_Configuration(void)
-
{
-
NVIC_InitTypeDef NVIC_InitStructure;
-
EXTI_InitTypeDef EXTI_InitStructure;
-
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
-
/* Enable the RTC Interrupt */
-
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //配置外部中斷源(秒中斷)
-
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
-
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 7;
-
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-
NVIC_Init(&NVIC_InitStructure);
-
/* Enable the RTC Alarm Interrupt */
-
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn; //配置外部中斷源(鬧鐘中斷)
-
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
-
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
-
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
-
NVIC_Init(&NVIC_InitStructure);
-
//鬧鐘中斷接到第17線外部中斷
-
EXTI_ClearITPendingBit(EXTI_Line17);
-
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);
-
}
-
void RTC_Configuration(void)
-
{
-
/* 使能 PWR 和 BKP 的時鐘 */
-
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
-
/* 允許訪問BKP區域 */
-
PWR_BackupAccessCmd(ENABLE);
-
/* 復位BKP */
-
BKP_DeInit();
-
#ifdef RTCClockSource_LSI
-
/* 使能內部RTC時鐘 */
-
RCC_LSICmd(ENABLE);
-
/* 等待RTC內部時鐘就緒 */
-
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
-
{
-
}
-
/* 選擇RTC內部時鐘為RTC時鐘 */
-
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
-
#elif defined RTCClockSource_LSE
-
/* 使能RTC外部時鐘 */
-
RCC_LSEConfig(RCC_LSE_ON);
-
/* 等待RTC外部時鐘就緒 */
-
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
-
{
-
}
-
/* 選擇RTC外部時鐘為RTC時鐘 */
-
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
-
#endif
-
/* 使能RTC時鐘 */
-
RCC_RTCCLKCmd(ENABLE);
-
#ifdef RTCClockOutput_Enable
-
/* Disable the Tamper Pin */
-
BKP_TamperPinCmd(DISABLE); /* To output RTCCLK/64 on Tamper pin, the tamper
-
functionality must be disabled */
-
/* 使能在TAMPER腳輸出RTC時鐘 */
-
BKP_RTCCalibrationClockOutputCmd(ENABLE);
-
#endif
-
/* 等待RTC暫存器同步 */
-
RTC_WaitForSynchro();
-
/* 等待寫RTC暫存器完成 */
-
RTC_WaitForLastTask();
-
/* 使能RTC naozhong中斷 */
-
RTC_ITConfig(RTC_IT_ALR, ENABLE);
-
/* 等待寫RTC暫存器完成 */
-
RTC_WaitForLastTask();
-
/* 使能RTC秒中斷 */
-
RTC_ITConfig(RTC_IT_SEC, ENABLE);
-
/* 等待寫RTC暫存器完成 */
-
RTC_WaitForLastTask();
-
/* 設定RTC預分頻 */
-
#ifdef RTCClockSource_LSI
-
RTC_SetPrescaler(31999); /* RTC period = RTCCLK/RTC_PR = (32.000 KHz)/(31999+1) */
-
#elif defined RTCClockSource_LSE
-
RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */
-
#endif
-
/* 等待寫RTC暫存器完成 */
-
RTC_WaitForLastTask();
-
}
-
void RTCAlarm_IRQHandler(void)
-
{
-
RTC_WaitForSynchro();
-
if(RTC_GetITStatus(RTC_IT_ALR) != RESET)
-
{
-
//printf("mmmmmm");
-
EXTI_ClearITPendingBit(EXTI_Line17);
-
RTC_WaitForLastTask();
-
if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
-
{
-
// 清除喚醒標誌
-
PWR_ClearFlag(PWR_FLAG_WU);
-
RTC_WaitForLastTask();
-
}
-
RTC_ClearITPendingBit(RTC_IT_ALR);
-
RTC_WaitForLastTask();
-
printf("\nIt will wake up after %d s\n",standbytime);
-
RTC_Enter_StandbyMode(standbytime);//standbytime秒後喚醒
-
}
-
}
-
void RTC_Enter_StandbyMode(u32 s)
-
{
-
RTC_WaitForLastTask();
-
RTC_SetAlarm(RTC_GetCounter()+s);
-
RTC_WaitForLastTask();
-
// 進入待機模式, 此時所有1.8V域的時鐘都關閉,HIS和HSE的振盪器關閉, 電壓調節器關閉.
-
// 只有WKUP引腳上升沿,RTC警告事件,NRST引腳的外部復位,IWDG復位.
-
/* Request to enter STANDBY mode (Wake Up flag is cleared in PWR_EnterSTANDBYMode function) */
-
PWR_EnterSTANDBYMode();
-
}
5、接下來幾天我要研究一下停機模式和功耗問題