STM32(二十)看门狗
一、独立看门狗
1、简介
独立看门狗用通俗一点的话来解释就是-一个12 位的递减计数器,当计数器的值从某个值一直减到0的时候,系统就会产生一个复位信号,即IWDG_ RESET.如果在计数没减到0之前,刷新了计数器的值的话,那么就不会产生复位信号,这个动作就是我们经常说的喂狗。看门狗功能由VDD电压域供电,在停止模式和待机模式下仍能工作。独立看门狗 (IWDG) 由其专用低速时钟 (LSI) 驱动,因此即便在主时钟发生故障时仍然保持工作状态。窗口看门狗 (WWDG) 时钟由 APB1 时钟经预分频后提供,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作。
2、作用
独立看门狗一般用来检测和解决由程序引起的故障,比如一个程序正常运行的时间是50ms,在运行完这个段程序之后紧接着进行喂狗,我们设置独立看门狗的定时溢出时间为60ms,比我们需要监控的程序50ms多-一点,如果超过60ms还没有喂狗,那就说明我们监控的程序出故障了,跑飞了,那么就会产生系统复位,让程序重新运行。
3、IWDG功能说明
当通过对关键字寄存器(IWDG_ _KR) 写入值0xCCCC启动独立看门狗时,计数器开始从复位值0xFFF递减计数。当计数器计数到终值(0x000)时会产生一个复位信号(IWDG复位)。任何时候将关键字0xAAAA写到IWWDG__KR寄存器中,IWDG__RLR的值就会被重载到计数器,从而避免产生看门狗复位。
4、硬件看门狗
如果通过器件选项位使能“硬件看门狗”功能,上电时将自动使能看门狗;如果在计数器计数结束前,若软件没有向关键字寄存器写入相应的值,则系统会产生复位。
5、寄存器访问保护
IWDG_ PR和IWDG_ _RLR 寄存器具有写访问保护。若要修改寄存器,必须首先对IWDG_ _KR寄存器写入代码0x5555。而写入其他值则会破坏该序列,从而使寄存器访问保护再次生效。这意味着重装载操作(即写入0xAAAA)也会启动写保护功能。
状态寄存器指示预分频值和递减计数器是否正在被更新。
6、代码编写
(1)初始化看门狗
void Iwdg_Init(void)
{
IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_128); // 32KHZ/128= 250HZ 设置预分频器
IWDG_SetReload(500); //设置重装载值,如果计数器从500减到0之前没有喂狗,则会reset, 时钟频率为250hz,则500减到0为2s的时间
IWDG_Enable(); //是能独立看门狗
}
(2)喂狗
我们设置LED闪烁,延时1秒后喂狗,计数器没有减到0,程序运行超过两秒,则程序正常执行,若延时超过2s,则重装载值减到0,会进行reset复位。
Iwdg_Init();
printf("hello Iwdg\r\n");
while(1)
{
PFout(9)=~PFout(9);
delay_s(1);
IWDG_ReloadCounter(); //喂狗
}
二、窗口看门狗
1、简介
窗口看门狗跟独立看门狗一样,也是一个递减计数器不断的往下递减计数,当减到一个固定值0X40 时还不喂狗的话,产生复位,这个值叫窗口的下限,是固定的值,不能改变。这个是跟独立看门狗类似的地方,不同的地方是窗口看门狗的计数器的值在减到某一个数之前喂狗的话也会产生复位,这个值叫窗口的上限,上限值由用户独立设置。窗口看门狗计数器的值必须在上窗口和下窗口之间才可以喂狗,这就是窗口看门狗中窗口两个字的含义。
2、作用
WWDG一般被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。比如一个程序段正常运行的时间是50ms,在运行完这个段程序之后紧接着进行喂狗,如果在规定的时间窗口内还没有喂狗,那就说明我们监控的程序出故障了,跑飞了,那么就会产生系统复位,让程序重新运行。
3、WWDG主要特性
(1)可编程的自由运行递减计数器
(2)复位条件
- 当递减计数器值小于0x40时复位(如果看门狗已激活)
- 在窗口之外重载递减计数器时复位(如果看门狗已激活) ( 请参见图200)
(3)提前唤醒中断(EWI):当递减计数器等于0x40时触发(如果已使能且看门狗已激活)
4、代码编写
当递减计数器等于0x40时触发中断进行喂狗(如果已使能且看门狗已激活)
void Wwdg_Init(void)
{
NVIC_InitTypeDef NVIC_InitStruct;
//初始化硬件时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);
//配置分频
//窗口看门狗的硬件时钟=42MHz/4096/8 = 1281Hz
//每减一个数时间 T= 1/F = 1000000/1281 = 780.6us
WWDG_SetPrescaler(WWDG_Prescaler_8);
//配置窗口看门狗的窗口值
WWDG_SetWindowValue(80);
//配置计数值127,然后启动窗口看门狗
WWDG_Enable(127);
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x1;//抢占优先级 0-3
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x1;//响应占优先级 0-3
NVIC_InitStruct.NVIC_IRQChannel = WWDG_IRQn;//中断向量号 WWDG
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
NVIC_Init(&NVIC_InitStruct);
//清空标志位
WWDG_ClearFlag();
//提前唤醒中断
WWDG_EnableIT();
}
//中断服务函数 在CORE里面的start_stm32f40_41xxx.s这个汇编里面找
void WWDG_IRQHandler(void)//WWDG
{
u8 i=0;
if(WWDG_GetFlagStatus() == SET)
{
//增加喂狗
WWDG_SetCounter(127);
PFout(8)^=1;
//清空标志位
WWDG_ClearFlag();
}
}