一。 看門狗概述
1. 為什么要用看門狗
2. 看門狗要解決的問題
STM32有兩個看門狗
獨立看門狗
窗口看門狗
3. 獨立看門狗的功能描述
鍵值寄存器 KR
(1)往KR中寫入0xCCCC的時候,開始啟動看門狗。
(2)計數(shù)器開始從其復位值0xFFF遞減,當計數(shù)到0的時候會產(chǎn)生一個復位信號RESET。
(3)如果在某個時候往KR寄存器中寫入0xAAAA(喂狗),自動重裝載寄存器RLR的值就會重新加載到計數(shù)器中,從而避免看門狗復位。
如果能夠及時喂狗,計數(shù)器的值就無法到0,從而程序可以正常運行。
在由單片機構成的微型計算機系統(tǒng)中,由于單片機的工作常常會受到來自外界電磁場的干擾,
造成程序跑飛,而陷入死循環(huán),程序的正常運行被打斷,由單片機控制的系統(tǒng)無法繼續(xù)工作,會造
成整個系統(tǒng)陷入停滯狀態(tài),發(fā)生不可預料的后果,所以出于對單片機運行狀態(tài)進行實時監(jiān)測的考慮,
便產(chǎn)生了一種專門用于監(jiān)測單片機程序運行狀態(tài)的模塊或者芯片,俗稱“看門狗”(watchdog)。
單片機系統(tǒng)在外界的干擾下會出現(xiàn)程序跑飛的現(xiàn)象導致出現(xiàn)死循環(huán),看門狗電路就是為了避免
這種情況的發(fā)生??撮T狗的作用就是在一定時間內(nèi)(通過定時計數(shù)器實現(xiàn))沒有接收喂狗信號(表
示 MCU 已經(jīng)掛了),便實現(xiàn)處理器的自動復位重啟(發(fā)送復位信號) 。
4. 獨立看門狗框圖及寄存器
獨立看門狗有外部時鐘SLI驅(qū)動
二。STM32的獨立看門狗
STM32 的獨立看門狗由內(nèi)部專門的 40Khz 低速時鐘驅(qū)動,即使主時鐘發(fā)生故障,它也仍然
有效。
幾個與獨立看門狗相關聯(lián)的寄存器
1.鍵值寄存器( IWDG_KR)
在KR寄存器中寫入0x5555,就取消了PR和RLR的寫保護。
2.預分頻寄存器(IWDG_PR)
該寄存器用來設置看門狗時鐘的分頻系數(shù)
例如:當pr設置為4時,分頻因子=4*2∧4=64,設置為2時,分頻因子= 4*2∧2=16.
3.重裝載寄存器(IWDG_RLR)
該寄存器用來保存重裝載到計數(shù)器中的值。
4. 狀態(tài)寄存器
獲取一些狀態(tài),用的不多。
5. 獨立看門狗超時時間及計算
LSI=40K,先進行預分頻,在預分頻寄存器PR中設置prer,4×2∧prer才是真正的預分頻系數(shù)P。
40/預分頻系數(shù)P=看門狗的頻率
最長時間就是40/預分頻系數(shù)P×0xFFF
最短時間是40/預分頻系數(shù)P×1,也就是一個看門狗時鐘。
三。獨立看門狗常用函數(shù)
四。啟用STM32獨立看門狗的步驟
1.取消寄存器寫保護(向 IWDG_KR 寫入 0X5555)
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
2.設置獨立看門狗的預分頻系數(shù)和重裝載值
設置看門狗的分頻系數(shù)的函數(shù)是:
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //設置 IWDG 預分頻值
設置看門狗的重裝載值的函數(shù)是:
void IWDG_SetReload(uint16_t Reload); //設置 IWDG 重裝載值
設置好看門狗的分頻系數(shù) prer 和重裝載值就可以知道看門狗的喂狗時間,該時間的計算方式為:
Tout=((4×2^prer) ×rlr) /40
其中 Tout 為看門狗溢出時間(單位為 ms) ;prer 為看門狗時鐘預分頻值(IWDG_PR 值),
范圍為 0~7;rlr 為看門狗的重裝載值(IWDG_RLR 的值)。
3.重載計數(shù)值喂狗(向 IWDG_KR 寫入 0XAAAA)
IWDG_ReloadCounter(); //按照 IWDG 重裝載寄存器的值重裝載 IWDG 計數(shù)器
4.啟動看門狗(向 IWDG_KR 寫入 0XCCCC)
IWDG_Enable(); //使能 IWDG
例:
通過按鍵不停的喂狗,否則程序就會復位。
wdg.c 里面的代碼如下:
#include "wdg.h"
//初始化獨立看門狗
//prer:分頻數(shù):0~7(只有低 3 位有效!)
//分頻因子=4*2^prer.但最大值只能是 256!
//rlr:重裝載寄存器值:低 11 位有效.
//時間計算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
void IWDG_Init(u8 prer,u16 rlr)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //①使能對寄存器 I 寫操作
IWDG_SetPrescaler(prer); //②設置 IWDG 預分頻值:設置 IWDG 預分頻值
IWDG_SetReload(rlr); //②設置 IWDG 重裝載值
IWDG_ReloadCounter(); //③按照 IWDG 重裝載寄存器的值重裝載 IWDG 計數(shù)器
IWDG_Enable(); //④使能 IWDG
}
//喂獨立看門狗
void IWDG_Feed(void)
{
IWDG_ReloadCounter();//reload
}
主函數(shù)
如果不去按Wake_up按鍵就會不停的復位,燈會閃,如果不停的按Wake_up,去喂狗,燈會一直亮。
int main(void)
{
vu8 key=0;
delay_init(); //延時函數(shù)初始化
LED_Init(); //LED端口初始化,并滅掉LED燈
KEY_Init(); //初始化與按鍵連接的硬件接口
BEEP_Init(); //初始化蜂鳴器端口
IWDG_Init(4,625); //使溢出時間為1s。
delay_ms(200);
LED0=0; //先點亮紅燈
while(1)
{
if( KEY_Scan(0) == WKUP_PRES ) //如果wake_up按鍵按下了
{
IWDG_ReloadCounter(); //喂狗
}
}
}
Tout=((4*2^prer)*rlr)/40; //單位為毫秒
Tout為看門狗溢出時間(單位為ms);prer為看門狗時鐘預分頻值(IWDG_PR),范圍為0~7;rlr為看門狗的重裝載值(IWDG_RLR的值);
Tout = ((4*2∧4) * 625 ) / 40 ms= 1000ms
iwdg.c文件
#include "iwdg.h"
void IWDG_Init(u8 prer,u16 rlr)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //取消寫保護
IWDG_SetPrescaler( prer ); //設置預分頻系數(shù)
IWDG_SetReload( rlr ); //設置重裝載值
IWDG_ReloadCounter(); //把重裝載值rlr加入計數(shù)器的初值
IWDG_Enable(); //使能看門狗
}