基於STM32F103ZET6實現看門狗(獨立與窗口)

STM32開發板自帶獨立(IWDG)與窗口(WWDG)看門狗
1(獨立看門狗):實現按鍵喂狗,LED來指示覆位狀態!
2(窗口看門狗):使用看門狗中斷喂狗,LDE指示狀態!

1(獨立看門狗)

獨立看門狗有內部專門的低速時鐘提供時鐘驅動,大概40KHz,範圍大概在30~60KHz範圍內,單片機系統在外界的干擾下會出現程序跑飛的現象導致出現死循環,看門狗電路就是爲了避免這種情況的發生。看門狗的作用就是在一定時間內(通過定時計數器實現)沒有接收喂狗信號(表示 MCU 已經掛了),便實現處理器的自動復位重啓(發送復位信號)。
IWDG_KR 寫入 0X5555可以使能寫權限,否則無法修改寄存器值分頻值重裝載值,具體操作爲:
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
設置獨立看門狗的預分頻係數重裝載值可通過這兩個函數寫入:
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);//預分頻
void IWDG_SetReload(uint16_t Reload);//重裝載值
獨立看門狗的溢出時間我們可以通過這個公式計算:
T=((4×2^Prescaler) ×Reload) /40
便捷:定時1s,Prescaler值:4,Reload值:625
解釋:也就是說,在1s內喂狗,就可以實現不復位!

注意:

這裏需要提醒大家的是,看門狗的時鐘不是準確的 40Khz,所以在喂狗的時候,最好不要太晚了,否則,有可能發生看門狗復位。

重載計數值喂狗(向 IWDG_KR 寄存器寫入 0XAAAA)
IWDG_ReloadCounter()
大家可能會混淆兩個概念!
設定重裝載值:設定一個值作爲重裝載值的大小
重載計數值喂狗:讓STM32開發板中的重裝載值重新寫到計數器中,從而實現計數器值更新,達到喂狗目的!
啓動看門狗(向 IWDG_KR 寫入 0XCCCC):
IWDG_Enable();
如果不用獨立看門狗的話,就不要去打開它,免得麻煩。
獨立看門狗頭文件iwdg.h
#ifndef IWDG_H
#define IWDG_H
void iwdg_init(void);
void feed_dog(void);
#endif
獨立看門狗源文件iwdg.c
#include “iwdg.h”
#include “sys.h”
void iwdg_init(void)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(4);
IWDG_SetReload(625);
IWDG_ReloadCounter();
IWDG_Enable();
}
void feed_dog(void)
{
IWDG_ReloadCounter();
}
獨立看門狗主函數源文件main.c
#include “led.h”
#include “delay.h”
#include “key.h”
#include “sys.h”
#include “iwdg.h”
int main(void)
{
delay_init();
KEY_Init();
LED_Init();
iwdg_init();
delay_ms(500);
LED0=0;
while(1)
{
if(KEY_Scan(0)==KEY0_PRES)
{
feed_dog();
}
delay_ms(10);
}
}
都比較簡單就不贅述了!
實驗現象:只要按鍵及時喂狗,led將保持常亮!

2(窗口看門狗)

窗口看門狗(WWDG)通常被用來監測由外部干擾或不可預見的邏輯條件造成的應用程序背離正常的運行序列而產生的軟件故障。比獨立看門狗更加精準!
我們以圖在說明該配置哪些:
在這裏插入圖片描述
所謂窗口看門狗,就是有個窗口一樣的上下限,我們必須在上下線值之間進行喂狗纔不會導致復位!
圖中T[6:0]就是 WWDG_CR寄存器 的低七位,W[6:0]即是 寄存器WWDG->CFR 的低七位。T[6:0]就是窗口看門狗的計數器,而 W[6:0]則是窗口看門狗的上窗口,下窗口值是固定的(0X40)。
其中W[6:0]是可以用戶自行定義的。但是一定要確保窗口值大於 0X40,否則窗口就不存在了。
超時的最大時間計算公式爲:
Twwdg=(4096×2^預分頻數×(T[5:0]+1))/APB1時鐘頻率;
例子:如果說我們的APB1時鐘爲36M,可以通過預分頻數得知超時時間:
在這裏插入圖片描述
復位的兩種情況:
(1)當窗口看門狗的計數器在上窗口值之外被刷新。
(2)低於下窗口值會產生復位。
那麼如何設置值呢?
控制寄存器
在這裏插入圖片描述
低八位有效,0-6控制T6值,當值從 0X40 變 爲 0X3F 的時候,將產生看門狗復位。第八位是控制看門狗的激活位。
配置寄存器:
在這裏插入圖片描述
低十位有效,第十位爲提前喚醒中斷標誌位,注意這裏在進入中斷後,必 須在不大於 1 個窗口看門狗計數週期的時間(在 APB1頻率爲 36M 且 預分頻爲 0 的條件下,該時間爲 113us)內重新寫控制寄存器,否則,看門狗將產生復位!W6用戶寫入數據位。
狀態寄存器
該寄存器用來記錄當前是否有提前喚醒的標誌。該寄存器僅有位 0 有效,其他都是保留位。當計數器值達到 40h 時,此位由硬件置 1。它必須通過軟件寫 0 來清除。對此位寫 1 無效。即使中斷未被使能,在計數器的值達到 0X40的時候,此位也會被置 1。
重要的三個寄存器配置項就只有這些
(1)使能 WWDG 時鐘
窗口看門狗使用的是PCLOCK1內部時鐘,所以需要使能時鐘:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
(2)設置窗口值和分頻數
窗口值設置:void WWDG_SetWindowValue(uint8_t WindowValue);
分頻數設置:void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
(3)開啓 WWDG 中斷並分組
開啓WWDG_EnableIT();中斷從初始化NVIC_Init();
(4)設置計數器初始值並使能看門狗
**void WWDG_Enable(uint8_t Counter);**這個函數及設置了計數器初值,又完成了看門狗使能
(5)中斷服務函數
**void WWDG_IRQHandler(void);**不可更改函數名
窗口看門狗頭文件wwdg.h
#ifndef WWDG_H
#define WWDG_H
#include “sys.h”
extern void wwdg_init(u32,u8,u8);
#endif
窗口看門狗源文件wwdg.c
#include “wwdg.h”
#include “sys.h”
#include “led.h”
void wwdg_init(u32 prer,u8 value,u8 in)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
WWDG_SetPrescaler( prer);
WWDG_SetWindowValue(value);
WWDG_Enable(in);
WWDG_ClearFlag();
WWDG_EnableIT();
}
void WWDG_IRQHandler(void)
{
WWDG_SetCounter(0x7F);
WWDG_ClearFlag();
LED1=!LED1;
}
窗口看門狗主函數main.c
#include “led.h”
#include “delay.h”
#include “sys.h”
#include “wwdg.h”
int main(void)
{
delay_init();
LED_Init();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
LED0=0;
delay_ms(300);
wwdg_init(WWDG_Prescaler_8,0x5F,0x7F);
while(1)
{
LED0=1;
}
}

總結

本章主要是熟悉配置流程,有些細節問題就是初始化函數的配置順序,主函數的開門狗初始化應該是在哪個位置都是我們需要考慮的,爲什麼會出現這樣的順序,這些問題想明白了,以後自己寫程序的時候便得心應手!
小編第一次寫的時候出現了初始化地方不合適,導致實驗結果千差萬別,一直沒找到原因。
只有努力與實踐共存,才能進步!希望這篇文章對大家有所幫助!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章