章參考資料:《STM32F4XX 中文參考手冊》IWDG 章節。
1、IWDG簡介:
STM32 有兩個看門狗,一個是獨立看門狗另外一個是窗口看門狗,獨立看門狗號稱寵物狗,窗口看門狗號稱警犬,本章我們主要分析獨立看門狗的功能框圖和它的應用。獨立看門狗用通俗一點的話來解釋就是一個 12 位的遞減計數器,當計數器的值從某個值一直減到 0 的時候,系統就會產生一個復位信號,即 IWDG_RESET。如果在計數沒減到 0 之前,刷新了計數器的值的話,那么就不會產生復位信號,這個動作就是我們經常說的喂狗。看門狗功能由 VDD 電壓域供電,在停止模式和待機模式下仍能工作。
2 、IWDG功能框圖剖析
①獨立看門狗時鍾
獨立看門狗的時鍾由獨立的 RC振盪器 LSI提供,即使主時鍾發生故障它仍然有效,非常獨立。LSI的頻率一般在 30~60KHZ之間,根據溫度和工作場合會有一定的漂移,我們一般取 40KHZ,所以獨立看門狗的定時時間並一定非常精確,只適用於對時間精度要求比較低的場合。
②計數器時鍾
遞減計數器的時鍾由 LSI經過一個 8位的預分頻器得到,我們可以操作預分頻器寄存器 IWDG_PR 來設置分頻因子,分頻因子可以是:[4,8,16,32,64,128,256,256],計數器時鍾CK_CNT= 40/ 4*2^PRV,一個計數器時鍾計數器就減一。
③計數器
獨立看門狗的計數器是一個 12 位的遞減計數器,最大值為 0XFFF,當計數器減到 0時,會產生一個復位信號:IWDG_RESET,讓程序重新啟動運行,如果在計數器減到 0 之前刷新了計數器的值的話,就不會產生復位信號,重新刷新計數器值的這個動作我們俗稱喂狗。
④重裝載寄存器
重裝載寄存器是一個 12 位的寄存器,里面裝着要刷新到計數器的值,這個值的大小決定着獨立看門狗的溢出時間。超時時間 Tout = (4*2^prv) / 40 * rlv (s) ,prv是預分頻器寄存器的值,rlv是重裝載寄存器的值。
⑤鍵值寄存器
鍵值寄存器 IWDG_KR 可以說是獨立看門狗的一個控制寄存器,主要有三種控制方式,往這個寄存器寫入下面三個不同的值有不同的效果。
通過寫往鍵寄存器寫 0XCCC 來啟動看門狗是屬於軟件啟動的方式,一旦獨立看門狗啟動,它就關不掉,只有復位才能關掉。
⑥狀態寄存器
狀態寄存器 SR只有位 0:PVU和位 1:RVU有效,這兩位只能由硬件操作,軟件操作不了。RVU:看門狗計數器重裝載值更新,硬件置 1 表示重裝載值的更新正在進行中,更新完畢之后由硬件清 0。PVU: 看門狗預分頻值更新,硬件置’1’指示預分頻值的更新正在進行中,當更新完成后,由硬件清 0。所以只有當 RVU/PVU等於 0 的時候才可以更新重裝載寄存器/預分頻寄存器。
3、 怎么用 IWDG
獨立看門狗一般用來檢測和解決由程序引起的故障,比如一個程序正常運行的時間是50ms,在運行完這個段程序之后緊接着進行喂狗,我們設置獨立看門狗的定時溢出時間為60ms,比我們需要監控的程序 50ms 多一點,如果超過 60ms 還沒有喂狗,那就說明我們監控的程序出故障了,跑飛了,那么就會產生系統復位,讓程序重新運行。
4 、IWDG超時實驗
硬件設計:
1-IWDG,屬於內部資源,無需外部硬件
2-KEY 一個
3-LED 兩個,用開發板自帶的RGB燈即可
實驗設計
配置IWDG的超時時間為1S,如果在1S之內沒有及時喂狗的話,產生系統復位,並用LED燈的狀態變化來指示。
編程要點
1-如何配置IWDG的超時時間?
2-如果編寫喂狗函數?
3-在main函數里面的什么地方喂狗比較合適?
配置IWDG的超時時間。
/* * 設置 IWDG 的超時時間 * Tout = prv/40 * rlv (s) * prv可以是[4,8,16,32,64,128,256] * prv:預分頻器值,取值如下: * @arg IWDG_Prescaler_4: IWDG prescaler set to 4 * @arg IWDG_Prescaler_8: IWDG prescaler set to 8 * @arg IWDG_Prescaler_16: IWDG prescaler set to 16 * @arg IWDG_Prescaler_32: IWDG prescaler set to 32 * @arg IWDG_Prescaler_64: IWDG prescaler set to 64 * @arg IWDG_Prescaler_128: IWDG prescaler set to 128 * @arg IWDG_Prescaler_256: IWDG prescaler set to 256 * * 獨立看門狗使用LSI作為時鍾。 * LSI 的頻率一般在 30~60KHZ 之間,根據溫度和工作場合會有一定的漂移,我 * 們一般取 40KHZ,所以獨立看門狗的定時時間並一定非常精確,只適用於對時間精度 * 要求比較低的場合。 * * rlv:重裝載寄存器的值,取值范圍為:0-0XFFF * 函數調用舉例: * IWDG_Config(IWDG_Prescaler_64 ,625); // IWDG 1s 超時溢出 * (64/40)*625 = 1s */ void IWDG_Config(uint8_t prv ,uint16_t rlv) { // 使能 預分頻寄存器PR和重裝載寄存器RLR可寫 IWDG_WriteAccessCmd( IWDG_WriteAccess_Enable ); // 設置預分頻器值 IWDG_SetPrescaler( prv ); // 設置重裝載寄存器值 IWDG_SetReload( rlv ); // 把重裝載寄存器的值放到計數器中 IWDG_ReloadCounter(); // 使能 IWDG IWDG_Enable(); }
喂狗函數:
// 喂狗 void IWDG_Feed(void) { // 把重裝載寄存器的值放到計數器中,喂狗,防止IWDG復位 // 當計數器的值減到0的時候會產生系統復位 IWDG_ReloadCounter(); }
#include "stm32f4xx.h" #include "./led/bsp_led.h" #include "./key/bsp_key.h" #include "./iwdg/bsp_iwdg.h" static void Delay(__IO u32 nCount); int main(void) { /* LED 端口初始化 */ LED_GPIO_Config(); Delay(0X8FFFFF); /* 檢查是否為獨立看門狗復位 */ if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET) { /* 獨立看門狗復位 */ /* 亮紅燈 */ LED_RED; /* 清除標志 */ RCC_ClearFlag(); /*如果一直不喂狗,會一直復位,加上前面的延時,會看到紅燈閃爍 在1s 時間內喂狗的話,則會持續亮綠燈*/ } else { /*不是獨立看門狗復位(可能為上電復位或者手動按鍵復位之類的) */ /* 亮藍燈 */ LED_BLUE; } /*初始化按鍵*/ Key_GPIO_Config(); // IWDG 1s 超時溢出 IWDG_Config(IWDG_Prescaler_64 ,625); //while部分是我們在項目中具體需要寫的代碼,這部分的程序可以用獨立看門狗來監控 //如果我們知道這部分代碼的執行時間,比如是500ms,那么我們可以設置獨立看門狗的 //溢出時間是600ms,比500ms多一點,如果要被監控的程序沒有跑飛正常執行的話,那么 //執行完畢之后就會執行喂狗的程序,如果程序跑飛了那程序就會超時,到達不了喂狗的 //程序,此時就會產生系統復位。但是也不排除程序跑飛了又跑回來了,剛好喂狗了, //歪打正着。所以要想更精確的監控程序,可以使用窗口看門狗,窗口看門狗規定必須 //在規定的窗口時間內喂狗。 while(1) { if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON ) { // 喂狗,如果不喂狗,系統則會復位,復位后亮紅燈,如果在1s // 時間內准時喂狗的話,則會亮綠燈 IWDG_Feed(); //喂狗后亮綠燈 LED_GREEN; } } } static void Delay(__IO uint32_t nCount) //簡單的延時函數 { for(; nCount != 0; nCount--); } /*********************************************END OF FILE**********************/
程序先檢查是否為獨立看門狗復位,如果是獨立看門狗復位亮紅燈。如果一直不喂狗,會一直復位,加上前面的延時,會看到紅燈閃爍,在1S時間內喂狗的話,則會持續亮綠燈。