STM32待機模式喚醒測試以及獨立看門狗測試
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
STM32待機模式喚醒測試以及獨立看門狗測試
本文部落格連結:http://blog.csdn.net/jdh99,作者:jdh,轉載請註明.
環境:
主機:WIN7
開發環境:MDK4.23
MCU:STM32F103CBT6
說明:
在上篇文章中http://blog.csdn.net/jdh99/article/details/7369844,進行了一些STM32待機模式的測試.其中關於如何在再次啟動時判斷是否是待機模式沒有進行測試.另外上篇文章有個問題,鬧鐘中斷在待機模式下是進入不了的.
本文進行了獨立看門狗IWDG測試,以及待機模式更詳細的測試.
STM32中,復位分為3種:
1.系統復位:外部復位,WWDG,IWDG,SW復位,低功耗管理復位.除復位標誌暫存器RCC_CSR不被複位,全部都被複位
2.電源復位:上電/掉電覆位,從待機模式復位.上電/掉電覆位除備份域外暫存器全部復位.待機復位不會復位備份域暫存器以及PWR_CSR暫存器.
3.備份域復位.
暫存器說明:
由圖可以看出,可以通過WUF位來判斷是否由待機模式喚醒.
RCC_CSR暫存器:
由圖可以看出,RCC_CSR暫存器的IWDGRSTF位可以指示是否發生獨立看門狗復位.
因為在看門狗復位時如果系統不處在待機模式,PWR_CSR暫存器也會被複位,所以WUF位也可以指示是否發生獨立看門狗復位.
原始碼:
獨立看門狗復位測試:
//檢查喚醒標誌是否設定 if (PWR_GetFlagStatus(PWR_FLAG_WU) == RESET){ //首次啟動,或者獨立看門狗復位 //初始化備份暫存器 //BKP_DeInit(); //RTC功能開啟 //使能外部晶振 RCC_LSEConfig(RCC_LSE_ON); //等待外部晶振準備好 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); //設定RTC時鐘為外部晶振 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //使能RTC時鐘 RCC_RTCCLKCmd(ENABLE); //等待RTC_CTL暫存器中的RSF位(暫存器同步標誌)被硬體置1 RTC_WaitForSynchro(); RTC_WaitForLastTask(); //使能鬧鐘中斷 RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); //分頻係數為1,即最小時間單位1/2^15 = 30.5us RTC_SetPrescaler(RTC_PRESCALE); RTC_WaitForLastTask(); //啟動獨立看門狗 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //訪問之前要首先使能暫存器寫 IWDG_SetPrescaler(IWDG_Prescaler_64); //64分頻 一個週期1.6ms IWDG_SetReload(1250); //最長12位 [0,4096] 1250*1.6 = 2s IWDG_ReloadCounter(); //喂狗 //使能開門狗 IWDG_Enable(); if (BKP_ReadBackupRegister(BKP_DR6) == 0xabcd) { GPIO_ResetBits(GPIOA, GPIO_Pin_11) ; BKP_WriteBackupRegister(BKP_DR6,0); } else { GPIO_SetBits(GPIOA,GPIO_Pin_11) ; BKP_WriteBackupRegister(BKP_DR6,0xabcd); } }else{ //從待機模式中退出 //清除喚醒標誌 RCC_ClearFlag(); if (BKP_ReadBackupRegister(BKP_DR7) == 0xabcd) { GPIO_ResetBits(GPIOA, GPIO_Pin_8) ; BKP_WriteBackupRegister(BKP_DR7,0); } else { GPIO_SetBits(GPIOA,GPIO_Pin_8) ; BKP_WriteBackupRegister(BKP_DR7,0xabcd); }}while (1);
測試結果PA11引腳所連的LED不斷閃爍,PA8所連的LED常亮,這說明不斷進入看門狗復位.
待機模式RTC鬧鐘喚醒測試:
//檢查喚醒標誌是否設定if (PWR_GetFlagStatus(PWR_FLAG_WU) == RESET){ //首次啟動,或者獨立看門狗復位 //初始化備份暫存器 //BKP_DeInit(); //RTC功能開啟 //使能外部晶振 RCC_LSEConfig(RCC_LSE_ON); //等待外部晶振準備好 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); //設定RTC時鐘為外部晶振 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //使能RTC時鐘 RCC_RTCCLKCmd(ENABLE); //等待RTC_CTL暫存器中的RSF位(暫存器同步標誌)被硬體置1 RTC_WaitForSynchro(); RTC_WaitForLastTask(); //使能鬧鐘中斷 RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); //分頻係數為1,即最小時間單位1/2^15 = 30.5us RTC_SetPrescaler(RTC_PRESCALE); RTC_WaitForLastTask(); //啟動獨立看門狗 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //訪問之前要首先使能暫存器寫 IWDG_SetPrescaler(IWDG_Prescaler_64); //64分頻 一個週期1.6ms IWDG_SetReload(1250); //最長12位 [0,4096] 1250*1.6 = 2s IWDG_ReloadCounter(); //喂狗 //使能開門狗 //IWDG_Enable(); if (BKP_ReadBackupRegister(BKP_DR6) == 0xabcd) { GPIO_ResetBits(GPIOA, GPIO_Pin_11) ; BKP_WriteBackupRegister(BKP_DR6,0); } else { GPIO_SetBits(GPIOA,GPIO_Pin_11) ; BKP_WriteBackupRegister(BKP_DR6,0xabcd); } }else{ //從待機模式中退出 //清除喚醒標誌 RCC_ClearFlag(); if (BKP_ReadBackupRegister(BKP_DR7) == 0xabcd) { GPIO_ResetBits(GPIOA, GPIO_Pin_8) ; BKP_WriteBackupRegister(BKP_DR7,0); } else { GPIO_SetBits(GPIOA,GPIO_Pin_8) ; BKP_WriteBackupRegister(BKP_DR7,0xabcd); }}
//延時1sfor (i = 0;i < 100;i++){ _delay_ms(10);}
//開啟待機模式,1s後喚醒
open_standy_mode(30000);
每次剛上電所有LED會亮,進入待機模式則全部滅.測試結果PA8引腳所連的LED會亮1s進入滅進入待機模式,下次則常滅進入待機模式.PA11所連的LED隨著低功耗進入正常亮滅,這說明不斷髮生鬧鐘喚醒(看門狗已關).
待機模式IWDG喚醒測試:
//檢查喚醒標誌是否設定if (PWR_GetFlagStatus(PWR_FLAG_WU) == RESET){ //首次啟動,或者獨立看門狗復位 //初始化備份暫存器 //BKP_DeInit(); //RTC功能開啟 //使能外部晶振 RCC_LSEConfig(RCC_LSE_ON); //等待外部晶振準備好 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); //設定RTC時鐘為外部晶振 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //使能RTC時鐘 RCC_RTCCLKCmd(ENABLE); //等待RTC_CTL暫存器中的RSF位(暫存器同步標誌)被硬體置1 RTC_WaitForSynchro(); RTC_WaitForLastTask(); //使能鬧鐘中斷 RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); //分頻係數為1,即最小時間單位1/2^15 = 30.5us RTC_SetPrescaler(RTC_PRESCALE); RTC_WaitForLastTask(); //啟動獨立看門狗 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //訪問之前要首先使能暫存器寫 IWDG_SetPrescaler(IWDG_Prescaler_64); //64分頻 一個週期1.6ms IWDG_SetReload(1250); //最長12位 [0,4096] 1250*1.6 = 2s IWDG_ReloadCounter(); //喂狗 //使能開門狗 IWDG_Enable(); if (BKP_ReadBackupRegister(BKP_DR6) == 0xabcd) { GPIO_ResetBits(GPIOA, GPIO_Pin_11) ; BKP_WriteBackupRegister(BKP_DR6,0); } else { GPIO_SetBits(GPIOA,GPIO_Pin_11) ; BKP_WriteBackupRegister(BKP_DR6,0xabcd); } }else{ //從待機模式中退出 //清除喚醒標誌 RCC_ClearFlag(); if (BKP_ReadBackupRegister(BKP_DR7) == 0xabcd) { GPIO_ResetBits(GPIOA, GPIO_Pin_8) ; BKP_WriteBackupRegister(BKP_DR7,0); } else { GPIO_SetBits(GPIOA,GPIO_Pin_8) ; BKP_WriteBackupRegister(BKP_DR7,0xabcd); }}//延時1sfor (i = 0;i < 100;i++){ _delay_ms(10);} //開啟待機模式,2s後喚醒open_standy_mode(60000);
每次剛上電所有LED會亮,進入待機模式則全部滅.測試結果PA11引腳所連的LED會亮1s進入滅進入待機模式,下次則常滅進入待機模式.PA8所連的LED隨著低功耗進入正常亮滅,而且待機模式是待機2s加延時1s應該是3s喚醒,LED閃爍頻率2s左右說明被提前喚醒.這說明不斷髮生看門狗喚醒.
完整的測試程式:判斷出首次啟動程式,微控制器處於正常狀態時看門狗復位,微控制器處於待機模式下被鬧鐘喚醒/看門狗喚醒.
注意:每次看門狗復位都要被重新配置啟動
//檢查是否正常狀態發生看門狗復位if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET){ //清楚標誌位 RCC_ClearFlag(); //RTC功能開啟 //使能外部晶振 RCC_LSEConfig(RCC_LSE_ON); //等待外部晶振準備好 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); //設定RTC時鐘為外部晶振 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //使能RTC時鐘 RCC_RTCCLKCmd(ENABLE); //等待RTC_CTL暫存器中的RSF位(暫存器同步標誌)被硬體置1 RTC_WaitForSynchro(); RTC_WaitForLastTask(); //使能鬧鐘中斷 RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); //分頻係數為1,即最小時間單位1/2^15 = 30.5us RTC_SetPrescaler(RTC_PRESCALE); RTC_WaitForLastTask(); //啟動獨立看門狗 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //訪問之前要首先使能暫存器寫 IWDG_SetPrescaler(IWDG_Prescaler_64); //64分頻 一個週期1.6ms IWDG_SetReload(1250); //最長12位 [0,4096] 1250*1.6 = 2s IWDG_ReloadCounter(); //喂狗 //使能開門狗 IWDG_Enable(); if (BKP_ReadBackupRegister(BKP_DR5) == 0xabcd) { GPIO_SetBits(GPIOA,GPIO_Pin_12) ; BKP_WriteBackupRegister(BKP_DR5,0); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_12) ; BKP_WriteBackupRegister(BKP_DR5,0xabcd); } }else{ //檢查喚醒標誌是否設定,判斷是否首次啟動 if (PWR_GetFlagStatus(PWR_FLAG_WU) == RESET) { //首次啟動 //初始化備份暫存器 //BKP_DeInit(); //RTC功能開啟 //使能外部晶振 RCC_LSEConfig(RCC_LSE_ON); //等待外部晶振準備好 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET); //設定RTC時鐘為外部晶振 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //使能RTC時鐘 RCC_RTCCLKCmd(ENABLE); //等待RTC_CTL暫存器中的RSF位(暫存器同步標誌)被硬體置1 RTC_WaitForSynchro(); RTC_WaitForLastTask(); //使能鬧鐘中斷 RTC_ITConfig(RTC_IT_ALR, ENABLE); RTC_WaitForLastTask(); //分頻係數為1,即最小時間單位1/2^15 = 30.5us RTC_SetPrescaler(RTC_PRESCALE); RTC_WaitForLastTask(); //啟動獨立看門狗 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //訪問之前要首先使能暫存器寫 IWDG_SetPrescaler(IWDG_Prescaler_64); //64分頻 一個週期1.6ms IWDG_SetReload(1250); //最長12位 [0,4096] 1250*1.6 = 2s IWDG_ReloadCounter(); //喂狗 //使能開門狗 IWDG_Enable(); if (BKP_ReadBackupRegister(BKP_DR6) == 0xabcd) { GPIO_ResetBits(GPIOA, GPIO_Pin_11) ; BKP_WriteBackupRegister(BKP_DR6,0); } else { GPIO_SetBits(GPIOA,GPIO_Pin_11) ; BKP_WriteBackupRegister(BKP_DR6,0xabcd); } } else { //從待機模式中退出,有鬧鐘喚醒或者看門狗喚醒 //清除喚醒標誌 RCC_ClearFlag(); if (BKP_ReadBackupRegister(BKP_DR7) == 0xabcd) { GPIO_ResetBits(GPIOA, GPIO_Pin_8) ; BKP_WriteBackupRegister(BKP_DR7,0); } else { GPIO_SetBits(GPIOA,GPIO_Pin_8) ; BKP_WriteBackupRegister(BKP_DR7,0xabcd); } }}//延時1sfor (i = 0;i < 100;i++){ _delay_ms(10);}//開啟待機模式,2s後喚醒open_standy_mode(60000);