1. 程式人生 > >STM32的獨立看門狗

STM32的獨立看門狗

STM32 內

部自帶了 2 個看門狗:獨立看門狗(IWDG)和視窗看門狗(WWDG)

STM32 的獨立看門狗由內部專門的 40Khz 低速時鐘驅動,即使主時鐘發生故障,它也仍然
有效。這裡需要注意獨立看門狗的時鐘是一個內部 RC 時鐘,所以並不是準確的 40Khz,而是
在 30~60Khz 之間的一個可變化的時鐘,只是我們在估算的時候,以 40Khz 的頻率來計算,看
門狗對時間的要求不是很精確,所以,時鐘有些偏差,都是可以接受的。
首先我們得講解一下看門狗的原理。這個百度百科裡面有很詳細的解釋。我們總結一下:
微控制器系統在外界的干擾下會出現程式跑飛的現象導致出現死迴圈,看門狗電路就是為了避免
這種情況的發生。看門狗的作用就是在一定時間內(通過定時計數器實現)沒有接收喂狗訊號
(表示 MCU 已經掛了),便實現處理器的自動復位重啟(傳送復位訊號)。

                                                                            IWDG_PR 和 IWDG_RLR 暫存器具有防寫功能。要修改這兩個暫存器的值,必須先向
IWDG_KR 暫存器中寫入 0x5555。將其他值寫入這個暫存器將會打亂操作順序,暫存器將重新
被保護。重灌載操作(即寫入 0xAAAA)也會啟動防寫功能。
還有兩個暫存器,一個預分頻暫存器(IWDG_PR),該暫存器用來設定看門狗時鐘的分頻
係數。另一個重灌載暫存器。該暫存器用來儲存重灌載到計數器中的值。該暫存器也是一個 32
位暫存器,但是隻有低 12 位是有效的。
只要對以上三個暫存器進行相應的設定,我們就可以啟動 STM32 的獨立看門狗,啟動過
程可以按如下步驟實現(獨立看門狗相關的庫函式和定義分佈在檔案 stm32f10x_iwdg.h 和
stm32f10x_iwdg.c 中):
1)取消暫存器防寫(向 IWDG_KR 寫入 0X5555)
通過這步,我們取消 IWDG_PR 和 IWDG_RLR 的防寫,使後面可以操作這兩個暫存器,
設定 IWDG_PR 和 IWDG_RLR 的值。這在庫函式中的實現函式是:
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
這個函式非常簡單,顧名思義就是開啟/取消防寫,也就是使能/失能寫許可權。
2)設定獨立看門狗的預分頻係數和重灌載值

設定看門狗的分頻係數的函式是:
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //設定 IWDG 預分頻值
設定看門狗的重灌載值的函式是:
void IWDG_SetReload(uint16_t Reload); //設定 IWDG 重灌載值
設定好看門狗的分頻係數 prer 和重灌載值就可以知道看門狗的喂狗時間(也就是看門狗溢
出時間),該時間的計算方式為:
Tout=((4×2^prer) ×rlr) /40
其中 Tout 為看門狗溢位時間(單位為 ms);prer 為看門狗時鐘預分頻值(IWDG_PR 值),
範圍為 0~7;rlr 為看門狗的重灌載值(IWDG_RLR 的值);
比如我們設定 prer 值為 4,rlr 值為 625,那麼就可以得到 Tout=64×625/40=1000ms,這樣,
看門狗的溢位時間就是 1s,只要你在一秒鐘之內,有一次寫入 0XAAAA 到 IWDG_KR,就不
會導致看門狗復位(當然寫入多次也是可以的)。這裡需要提醒大家的是,看門狗的時鐘不是準
確的 40Khz,所以在喂狗的時候,最好不要太晚了,否則,有可能發生看門狗復位。
3)過載計數值喂狗(向 IWDG_KR 寫入 0XAAAA)
庫函式裡面過載計數值的函式是:
IWDG_ReloadCounter(); //按照 IWDG 重灌載暫存器的值重灌載 IWDG 計數器
通過這句,將使 STM32 重新載入 IWDG_RLR 的值到看門狗計數器裡面。即實現獨立看門
狗的喂狗操作。
4) 啟動看門狗(向 IWDG_KR 寫入 0XCCCC)
庫函式裡面啟動獨立看門狗的函式是:
IWDG_Enable(); //使能 IWDG
通過這句,來啟動 STM32 的看門狗。注意 IWDG 在一旦啟用,就不能再被關閉!想要關
閉,只能重啟,並且重啟之後不能開啟 IWDG,否則問題依舊,所以在這裡提醒大家,如果不
用 IWDG 的話,就不要去開啟它,免得麻煩。
通過上面 4 個步驟,我們就可以啟動 STM32 的看門狗了,使能了看門狗,在程式裡面就
必須間隔一定時間喂狗,否則將導致程式復位。利用這一點,我們本章將通過一個 LED 燈來指
示程式是否重啟,來驗證 STM32 的獨立看門狗。
在配置看門狗後,DS0 將常亮,如果 WK_UP 按鍵按下,就喂狗,只要 WK_UP 不停的按,
看門狗就一直不會產生復位,保持 DS0 的常亮,一旦超過看門狗定溢位時間(Tout)還沒按,
那麼將會導致程式重啟,這將導致 DS0 熄滅一次

wdg.c 裡面的程式碼如下:

#include "wdg.h"
//初始化獨立看門狗
//prer:分頻數: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 計數器
IWDG_Enable(); //④使能 IWDG
}
//喂獨立看門狗
void IWDG_Feed(void)
{
IWDG_ReloadCounter();//reload
}

該程式碼就 2 個函式,void IWDG_Init(u8 prer,u16 rlr)是獨立看門狗初始化函式,就是按照
上面介紹的步驟 1~4 來初始化獨立看門狗的。該函式有 2 個引數,分別用來設定與預分頻數與
重灌暫存器的值的。通過這兩個引數,就可以大概知道看門狗復位的時間週期為多少了。其計
算方式上面有詳細的介紹,這裡不再多說了。
void IWDG_Feed(void)函式,該函式用來喂狗,因為 STM32 的喂狗只需要向鍵值暫存器寫
入 0XAAAA 即可,也就是呼叫 IWDG_ReloadCounter()函式,所以,我們這個函式也是簡單的很。
標頭檔案 wdg.h 的原始碼如下大家可以看下,這裡我們就不列出來了。
接下來我們看看主函式 main 的程式碼。在主程式裡面我們先初始化一下系統程式碼,然後啟動
按鍵輸入和看門狗,在看門狗開啟後馬山點亮 LED0(DS0),並進入死迴圈等待按鍵的輸入,
一旦 WK_UP 有按鍵,則喂狗,否則等待 IWDG 復位的到來。這段程式碼很容易理解,該部分代
碼如下:
int main(void)
{
delay_init();
//延時函式初始化
NVIC_Configuration(); //設定 NVIC 中斷分組 2:2 位搶佔優先順序,2 位響應優先順序
uart_init(9600);
//串列埠初始化波特率為 9600
LED_Init();
//初始化與 LED 連線的硬體介面
KEY_Init(); //按鍵初始化
185
delay_ms(500); //讓人看得到滅
IWDG_Init(4,625); //與分頻數為 64,過載值為 625,溢位時間為 1s
LED0=0;
//點亮 LED0
while(1)
{
if(KEY_Scan(0)==KEY_UP)
{
IWDG_Feed(); //如果 WK_UP 按下,則喂狗
}
delay_ms(10);
};
}