看门狗定时器(WDT, Watch Dog Timer)是单片机的一个组成部分,
它实际上是一个计数器,一般给看门狗计数值,程序开始运行后看门狗开始倒计数。如果程序运行正常,过一段时间CPU应发出指令让看狗复位,重新开始倒计数。如果看门狗减到0就认为程序没有正常工作,强制整个系统复位。
看门狗是一个计数器
启动后开始倒计时
每过一 段时间CPU要重新写入计数值(喂狗)?
CPU能重写计数值,表示程序运行正常
如果程序运行出错或死机,则不能重写计数值
当计数值减到0时,看狗会让整个单片机复位
看门狗的主要目的是监控单片机程序。
如果程序不断喂狗,就证明单片机工作正常。如果程序没有喂狗,就说明单片机出了问题。
看门狗不能检查问题的原因,只能通过复位单片机,让程序重新开始运行。
独立的看门狗是基于一个12位的递减计数器和一个8位的预分频器,它由一个内部独立的40kHz的RC振荡器提供时钟;
因为这个RC振荡器独立于主时钟,所以它可运行于停机和待机模式。它可以被当成看门狗用于在发生问题时复位整个系统,或作为一个自由定时器为应用程序提供超时管理。通过选项字节可以配置成是软件或硬件启动看狗。在调试模式下,计数器可以被冻结。
由图中可看出只要在计数器减到0的之前喂狗,均可使看门狗不复位单片机。
窗口看狗内有一个7位的递减计数器,并可以设置成自由运行。
它可以被当成看门狗用于在发生问题时复位整个系统。它由主时钟驱动,
具有早期预警中断功能;在调试模式下,计数器可以被冻结。
窗口看狗必须在规定的时间范围内喂狗
作用是监控单片机运行时效是否精确,独立看门狗产生复位,说明单片机已经混乱或者死机,产生中断没有意义,也无法处理中断函数的内容,窗口看门狗的主要意义是在单片机正常工作情况下,保持系统的实效性,窗口看门狗复位,只表示系统时效性不足,并不表示系统出错或死机,因为程序可以正常运行,所以可以中断函数进行收尾
所谓窗口的意思便是在窗口范围之间喂狗不会使整个单片机复位,其中0x3F的值是计数器递减下边界固定值,不可改变,在0x40使会产生一个中断给单片机,在一个计数单位的时间内,在中断处理函数中处加入在复位前需要处理的工作或保存数据。
下面是两个看门狗的驱动程序以及定时时间的设定:
看门狗定时时间计算公式:Tout=(预分频值*重装载值)/40 (单位:ms)
当前pre为64,rlr为625,计算得到Tout时间为1秒(大概值)。
#define pre IWDG_Prescaler_64 //分频值范围:4,8,16,32,64,128,256
#define rlr 625 //重装载值范围:0~0xFFF(4095)
void IWDG_Init(void){ //初始化独立看门狗
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //使能对寄存器IWDG_PR和IWDG_RLR的写操作
IWDG_SetPrescaler(pre); //设置IWDG预分频值
IWDG_SetReload(rlr); //设置IWDG重装载值
IWDG_ReloadCounter(); //按照IWDG重装载寄存器的值重装载IWDG计数器
IWDG_Enable(); //使能IWDG
}
void IWDG_Feed(void){ //喂狗程序
IWDG_ReloadCounter();//固件库的喂狗函数
}
窗口看门狗定时时间计算公式:
上窗口超时时间(单位us) = 预分频值×(计数器初始值-窗口值)/APB1时钟频率(单位MHz)
下窗口超时时间(单位us) = 预分频值×(计数器初始值-0x3f)/APB1时钟频率(单位MHz)
#define WWDG_CNT 0x7F //计数器初始值,范围:0x40~0x7F
#define wr 0x50 //窗口值,范围:0x40~0x7F
#define fprer WWDG_Prescaler_8 //预分频值,取值:1,2,4,8
//如上三个值是:0x7f,0x50,8时,上窗口48MS,下窗口64MS。
由前面图中可得到外部晶振提供了8MHZ经分频器分频之后接入了窗口看门狗,因此计时时间便是前面的晶振经分频之后,再乘以计数的值,因为本次是计算的窗口值,因此从开始相减即可得到相应的装载值,计算得到了窗口值对应时间值以及结束的时间值
void WWDG_Init(void);
void WWDG_NVIC_Init(void);
void WWDG_Feed(void);
void WWDG_Init(void){ //初始化窗口看门狗
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // WWDG 时钟使能
WWDG_SetPrescaler(fprer); //设置 IWDG 预分频值
WWDG_SetWindowValue(wr); //设置窗口值
WWDG_Enable(WWDG_CNT); //使能看门狗,设置 counter
WWDG_ClearFlag(); //清除提前唤醒中断标志位
WWDG_NVIC_Init(); //初始化窗口看门狗 NVIC
WWDG_EnableIT(); //开启窗口看门狗中断
}
void WWDG_NVIC_Init(void){ //窗口看门狗中断服务程序(被WWDG_Init调用)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; //WWDG 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占 2 子优先级 3 组 2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //抢占 2,子优先级 3,组 2
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure); //NVIC 初始化
}
void WWDG_Feed(void){ //窗口喂狗程序
WWDG_SetCounter(WWDG_CNT); //固件库的喂狗函数
}
void WWDG_IRQHandler(void){ //窗口看门狗中断处理程序
WWDG_ClearFlag(); //清除提前唤醒中断标志位
//此处加入在复位前需要处理的工作或保存数据
}
另外需要注意窗口看门狗有中断请求信号,因此需要初始化中断,即设定中断控制向量器,为窗口看门狗配置中断、开启中断(先开启窗口看门狗定时器的中断,再开启中断控制器的中断,因为看门狗的中断连接与中断控制器,中断控制器连接于CPU,使用中断控制器,是方便所有的中断,因此需要设置、配置两个中断。)窗口看门狗的中断函数的时间是计数一次所需要的时间,因为在0x40触发中断,在0x3f处复位,在中断处理函数中进行收尾工作,即加入在复位前需要处理的工作或保存数据
图中部分图片出自洋桃电子,仅用于学习目的。