1. 程式人生 > >watchdog(IWDG)

watchdog(IWDG)

實時監控 時鐘 打開 rem from refresh com ati 循環

1、為了避免程序忙跑跑死了沒反應,加上一個看門狗watchdog實時監控著程序,一旦程序沒有在規定的時間餵狗,則狗叫使得單片機復位。

2、Independent watchdog(IWDG)內部有時鐘源(128kHz),所以即使主時鐘掛了watchdog還是能繼續工作的。

  另外還有個Window watchdog (WWDG),比IWDG復雜得多,我們沒有采用。

3、由於內部是128kHz,所以watchdog能允許的最大延遲時間為510ms(當RL[7:0]= 0xFF時),最小延遲時間為2ms(當RL[7:0]= 0x00時);我們選取510ms。

技術分享

  也就是說一旦打開看門狗,最遲每隔510ms就要進行餵狗操作,否則看門狗將會打開復位。

4、看門狗的實現不難,難點在於怎樣驗證自己設置的看門狗是否正確,難點在與想辦法測試watchdog。

  方法是在while(1)的循環裏延時510ms以上(如延時600ms),通過對相關寄存器特征值的顯示查看,來判斷單片機是否被復位,若被復位則驗證成功。

5、值得註意的是,開門狗一旦打開就無法關閉,只有通過不斷的餵狗來防止復位。

6、下面給出代碼思路並且附帶詳細註釋:

  由於延時函數如果延時太久會無法實現餵狗操作,所以應該在原來的Delay1ms()函數的基礎上,再另外定義一個newDelay()函數,目的是每次延時250ms時(即調用Delay1ms(250))餵狗;

技術分享
  1 /*-- private variable --
*/ 2 __IO uint32_t space_reloadTM = 250;//define every after 250 ms reload IWDG 3 4 /*-- private function --*/ 5 void NewDelay(__IO uint32_t nTime);//include reload IWDG 6 7 static void IWDG_Config_Enable(void);//config and enable IWDG 8 9 10 /*-- main function --*/ 11 int main() 12 { 13 IWDG_Config_Enable(); //
config and enable IWDG 14 15 //for test 16 while (1) 17 { 18 Delay1ms(600); //timeout and reset happend 19 20 /*-- never runs here --*/ 21 22 //Reload IWDG counter 23 IWDG_ReloadCounter(); 24 } 25 } 26 27 28 29 void NewDelay(__IO uint32_t nTime) 30 { 31 uint32_t time_divisor = nTime/space_reloadTM; 32 uint32_t time_remainder = nTime%space_reloadTM; 33 uint8_t i; 34 35 /* every after 250ms reload IWDG */ 36 for(i=0;i<time_divisor;i++) 37 { 38 Delay1ms(space_reloadTM); 39 //Reload IWDG counter 40 IWDG_ReloadCounter(); 41 } 42 43 /* delay the remain time */ 44 Delay1ms(time_remainder); 45 //Reload IWDG counter 46 IWDG_ReloadCounter(); 47 } 48 /* 49 void Delay1ms(__IO uint32_t nTime) 50 { 51 TimingDelay = nTime; 52 53 while (TimingDelay != 0); 54 } 55 */ 56 57 58 59 /** 60 * @brief Configures the IWDG to generate a Reset if it is not refreshed at the 61 * correct time. 62 * @param None 63 * @retval None 64 */ 65 static void IWDG_Config_Enable(void) 66 { 67 /* Check if the system has resumed from IWDG reset */ 68 if (RST_GetFlagStatus(RST_FLAG_IWDGF) != RESET) 69 { 70 printf("\n\r"); 71 uart2str(uartbuff,RST->SR,8,2,0); //output RST register 72 printf("Timeout, RST_SR=%s\n\r",uartbuff); 73 74 printf("timeout!!!"); 75 76 /* IWDGF flag set */ 77 /* Clear IWDGF Flag */ 78 RST_ClearFlag(RST_FLAG_IWDGF); 79 } 80 else 81 { 82 //IWDGF flag is not set 83 } 84 85 86 /* --- IWDG Configuration --- */ 87 88 /* Enable IWDG (the LSI oscillator will be enabled by hardware) */ 89 IWDG_Enable(); //0xCC 90 91 /* IWDG timeout equal to 250 ms (the timeout may varies due to LSI frequency 92 dispersion) */ 93 /* Enable write access to IWDG_PR and IWDG_RLR registers */ 94 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //0x55 95 96 /* IWDG counter clock: LSI/128 */ 97 IWDG_SetPrescaler(IWDG_Prescaler_128); 98 99 /* Set counter reload value to obtain 250ms IWDG Timeout. 100 Counter Reload Value = 250ms/IWDG counter clock period 101 = 250ms / (LSI/128) 102 = 0.25s / (LsiFreq/128) 103 = LsiFreq/(128 * 4) 104 = LsiFreq/512 105 */ 106 IWDG_SetReload((uint8_t)(0xFF));//510ms 107 108 /* Reload IWDG counter */ 109 IWDG_ReloadCounter(); //0xAA 110 }
watchdog

  為了驗證代碼的可實現性,故意在主函數中調用Delay1ms(600),所以正確的執行結果應該是:執行Delay1ms(600),watchdog啟動復位,輸出timeout之類的提示;

  其中證明是否是watchdog啟動的復位:查看RST->SR(Reset status register)中Bit1的值,為1表示An IWDG reset occurred,為0表示No IWDG reset occurred。

watchdog(IWDG)