看門(mén)狗定時(shí)器(WDT,Watch Dog Timer)是單片機(jī)的一個(gè)組成部分,它實(shí)際上是一個(gè)計(jì)數(shù)器,一般來(lái)說(shuō)都是向下計(jì)數(shù)的,給看門(mén)狗一個(gè)數(shù)字,程序開(kāi)始運(yùn)行后看門(mén)狗開(kāi)始倒計(jì)數(shù)。如果程序運(yùn)行正常,過(guò)一段時(shí)間CPU應(yīng)發(fā)出指令讓看門(mén)狗復(fù)位(在計(jì)數(shù)器減到0之前),重新開(kāi)始倒計(jì)數(shù)。如果看門(mén)狗減到0就認(rèn)為程序沒(méi)有正常工作,強(qiáng)制整個(gè)系統(tǒng)復(fù)位。本節(jié)將對(duì)看門(mén)狗定時(shí)器的工作原理和作用進(jìn)行詳細(xì)講解。
看門(mén)狗的主要功能是在發(fā)生系統(tǒng)軟件故障時(shí),將系統(tǒng)復(fù)位。也可以用于將系統(tǒng)從休眠或空閑模式喚醒。一般在嵌入式開(kāi)發(fā)中,整個(gè)程序都是在次循環(huán)往復(fù)不停的工作,正常運(yùn)行期間會(huì)定時(shí)讓看門(mén)狗復(fù)位,一旦程序發(fā)生故障,停在某一處,看門(mén)狗不能及時(shí)復(fù)位,計(jì)數(shù)器減到0,就會(huì)強(qiáng)制整個(gè)系統(tǒng)復(fù)位,一般情況下復(fù)位操作能解決大部分問(wèn)題。
用戶開(kāi)發(fā)的產(chǎn)品很有可能運(yùn)用到一些非常極端苛刻的環(huán)境中,容易發(fā)生故障,但是通過(guò)復(fù)位就能解決,如果人工復(fù)位,成本相當(dāng)高,這時(shí)候看門(mén)狗的使用就非常有效了。
STM32結(jié)合安全度、計(jì)時(shí)精確度和易用性提供了IWDG和WWDG兩種看門(mén)狗,監(jiān)測(cè)軟件跑飛,或未按預(yù)想地運(yùn)行的情況觸發(fā)系統(tǒng)復(fù)位或產(chǎn)生中斷(中斷僅針對(duì)窗口看門(mén)狗)
獨(dú)立看門(mén)狗IWDG:專(zhuān)用時(shí)鐘LSI(內(nèi)部低速時(shí)鐘),低功耗模式仍可運(yùn)行,對(duì)定時(shí)的控制比較松,由于專(zhuān)門(mén)為其提供獨(dú)立的時(shí)鐘,因此稱(chēng)為獨(dú)立看門(mén)狗。
窗口看門(mén)狗WWDG:總線時(shí)鐘APB1,對(duì)定時(shí)控制比較嚴(yán),要求主應(yīng)用程序在規(guī)定時(shí)間窗口內(nèi)喂狗。
獨(dú)立看門(mén)狗IWDG工作原理框圖分析
獨(dú)立看門(mén)狗本質(zhì)上就是一個(gè)計(jì)數(shù)定時(shí)器,既然是定時(shí)器,就和普通定時(shí)器的工作原理差不多,仍然包含計(jì)數(shù)器,重裝載寄存器等關(guān)鍵部件。計(jì)數(shù)器遞減的速度取決于時(shí)鐘的頻率,獨(dú)立看門(mén)狗使用專(zhuān)用內(nèi)部低速時(shí)鐘,大小為32KHz。當(dāng)計(jì)數(shù)器減到0后會(huì)觸發(fā)一個(gè)復(fù)位異常,進(jìn)行系統(tǒng)的重啟。為了不讓計(jì)數(shù)器減到0,在程序中每過(guò)一段時(shí)間都要進(jìn)行喂狗操作,喂狗操作就是刷新遞減計(jì)數(shù)器CNT的值,就是把重裝載值再次刷進(jìn)計(jì)數(shù)器中。狀態(tài)寄存器是用來(lái)指示預(yù)分頻器和重載寄存器更新的狀態(tài)。
1.獨(dú)立看門(mén)狗的時(shí)鐘:STM32F4 的獨(dú)立看門(mén)狗由內(nèi)部專(zhuān)門(mén)的 32Khz 低速時(shí)鐘(LSI)驅(qū)動(dòng),即使主時(shí)鐘發(fā)生故障,它也仍然有效。這里需要注意獨(dú)立看門(mén)狗的時(shí)鐘是一個(gè)內(nèi)部RC時(shí)鐘(RC振蕩器典型的缺陷就是比較容易受環(huán)境的影響,且精確地不高),所以并不是準(zhǔn)確的32Khz,而是在 15~47Khz 之間的一個(gè)可變化的時(shí)鐘,只是我們?cè)诠浪愕臅r(shí)候(之所以要估算時(shí)間是因?yàn)橛脩粢_保計(jì)數(shù)器減到0 之前喂狗),以 32Khz 的頻率來(lái)計(jì)算,看門(mén)狗對(duì)時(shí)間的要求不是很精確,所以,時(shí)鐘有些偏差,都是可以接受的。
2.預(yù)分頻器:分頻之后的時(shí)鐘才是真正驅(qū)動(dòng)遞減計(jì)數(shù)器的時(shí)鐘。寄存器中只有低3位有效,不同的位組合表示不同的分頻系數(shù)。
3.重載寄存器:低12位有效,最大值位2的12次方。只有在關(guān)鍵字寄存器中寫(xiě)入AAAAh時(shí),重載寄存器厚葬的值才會(huì)自動(dòng)裝載到看門(mén)狗計(jì)數(shù)器中。
4.關(guān)鍵字寄存器:用來(lái)控制獨(dú)立看門(mén)狗,寫(xiě)入不同的值執(zhí)行不同的命令。正常情況下PR和PLR是不可寫(xiě)的,具有寫(xiě)保護(hù),需要通過(guò)寫(xiě)入關(guān)鍵字寄存器值來(lái)解除寫(xiě)保護(hù)。另外一旦通過(guò)關(guān)鍵字寄存器啟動(dòng)看門(mén)狗,看門(mén)狗計(jì)數(shù),將不會(huì)再停止,除非硬件復(fù)位,默認(rèn)情況下看門(mén)狗關(guān)閉,所以正常情況下不輕易使用看門(mén)狗,否則系統(tǒng)會(huì)產(chǎn)生出乎意料的復(fù)位,造成損失。
5.狀態(tài)寄存器:低2位有效,更新時(shí)一定要確定相應(yīng)位為0才可以更新。
IWDG的超時(shí)時(shí)間
以預(yù)分頻器分頻系數(shù)為32為例,計(jì)數(shù)器的時(shí)鐘頻率為1KHz,每個(gè)脈寬的時(shí)間間隔為1ms,當(dāng)計(jì)數(shù)器的值為最小值1時(shí),則最短超時(shí)時(shí)間為1ms,當(dāng)當(dāng)計(jì)數(shù)器的值為最大值0xFFF時(shí),最長(zhǎng)超時(shí)時(shí)間為2的12次方乘以1ms為4096ms。因此用戶可根據(jù)下表設(shè)置正確的超時(shí)時(shí)間防止看門(mén)狗復(fù)位。
IWDG獨(dú)立看門(mén)狗實(shí)例
實(shí)驗(yàn)要求:開(kāi)啟STM32的獨(dú)立看門(mén)狗,按鍵按下即喂狗,如果超時(shí)未喂狗,則看門(mén)狗復(fù)位系統(tǒng),用指示燈指示系統(tǒng)復(fù)位。
步驟:
1.配置RCC
2.使能并配置IWDG
3.配置按鍵管腳為輸入模式。
4.編寫(xiě)代碼
//mian.c
#include "main.h"
#include "stm32f4xx_hal.h"
#include "iwdg.h"
#include "usart.h"
#include "gpio.h"
int main(){
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_IWDG_Init();
printf("this is iwdg testn");
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_SET);//默認(rèn)指示燈熄滅
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_RESET);
//指示燈亮,如果系統(tǒng)復(fù)位,指示燈就會(huì)熄滅0.5s后再次亮起
while(){
//********************************
//********************************
//********************************
//正常情況下喂狗操作之前有很多用戶程序
//現(xiàn)在使用按鍵手動(dòng)喂狗以便觀察現(xiàn)象
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) {
HAL_IWDG_Refresh(&hiwdg);
//喂狗操作,將重載計(jì)數(shù)器的值再次裝填到計(jì)數(shù)器中 ,防止復(fù)位 }
}
}
窗口看門(mén)狗WWDG剖析
窗口看門(mén)狗(WWDG)通常被用來(lái)監(jiān)測(cè)由外部干擾或不可預(yù)見(jiàn)的邏輯條件造成的應(yīng)用程序背離正常的運(yùn)行序列而產(chǎn)生的軟件故障。
遞減計(jì)數(shù)器的值在 T6 位(WWDG->CR 的第六位)變成 0 前被刷新,看門(mén)狗電路在達(dá)到預(yù)置的時(shí)間周期時(shí),會(huì)產(chǎn)生一個(gè) MCU 復(fù)位。WWDG->CR滿載時(shí)為1111111,即0x7F,滿載隨著時(shí)鐘減1,當(dāng)減到1000000,即0x40時(shí),如果再減1變?yōu)?x3F之前計(jì)數(shù)器沒(méi)有被刷新(喂狗),則會(huì)產(chǎn)生 MCU 復(fù)位。由0x40變?yōu)?x3F第六為由1變?yōu)?,也就是第6為變?yōu)?之前計(jì)數(shù)器必須被刷新。0x40就是下窗口
在遞減計(jì)數(shù)器達(dá)到窗口配置寄存器(WWDG->CFR)數(shù)值之前,如果 7 位的遞減計(jì)數(shù)器數(shù)值(在控制寄存器中)被刷新, 那么也將產(chǎn)生一個(gè) MCU 復(fù)位。也就是計(jì)數(shù)器在減到窗口配置寄存器(WWDG->CFR)中設(shè)定的數(shù)值之前被刷新(喂狗),就會(huì)就會(huì)產(chǎn)生 MCU 復(fù)位。這個(gè)數(shù)值就是上窗口
二者分別設(shè)定了一個(gè)喂狗的時(shí)間下限和一個(gè)喂狗的時(shí)間上限,中間形成了一個(gè)喂狗的窗口,因而稱(chēng)為窗口看門(mén)狗。這樣對(duì)喂狗的時(shí)間有了更加精確的定位,要求也更嚴(yán)格。
WWDG的特性
可配置的時(shí)間窗,用來(lái)檢測(cè)應(yīng)用程序非預(yù)期中的運(yùn)行流程(過(guò)早或過(guò)晚),上窗口的值可配置范圍為0x40-0x7F(64-127)
看門(mén)狗復(fù)位條件:①使能了看門(mén)狗的情況下,自減計(jì)數(shù)器值小于0x40。② 使能了看門(mén)狗的情況下,喂狗時(shí)間大于上窗口的值
計(jì)數(shù)器值=0x40時(shí)可以使能一個(gè)早期喚醒中斷(EWI),因?yàn)樵贉p下去即將產(chǎn)生復(fù)位,如果有些數(shù)據(jù)還不保存就來(lái)不及了,可以在中斷處理中做一些緊急保護(hù)的事情或者刷新看門(mén)狗計(jì)數(shù)器。
窗口看門(mén)狗WWDG工作原理框圖分析
①窗口看門(mén)狗時(shí)鐘:窗口看門(mén)狗時(shí)鐘來(lái)自 PCLK1,也就是來(lái)自APB1,是主系統(tǒng)時(shí)鐘,PCLK1 最大是 42M,由 RCC 時(shí)鐘控制器開(kāi)啟。一旦主系統(tǒng)時(shí)鐘崩潰,窗口看門(mén)狗就無(wú)法工作。
②計(jì)數(shù)器時(shí)鐘:計(jì)數(shù)器時(shí)鐘由 CK計(jì)時(shí)器時(shí)鐘經(jīng)過(guò)預(yù)分頻器分頻得到,WDG分頻器仍然有一些分頻系數(shù)供用戶選擇,分頻系數(shù)由配置寄存器 CFR 的位 8:7 WDGTB[1:0]配置。
③計(jì)數(shù)器:窗口看門(mén)狗的計(jì)數(shù)器是一個(gè)遞減計(jì)數(shù)器,共有 7 位,其值存在控制寄存器CR 的位 6:0,即 T[6:0],當(dāng) 7 個(gè)位全部為 1時(shí)是 0X7F,這個(gè)是最大值,當(dāng)遞減到 T6 位變成 0時(shí),即從0X40 變?yōu)?0X40時(shí)候,會(huì)產(chǎn)生看門(mén)狗復(fù)位。這個(gè)值 0X40 是看門(mén)狗能夠遞減到的最小值,當(dāng)遞減計(jì)數(shù)器遞減到 0X40 的時(shí)候,還不會(huì)馬上產(chǎn)生復(fù)位,如果使能了提前喚醒中斷:CFR 位 9 EWI 置 1,則產(chǎn)生提前喚醒中斷,如果真進(jìn)入了這個(gè)中斷的話,就說(shuō)明程序肯定是出問(wèn)題了,那么在提前喚醒中斷的處理程序中我們就需要做最重要的工作,比如保存重要數(shù)據(jù),或者報(bào)警等,這個(gè)中斷我們也叫它死前中斷。但是這個(gè)中斷的處理時(shí)間只有0X40減到0X3F的一個(gè)CLK的時(shí)長(zhǎng)。
④窗口值:下窗口的值是固定的0X40,上窗口的值可以改變,具體的由配置寄存器CFR 的位 6:0 W[6:0]設(shè)置。其值必須大于 0X40(十進(jìn)制為64),如果小于或者等于 0X40就是失去了窗口的價(jià)值,而且也不能大于計(jì)數(shù)器的值,所以必須得小于 0X7F(十進(jìn)制為127)。如何設(shè)置窗口值需要根據(jù)我們需要監(jiān)控的程序的運(yùn)行時(shí)間來(lái)決定。如果我們要監(jiān)控的程序段 A 運(yùn)行的時(shí)間為 Ta,當(dāng)執(zhí)行完這段程序之后就要進(jìn)行喂狗,如果在窗口時(shí)間內(nèi)沒(méi)有喂狗的話,那程序就肯定是出問(wèn)題了。一般計(jì)數(shù)器的值TR設(shè)置成最大 0X7F,窗口值為 WR,計(jì)數(shù)器減一個(gè)數(shù)的時(shí)間為 T,那么時(shí)間:(TR-WR)*T 應(yīng)該稍微小于 Ta即可。
窗口看門(mén)狗WWDG實(shí)例
實(shí)驗(yàn)要求:開(kāi)啟STM32的窗口看門(mén)狗,并使能喚醒中斷。主程序正常運(yùn)行時(shí)喂狗,用按鍵中斷模擬程序故障死機(jī),此時(shí)將觸發(fā)喚醒中斷并產(chǎn)生復(fù)位,用LED燈指示喚醒中斷的觸發(fā)。
達(dá)到0X40會(huì)觸發(fā)早期喚醒中斷,但是再次減1就會(huì)產(chǎn)生系統(tǒng)復(fù)位,因此中斷處理的事件就是1個(gè)CLK的持續(xù)時(shí)間,不同的分頻系數(shù),CLK的持續(xù)時(shí)間不同,總體來(lái)說(shuō)早期喚醒中斷的時(shí)間事件相當(dāng)短,這個(gè)過(guò)程中只能做一些非常緊急的操作。
步驟:
1.配置RCC
2.配置LED燈管腳,設(shè)為輸出模式
3.配置按鍵中斷管腳,設(shè)為外部中斷模式
4.使能并配置WWDG
5.中斷配置
6.編寫(xiě)代碼
//main.c
#include "main.h"
#include "stm32f4xx_hal.h"
#include "usart.h"
#include "wwdg.h"
#include "gpio.h"
int main(){
uint8_t wr, tr;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_WWDG_Init();
printf("this is wwdg testn");
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_SET);//初始時(shí)指示燈熄滅
wr = WWDG- >CFR & 0x7f ;//獲取上窗口的值
while(){
tr = WWDG- >CR & 0x7f;//獲取當(dāng)前計(jì)數(shù)器的值
if(tr < wr){ //計(jì)數(shù)器的值小于上窗口的值,進(jìn)行喂狗
//沒(méi)有復(fù)位說(shuō)明大于下窗口的值,不需要判斷
HAL_WWDG_Refresh(&hwwdg); //刷新計(jì)數(shù)器的值,喂狗
}
}
}
//gpio.c
//重寫(xiě)按鍵中斷(外部中斷)的中斷處理回調(diào)函數(shù)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if(GPIO_Pin == GPIO_PIN_0) {
printf("程序故障n");
while(1); //死循環(huán),模擬故障死機(jī)
}
}
//wwdg.c
//重寫(xiě)提前喚醒中斷的中斷處理回調(diào)函數(shù)
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg) {
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_7, GPIO_PIN_RESET); //LED亮
printf("EarlyWakeup INTn");
//提前喚醒中斷處理的時(shí)間非常有限,串口信息很有可能打印不完整
}
-
看門(mén)狗定時(shí)器
+關(guān)注
關(guān)注
0文章
38瀏覽量
16248 -
STM32F4
+關(guān)注
關(guān)注
3文章
194瀏覽量
28047 -
狀態(tài)寄存器
+關(guān)注
關(guān)注
0文章
39瀏覽量
7083 -
WWDG
+關(guān)注
關(guān)注
0文章
19瀏覽量
5508 -
IWDG
+關(guān)注
關(guān)注
0文章
21瀏覽量
5211
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論