1 IWDG簡介
STM32有兩個看門狗:一個是獨立看門狗(IWDG),另外一個是窗口看門狗。獨立看門狗也稱寵物狗,窗口看門狗也稱警犬。本文主要分析獨立看門狗的功能和它的應用。
獨立看門狗用通俗一點的話來解釋就是一個12位的遞減計數器,當計數器的值從某個值一直減到0的時候,系統就會產生一個復位信號,即IWDG_RESET。如果在計數器沒減到0之前,刷新了計數器的值的話,那么就不會產生復位信號,這個動作就是我們經常說的“喂狗”。看門狗功能由VDD供電,在停止模式和待機模式下仍能工作。
2 IWDG功能框圖剖析
IWDG功能框圖如下圖所示:
2.1 獨立看門狗時鐘
獨立看門狗的時鐘由獨立的RC震蕩器LSI提供,即使主時鐘發生故障它仍然有效,非常獨立。LSI的頻率一般為30~60kHz,根據溫度和工作場合情況有一定的漂移。我們一般取40kHz,所以獨立看門狗的定時時間不是非常精確,只適用于對時間精度要求比較低的場合。
2.2 計數器時鐘
遞減計數器的時鐘由LSI經過一個8位的預分頻器得到,我們可以操作預分頻器寄存器IWDG_PR來設置分頻因子,分頻因子可以是:[4,8,16,32,64,128,256],計數器時鐘CK_CNT=40/4×2^PRV,一個計數器時鐘周期計數器就減一。
2.3 計數器
獨立看門狗的計數器是一個12位的遞減計數器,最大值為0XFFF。當計數器減到0時,會產生一個復位信號IWDG_RESET,讓程序重新啟動運行。如果在計數器減到0之前刷新了計數器的值的話,就不會產生復位信號,重新刷新計數器值的這個動作俗稱“喂狗”。
2.4 重裝載寄存器
重裝載寄存器是一個12位的寄存器,里面裝著要刷新到計數器的值,這個值的大小決定獨立看門狗的溢出時間。超時時間Tout=(4×2^prv)/40×rlv(s),prv是預分頻器寄存器的值,rlv是重裝載寄存器的值。
2.5鍵寄存器
鍵寄存器IWDG_KR可以說是獨立看門狗的一個控制寄存器,主要有三種控制方式,往這個寄存器寫入下面3個不同的值有不同的效果。
鍵值 | 鍵值作用 |
0XAAAA | 把RLR的值重裝載到CNT |
0X5555 | PR和RLR這兩個寄存器可寫 |
0XCCCC | 啟動 IWDG |
通過寫往鍵寄存器寫0XCCCC來啟動看門狗屬于軟件啟動的方式,一旦獨立看門狗啟動,它就關不掉,只有復位才能關掉它。
2.6 狀態寄存器
狀態寄存器SR只有位0,PVU和位1:RVU有效,這兩位只能由硬件操作,軟件操作不了。
RVU:看門狗計數器重裝載值更新,硬件置1表示重裝載值的更新正在進行中,更新完畢之后由硬件清0.
PVU:看門狗預分頻值更新,硬件置1指示預分頻值的更新正在進行中,當更新完成后,由硬件清0。
所以只有當RVU、PVU都等于0的時候,才可以更新重裝載寄存器和預分頻寄存器。
3 如何使用IWDG
獨立看門狗一般用來檢測和解決由程序引起的故障,比如一個程序正常運行的時間是50ms,在運行完這段程序之后緊接著進行喂狗,我們設置獨立看門狗的定時溢出時間為60ms,比我們需要監控的程序50ms多一點。如果超過60ms還沒有喂狗,那就說明我們的監控程序出故障了,運行出意外了,那么就會產生系統復位,讓程序重新運行。
3.1 IWDG 配置函數
void IWDG_Config(uint8_t prv,uint16_t rlv)
{//使能預分頻寄存器PR和重裝載寄存器RLR可寫IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);//設置預分頻器值IWDG_SetPrescaler(prv);//設置重裝載寄存器值IWDG_RetReload(rlv);//把重裝載寄存器的值放到計數器中IWDG_ReloadCounter();//使能IWDGIWDG_Enable();}
IWDG配置函數有兩個形參,prv用來設置預分頻的值,可取值如下:
/*
* @arg IWDG_Prescaler_4: IWDG 預分頻值設置為4
* @arg IWDG_Prescaler_8: IWDG 預分頻值設置為8
* @arg IWDG_Prescaler_16: IWDG 預分頻值設置為16
* @arg IWDG_Prescaler_32: IWDG 預分頻值設置為32
* @arg IWDG_Prescaler_64: IWDG 預分頻值設置為64
* @arg IWDG_Prescaler_128: IWDG 預分頻值設置為128
* @arg IWDG_Prescaler_256: IWDG 預分頻值設置為256
*/
如果我們需要設置1s的超時溢出,prv可以取IWDG_Prescaler_64,rlv取625,即調用IWDG使得Tout=64/40*625=1s。
3.2 喂狗函數
void IWDG_Feed(void)
(//把重裝載寄存器的值放到計數器中,喂狗,防止IWDG復位//當計數器的值減到0的時候會產生系統復位IWDG_ReloadCounter();
)
3.3 main函數
int main(void)
{//配置LED GPIO,并關閉LEDLED_GPIO_Config();Delay(0X8FFFFF);//——————————————————————————————————————————————————————————//檢查是否為獨立看門狗復位if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST)!=RESET){//獨立看門狗復位//亮紅燈LED_RED;//清除標志RCC_ClearFlag();//如果一直不能喂狗,會一直復位,加上前面的延時,會看到紅燈閃爍//在1s時間內喂狗的話,則會持續亮綠燈}else{//不是看門狗復位(可能為上電復位或者手動按鍵復位之類的操作)//亮藍燈LED_BLUE;}//————————————————————————————————————————————————————————————//配置按鍵GPIOKey_GPIO_Config();//IWDG 1s超時溢出IWDG_Config(IWDG_Prescaler_64,625);//while部分是我們在項目中具體要寫的代碼,這部分的程序可以用獨立看門狗來監控//如果我們知道這部分代碼執行的時間,比如500ms,那么我們可以設置獨立看門狗的溢出時間是600ms//比500ms多一點,如果要被監控的程序沒出意外,正常執行的話,那么執行完畢之后就會執行喂狗程序//如果程序出意外了那程序就會超時,到達不了喂狗的程序,此時就會產生系統復位。//但是也不排除程序出意外了又恢復正常了,剛好喂狗了,歪打正著。所以要想更精確得監控程序//可以使用窗口看門狗,窗口看門狗規定必須在規定的窗口時間內喂狗while(1){//這里添加需要被監控的代碼,如果有就去掉按鍵模擬喂狗,把按鍵掃描程序去掉//——————————————————————————————————————————————————————————————if(Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==KEY_ON){//喂狗,如果不喂狗,系統就會復位,LED1就會滅一次//如果在1s時間內準時喂狗的話,則綠燈會亮,否則紅燈閃爍IWDG_Feed();//喂狗后亮綠燈LED_GREEN;}}//———————————————————————————————————————————————————————————————
}