STM32的獨立看門(mén)狗
部自帶了 2 個(gè)看門(mén)狗:獨立看門(mén)狗(IWDG)和窗口看門(mén)狗(WWDG)
本文引用地址:http://dyxdggzs.com/article/201611/318191.htmSTM32 的獨立看門(mén)狗由內部專(zhuān)門(mén)的 40Khz 低速時(shí)鐘驅動(dòng),即使主時(shí)鐘發(fā)生故障,它也仍然
有效。這里需要注意獨立看門(mén)狗的時(shí)鐘是一個(gè)內部 RC 時(shí)鐘,所以并不是準確的 40Khz,而是
在 30~60Khz 之間的一個(gè)可變化的時(shí)鐘,只是我們在估算的時(shí)候,以 40Khz 的頻率來(lái)計算,看
門(mén)狗對時(shí)間的要求不是很精確,所以,時(shí)鐘有些偏差,都是可以接受的。
首先我們得講解一下看門(mén)狗的原理。這個(gè)百度百科里面有很詳細的解釋。我們總結一下:
單片機系統在外界的干擾下會(huì )出現程序跑飛的現象導致出現死循環(huán),看門(mén)狗電路就是為了避免
這種情況的發(fā)生。看門(mén)狗的作用就是在一定時(shí)間內(通過(guò)定時(shí)計數器實(shí)現)沒(méi)有接收喂狗信號
(表示 MCU 已經(jīng)掛了),便實(shí)現處理器的自動(dòng)復位重啟(發(fā)送復位信號)。 IWDG_PR 和 IWDG_RLR 寄存器具有寫(xiě)保護功能。要修改這兩個(gè)寄存器的值,必須先向
IWDG_KR 寄存器中寫(xiě)入 0x5555。將其他值寫(xiě)入這個(gè)寄存器將會(huì )打亂操作順序,寄存器將重新
被保護。重裝載操作(即寫(xiě)入 0xAAAA)也會(huì )啟動(dòng)寫(xiě)保護功能。
還有兩個(gè)寄存器,一個(gè)預分頻寄存器(IWDG_PR),該寄存器用來(lái)設置看門(mén)狗時(shí)鐘的分頻
系數。另一個(gè)重裝載寄存器。該寄存器用來(lái)保存重裝載到計數器中的值。該寄存器也是一個(gè) 32
位寄存器,但是只有低 12 位是有效的。
只要對以上三個(gè)寄存器進(jìn)行相應的設置,我們就可以啟動(dòng) STM32 的獨立看門(mén)狗,啟動(dòng)過(guò)
程可以按如下步驟實(shí)現(獨立看門(mén)狗相關(guān)的庫函數和定義分布在文件 stm32f10x_iwdg.h 和
stm32f10x_iwdg.c 中):
1)取消寄存器寫(xiě)保護(向 IWDG_KR 寫(xiě)入 0X5555)
通過(guò)這步,我們取消 IWDG_PR 和 IWDG_RLR 的寫(xiě)保護,使后面可以操作這兩個(gè)寄存器,
設置 IWDG_PR 和 IWDG_RLR 的值。這在庫函數中的實(shí)現函數是:
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
這個(gè)函數非常簡(jiǎn)單,顧名思義就是開(kāi)啟/取消寫(xiě)保護,也就是使能/失能寫(xiě)權限。
2)設置獨立看門(mén)狗的預分頻系數和重裝載值
設置看門(mén)狗的分頻系數的函數是:
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //設置 IWDG 預分頻值
設置看門(mén)狗的重裝載值的函數是:
void IWDG_SetReload(uint16_t Reload); //設置 IWDG 重裝載值
設置好看門(mén)狗的分頻系數 prer 和重裝載值就可以知道看門(mén)狗的喂狗時(shí)間(也就是看門(mén)狗溢
出時(shí)間),該時(shí)間的計算方式為:
Tout=((4×2^prer) ×rlr) /40
其中 Tout 為看門(mén)狗溢出時(shí)間(單位為 ms);prer 為看門(mén)狗時(shí)鐘預分頻值(IWDG_PR 值),
范圍為 0~7;rlr 為看門(mén)狗的重裝載值(IWDG_RLR 的值);
比如我們設定 prer 值為 4,rlr 值為 625,那么就可以得到 Tout=64×625/40=1000ms,這樣,
看門(mén)狗的溢出時(shí)間就是 1s,只要你在一秒鐘之內,有一次寫(xiě)入 0XAAAA 到 IWDG_KR,就不
會(huì )導致看門(mén)狗復位(當然寫(xiě)入多次也是可以的)。這里需要提醒大家的是,看門(mén)狗的時(shí)鐘不是準
確的 40Khz,所以在喂狗的時(shí)候,最好不要太晚了,否則,有可能發(fā)生看門(mén)狗復位。
3)重載計數值喂狗(向 IWDG_KR 寫(xiě)入 0XAAAA)
庫函數里面重載計數值的函數是:
IWDG_ReloadCounter(); //按照 IWDG 重裝載寄存器的值重裝載 IWDG 計數器
通過(guò)這句,將使 STM32 重新加載 IWDG_RLR 的值到看門(mén)狗計數器里面。即實(shí)現獨立看門(mén)
狗的喂狗操作。
4) 啟動(dòng)看門(mén)狗(向 IWDG_KR 寫(xiě)入 0XCCCC)
庫函數里面啟動(dòng)獨立看門(mén)狗的函數是:
IWDG_Enable(); //使能 IWDG
通過(guò)這句,來(lái)啟動(dòng) STM32 的看門(mén)狗。注意 IWDG 在一旦啟用,就不能再被關(guān)閉!想要關(guān)
閉,只能重啟,并且重啟之后不能打開(kāi) IWDG,否則問(wèn)題依舊,所以在這里提醒大家,如果不
用 IWDG 的話(huà),就不要去打開(kāi)它,免得麻煩。
通過(guò)上面 4 個(gè)步驟,我們就可以啟動(dòng) STM32 的看門(mén)狗了,使能了看門(mén)狗,在程序里面就
必須間隔一定時(shí)間喂狗,否則將導致程序復位。利用這一點(diǎn),我們本章將通過(guò)一個(gè) LED 燈來(lái)指
示程序是否重啟,來(lái)驗證 STM32 的獨立看門(mén)狗。
在配置看門(mén)狗后,DS0 將常亮,如果 WK_UP 按鍵按下,就喂狗,只要 WK_UP 不停的按,
看門(mén)狗就一直不會(huì )產(chǎn)生復位,保持 DS0 的常亮,一旦超過(guò)看門(mén)狗定溢出時(shí)間(Tout)還沒(méi)按,
那么將會(huì )導致程序重啟,這將導致 DS0 熄滅一次
wdg.c 里面的代碼如下:
#include "wdg.h"
//初始化獨立看門(mén)狗
//prer:分頻數:0~7(只有低 3 位有效!)
//分頻因子=4*2^prer.但最大值只能是 256!
//rlr:重裝載寄存器值:低 11 位有效.
//時(shí)間計算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
void IWDG_Init(u8 prer,u16 rlr)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //①使能對寄存器 I 寫(xiě)操作
IWDG_SetPrescaler(prer); //②設置 IWDG 預分頻值:設置 IWDG 預分頻值
IWDG_SetReload(rlr); //②設置 IWDG 重裝載值
IWDG_ReloadCounter(); //③按照 IWDG 重裝載寄存器的值重裝載 IWDG 計數器
IWDG_Enable(); //④使能 IWDG
}
//喂獨立看門(mén)狗
void IWDG_Feed(void)
{
IWDG_ReloadCounter();//reload
}
該代碼就 2 個(gè)函數,void IWDG_Init(u8 prer,u16 rlr)是獨立看門(mén)狗初始化函數,就是按照
上面介紹的步驟 1~4 來(lái)初始化獨立看門(mén)狗的。該函數有 2 個(gè)參數,分別用來(lái)設置與預分頻數與
重裝寄存器的值的。通過(guò)這兩個(gè)參數,就可以大概知道看門(mén)狗復位的時(shí)間周期為多少了。其計
算方式上面有詳細的介紹,這里不再多說(shuō)了。
void IWDG_Feed(void)函數,該函數用來(lái)喂狗,因為 STM32 的喂狗只需要向鍵值寄存器寫(xiě)
入 0XAAAA 即可,也就是調用 IWDG_ReloadCounter()函數,所以,我們這個(gè)函數也是簡(jiǎn)單的很。
頭文件 wdg.h 的源碼如下大家可以看下,這里我們就不列出來(lái)了。
接下來(lái)我們看看主函數 main 的代碼。在主程序里面我們先初始化一下系統代碼,然后啟動(dòng)
按鍵輸入和看門(mén)狗,在看門(mén)狗開(kāi)啟后馬山點(diǎn)亮 LED0(DS0),并進(jìn)入死循環(huán)等待按鍵的輸入,
一旦 WK_UP 有按鍵,則喂狗,否則等待 IWDG 復位的到來(lái)。這段代碼很容易理解,該部分代
碼如下:
int main(void)
{
delay_init();
//延時(shí)函數初始化
NVIC_Configuration(); //設置 NVIC 中斷分組 2:2 位搶占優(yōu)先級,2 位響應優(yōu)先級
uart_init(9600);
//串口初始化波特率為 9600
LED_Init();
//初始化與 LED 連接的硬件接口
KEY_Init(); //按鍵初始化
185
delay_ms(500); //讓人看得到滅
IWDG_Init(4,625); //與分頻數為 64,重載值為 625,溢出時(shí)間為 1s
LED0=0;
//點(diǎn)亮 LED0
while(1)
{
if(KEY_Scan(0)==KEY_UP)
{
IWDG_Feed(); //如果 WK_UP 按下,則喂狗
}
delay_ms(10);
};
}
評論