1.独立看门狗IWDG
- 独立看门狗实际上就是一个12位的递减计数器,软件设置一预装载值(不得大于2^12)然后递减,一旦递减到0则单片机复位程序重新执行,想要其不复位就要不断在递减到0之前刷新预装载值(喂狗)
- 一旦独立看门狗开启想要其关闭必须等程序复位并且再次开启时不使用独立看门狗
- 时钟来源是内部自己专用的低速时钟LSI(40Mhz),不需要开启哪个外设时钟。
-
Tout = (4*2^pre) / 40 * rlr
其中Tout为独立看门狗溢出时间,单位是ms。pre是预分频器系数(0-6),rlr 是重装载寄存器的值,公式内的40是独立看门狗的时钟。
2.窗口看门狗WWDG
窗口看门狗实际是个7位的递减计数器,其有上限和下限,下限固定0x40,上限自己定但不可超过0x7f(2^7)。当计数器值超过配置寄存器内的上窗口设置值或者低于下窗口值时喂狗,并且 WDGA 位置 1(即开启窗口看门狗) 将产生一个系统复位信号,促使系统复位。
窗口看门狗有唤醒中断功能, 即在计数递减到下限时会进入唤醒中断。可在这个中断里喂狗,实现自动喂狗,防止复位
时钟来源与APB1。需要开启APB1(36Mhz)时钟
-
Twwdg=(4096×2^WDGTB×(T[5:0]+1)) /PCLK1;
Twwdg为窗口看门狗的超时时间,单位为ms。
PCLK1为APB1的时钟频率,最大36MHz。
iwdg.c
#include "iwdg.h"
void IWDG_Init(u8 pre,u16 rlr)
{
//1*开启寄存器访问(关闭写保护),往键值寄存器IWDG_KR写入0x5555
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
//2*设置IWDG的预分配系数和预装载值
IWDG_SetPrescaler(pre);
IWDG_SetReload(rlr);
//3*重载计数器值(喂狗),往键值寄存器IWDG_KR写入0xaaaa
IWDG_ReloadCounter();
//4*开启独立看门狗,往键值寄存器IWDG_KR写入0xcccc
IWDG_Enable();
}
void Feed_dog() //好看
{
IWDG_ReloadCounter();
}
iwdg.h
#ifndef _iwdg_H
#define _iwdg_H
#include "system.h"
void IWDG_Init(u8 pre,u16 rlr);
void Feed_dog(void);
#endif
main.c
#include "systick.h"
#include "led.h"
#include "system.h"
#include "usart.h"
#include "iwdg.h"
#include "key.h"
//还利用了串口printf重定向
int main()
{
u8 i;
SysTick_Init(72); //系统时钟初始
LED_INIT();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART1_Init(9600);
IWDG_Init(4,800); //Tout = (4*2^pre) / 40 * rlr,单位ms,这是2000ms
KEY_INIT();
led2 = 1; //D2熄灭
printf("系统复位\r\n");
while(1)
{
i++;
if(KEY_Scan(0)==KEY_UP)
{
Feed_dog();
led2=0;
printf("喂狗\r\n");
}
if(i%20==0)
{
led1=!led1;
}
delay_ms(10);
}
}
wwdg.c
#include "wwdg.h"
void WWDG_Init()
{
NVIC_InitTypeDef NVIC_InitStructure;
//1*开启APB1时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
//2*设置上限值和分频系数
WWDG_SetWindowValue(0x5f);
WWDG_SetPrescaler(WWDG_Prescaler_8);
//3*配置优先级并开启WWDG中断
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);
//4*设置计数器初始值并使能中断
WWDG_Enable(0x7f);//使能窗口看门狗并初始化计数器值
WWDG_ClearFlag(); //清除窗口看门狗状态标志(这一句必须加上,否则进入不了中断)
WWDG_EnableIT();//开启中断
}
//5*唤醒中断函数
void WWDG_IRQHandler()
{
WWDG_SetCounter(0x7f);
led2=!led2;
WWDG_ClearFlag();//清除窗口看门狗状态标志
}
wwdg.h
#ifndef _wwdg_H
#define _wwdg_H
#include "system.h"
void WWDG_Init(void);
#endif
main.c
#include "systick.h"
#include "led.h"
#include "system.h"
#include "key.h"
#include "wwdg.h"
int main()
{
SysTick_Init(72); //系统时钟初始
LED_INIT();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
led1 = 0;
delay_ms(500);//每次程序开始D1都亮500ms后熄
WWDG_Init();
while(1)
{
led1=1;
}
}