定義
看門狗的本質是一個定時器,在啟動後,需要在一定時間内再給它一個信号,俗稱“喂狗”,如果沒有按時“喂狗”,說明MCU可能處于非正常狀态,這時看門狗就向MCU發送個複位信号,使整個系統重新開機,重新進入正常的工作狀态。看門狗指令在程式的中斷中擁有最高的優先級。
獨立看門狗( Independent Watchdog, IWDG)

時鐘:獨立看門狗的時鐘源來自LSI(内部低速時鐘),意味着不受外部晶振電路影響,同時就算系統主時鐘發生故障時,也可以正常工作。使用内部晶振,也意味精度并不高,是以隻适合應用在對時間精度要求比較低的場合。
計數:獨立看門狗的計數器是一個12位的遞減計數器,計數最大值為0xFFF,當計數器遞減到0時,就會産生一個複位信号,重新開機整個系統。如果在遞減到0之前,将重裝載數值寫入遞減計數器,就會由重裝載數值開始遞減到0,如此反複,就永遠不會到0,就不會産生複位信号,這個重裝載計數值寫入遞減計數器的過程就叫“喂狗”。
重裝載數值來自重裝載寄存器( IWDG_RLR), 這個值大小決定獨立看門狗的溢出時間(複位倒計時)。
/*
* STM32
* 函數名: void IWDG_Init(uint16_t period)
* 輸入參數: period-設定喂狗周期,機關 ms
* 輸出參數:無
* 傳回值:無
* 函數作用:初始化獨立看門狗的喂狗時間
* 重新整理時間計算: Prescaler/LSI*Reload
*/
void IWDG_Init(uint16_t period) {
hiwdg.Instance = IWDG; // 選擇獨立看門狗
hiwdg.Init.Prescaler = IWDG_PRESCALER_256; // 設定預分頻
hiwdg.Init.Reload = 40000/256*period/1000; // 設定重裝載值
if (HAL_IWDG_Init(&hiwdg) != HAL_OK) // 初始化獨立看門狗
{
Error_Handler();
}
}
總結:獨立看門狗包含一個12位遞減計數器,從使用者定義的t開始遞減到0,必須在t~0之間喂狗,否則複位重新開機。
視窗看門狗( Windowwatchdog, WWDG)
視窗看門狗,包含一個7位遞減計數器,從使用者定義的t開始遞減到64,必須在t~64之間喂狗,在t之前或者64之後喂狗,也會導緻複位重新開機。 這裡的t值,稱之為視窗上限,由使用者自定義設定;這裡的64,稱之為視窗下限,是系統固定的。視窗看門狗計數器必須在上視窗和下視窗之間被重新整理(喂狗),不能過早,也不能過晚,這也就視窗看門狗中的“視窗”含義。
時鐘:視窗看門狗的時鐘源來自PCLK1(最高36MHz),經過4096分頻,再經過WWDG_CFG的Bits[8:7]位WDGTB分頻得到, WDGTB支援2^n分頻( 0≤n≤3)。
計數: 視窗看門狗的計數器是一個7位的遞減計數器,計數最大值為0x7F,當計數器遞減到0x3F時,就會産生一個複位信号,重新開機整個系統。 當遞減計數器遞減到0x40時,如果使能了提前喚醒中斷( WWDG_CFG的Bits[9]位EWI設定為1), 則會産生提前喚醒中斷,在該中斷可以儲存重要資料或者向WWDG_CR重新寫入新計數器值,完成喂狗操作。 一旦0x40變為0x39,系統将進行複位,是以必須在一個視窗看門狗計數周期内完成喂狗操作。WWDG_CR的Bits[7]位WDGA為視窗看門狗使能位,當為1時,視窗看門狗才工作。
視窗:視窗看門狗的WWDG_CFG的Bits[6:0]位為視窗上邊界值,該值應小于計數器最大值0x7F,大于視窗下邊界值0x3F。
視窗看門狗初始化
“HAL_WWDG_Init()–HAL庫系統函數”函數會回調“ HAL_WWDG_MspInit()–HAL庫系統函數”進行硬體相關初始化。
視窗看門狗中斷處理
使能中斷後,當視窗看門狗計數到0x40時,會進去提前喚醒中斷,在該中斷處理函數裡,使用者可以儲存資料或喂狗。
/*
* 函數名: void WWDG_IRQHandler(void)
* 輸入參數:無
* 輸出參數:無
* 傳回值:無
* 函數作用: WWDG 的中斷處理函數
*/
void WWDG_IRQHandler(void) {
HAL_WWDG_IRQHandler(&hwwdg); // HAL庫的系統函數
}
/*
* 函數名: void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
* 輸入參數: hwwdg-WWDG 句柄
* 輸出參數:無
* 傳回值:無
* 函數作用:提前喚醒中斷回調函數
*/
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg) {
ClearWWDG(); // 使用者函數内調用HAL庫的系統函數“ HAL_WWDG_Refresh()”重新整理計數器值,實作喂狗操作
printf("-------複位前儲存資料------\n\r");
printf("--------- 軟體喂狗 --------\n\r");
}
對比