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