1. 程式人生 > >STM32待機模式喚醒測試以及獨立看門狗測試

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);
           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述