實驗現象:
這是基于窗口看門狗的實驗,剛開始初始化時LED2閃了一下,后來就保持亮著,而LED1卻不斷的在閃爍,這是因為中斷函數運行的緣故。
實驗平臺:
基于STM32F103C8T6的彩屏開發板
實驗步驟:
1)使能WWDG 時鐘
WWDG 不同于IWDG,IWDG 有自己獨立的40Khz 時鐘,不存在使能問題。而WWDG
使用的是PCLK1 的時鐘,需要先使能時鐘。
2)設置WWDG_CFR 和WWDG_CR 兩個寄存器
在時鐘使能完后,我們設置 WWDG 的CFR 和CR 兩個寄存器,對WWDG 進行配置。包
括使能窗口看門狗、開啟中斷、設置計數器的初始值、設置窗口值并設置分頻數WDGTB 等。
3)開啟WWDG 中斷并分組
在設置完了 WWDG 后,需要配置該中斷的分組及使能。這點通過我們之前所編寫的
MY_NVIC_Init 函數實現就可以了。
4)編寫中斷服務函數
在最后,還是要編寫窗口看門狗的中斷服務函數,通過該函數來喂狗,喂狗要快,否則當
窗口看門狗計數器值減到0X3F 的時候,就會引起軟復位了。在終端服務函數里面也要將狀態
寄存器的EWIF 位清空。
實驗代碼:
wwdg.h
#ifndef WWDG_H
#define WWDG_H
void WWDG_Init(u8,u8,u8);//聲明看門狗的初始化函數
void WWDG_Reset(void);//重新給遞減計數器賦值
#endif
wwdg.c
#include"common.h"
#include"wwdg.h"
#include"led.h"
//tr :T[6:0],用于存儲計數器的值
//wr :W[6:0],用于存儲窗口值
//fprer:窗口看門狗的實際設置
u8 WWDG_CNT=0x7f;
void WWDG_Init(u8 tr ,u8 wr,u8 fprer )
{
RCC->APB1ENR|=1<<11; //開啟窗口看門狗的時鐘
WWDG_CNT=tr&WWDG_CNT; //主要是為了防止用戶寫錯數據造成巨大偏差
WWDG->CFR|=fprer<<7; //預分頻時基設置
WWDG->CFR|=1<<9; //開啟提前喚醒中斷
WWDG->CFR&=0xff8; //保證上面兩個設置的正確性
WWDG->CFR|=wr; //給遞減計數器賦初值
WWDG->CR|=WWDG_CNT; //給窗口寄存器賦值
WWDG->CR|=1<<7; //啟用看門狗
MY_NVIC_Init(2,3,WWDG_IRQChannel,2);//設置中斷的分組和優先級
}
//重新給遞減計數器賦值
void WWDG_Reset(void)
{
WWDG->CR=0x7f;
}
//中斷服務函數
void WWDG_IRQHandler(void)
{
u8 tr,wr;
tr=(WWDG->CR&0x7f);//讀取窗口寄存器的值
wr=(WWDG->CFR&0x7f);//讀取遞減計數器的值
if(tr<wr)//當遞減計數器的值小于窗口的才能給遞減計數器重新復制,不然會復位的
WWDG_Reset();
WWDG->SR=0x0; //去除提前喚醒中斷標志
LED1=!LED1; //LED反向
}
第一個函數void WWDG_Init(u8 tr,u8 wr,u8 fprer)用來
設置WWDG的初始化值。包括看門狗計數器的值和看門狗比較值等。注意到這里有個全局變量WWDG_CNT,該變量用來保存最初設置WWDG_CR計數器的值。在后續的中斷服務函數里面,就又把該數值放回到WWDG_CR上。
WWDG_Set_Counter 函數比較簡單,就是用來復位窗口看門狗的計數器值的。該函數很簡
單。
最后中斷服務函數里面,一定要先比較窗口計數器的值是否小于看門狗的窗口值,如果不
小于,則不要修改,如果小于,才能進行修改。我們通過LED1 不停的取反,來觀測中斷服務函
數的執行了狀況。我們再把這幾個函數名加入到頭函數里面去,以方便其他文件調用。
主函數
#include<stm32f10x_lib.h>
#include"common.h"
#include"led.h"
#include"key.h"
#include"wwdg.h"
int main(void)
{
Stm32_Clock_Init(9); //系統時鐘設置
delay_init(72); //延時初始化
LED_Init(); //LED初始化
KEY_Init(); //按鍵的初始化
WWDG_Init(0x7f,0x5f,3);
LED2=0;
delay_ms(300);
while(1)
{
LED2=1;
}
}
|