1.WDG(Watchdog)看门狗
1.窗口看门狗(IWDG)与独立看门狗(WWDG)的简述
1.看门狗可以监控程序的运行状态。当程序因为设计漏洞,硬件古装,电磁干扰等原因,出现卡死或者跑飞的现象时。看门狗能及时复位程序,避免程序陷入长时间的罢工状态,保证系统的可靠性和安全性。
2.看门狗本质上是一个定时器,当指定时间范围内,程序没有执行喂狗(充值定时器)操作时,看门狗硬件电路自动产生复位信号。
3.stm32内置两个看门狗
独立看门狗(IWDG):独立工作,对时间精度要求低。
窗口看门狗(WWDG):要求看门狗在精确计时窗口起作用。
4.看门狗的时钟源
LSI低速内部时钟(40khz左右)供给独立看门狗(IWDG)。
APB1的PCLK1供给窗口看门狗(WWDG)。
2.IWDG独立看门狗的专栏
1.看门狗运行原理:
在键寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值
0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。
无论何时,只要在键寄存器IWDG_KR中写入0xAAAA, IWDG_RLR中的值就会被重新加载到
计数器,从而避免产生看门狗复位。
2.看门狗内部寄存器的访问保护
IWDG_PR和IWDG_RLR寄 存 器 具 有 写 保 护 功 能 。 要 修 改 这 两 个 寄 存 器 的 值 , 必 须 先 向IWDG_KR寄存器中写入0x5555。以不同的值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入0xAAAA)也会启动写保护功能。状态寄存器指示预分频值和递减计数器是否正在被更新。
3.IWDG独立看门狗内部框图
1.PR 预分频寄存器
PR寄存器就是对LSI内部低速时钟信号进行分频,以下是详细图解
例如:预分频系数为16,对应一个计时周期1638.4ms,且此时看门狗从0xfff减到0x000的一个周期。
如果此时需要一个计数周期为1000ms,对应的预分频系数也是16,那么看门狗此时的计数值为x
有下列关系 1638.4/0xfff = 1000/x 进而解得x为2500。
2.KR 键寄存器
键寄存器有三个功能:
1.写入0xAAAA表示对计数值进行重装载。例如:计数从0x123计到0x23时,对KR寄存器输入0xAAAA,则此时重装载计数值为0x123(从0x123重新开始计数)。
2.写入0x5555表示允许访问看门狗的PR与RLR寄存器,对预分频值和重装载值进行设置。
3.写入0xCCCC时,开启看门狗工作。
3.RLR 重装载寄存器(窗口看门狗不具有)
当在KR 键寄存器中输入0x5555时可以进行对RLR 重装载寄存器的重装载值进行设置。
4.SR 状态寄存器
讲解RVU位看门狗计数器重装值,在看门狗运行时(从自动重装寄存器的值递减到0x000时的过程)此时在0x123时对计数器的值进行重装。继而在重装前(RVU位为0),重装时(RVU位被置1)重装时长大概为1/40000 x 5 = 1ms,重装结束后RVU位被置0。同理PVU位。
5.示例程序的讲解
int main(void)
{
Key_Init();
OLED_Init();
Iwdg_Init();
while (1)
{
IWDG_ReloadCounter();//看门狗计数器重装,此时只有1msRVU被置为1。之后RVU是0。
Delay_ms(2);//通过去除延时方可判断RVU的状态
while(IWDG_GetFlagStatus(IWDG_FLAG_RVU)==SET)//RVU为1时进入
{
OLED_ShowString(1,1,"yes ,i am free");
}
}
}
3.WWDG窗口看门狗专栏
1.窗口看门狗原理
窗口看门狗通常被用来监测,由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运
行序列而产生的软件故障。除非递减计数器的值在T6位变成0前被刷新,看门狗电路在达到预置
的时间周期时,会产生一个MCU复位。在递减计数器达到窗口寄存器数值之前,如果7位的递减
计数器数值(在控制寄存器中)被刷新, 那么也将产生一个MCU复位。这表明递减计数器需要在
一个有限的时间窗口中被刷新。
WWDG的计数值:T[6:0]计数值,W[6:0]比较值。W[6:0]比较值范围[0x40,0x80),T[6:0]计数值范围为[0x3f,0x7f]最多可以减到0x3f但是在0x3f(0011 1111)时系统产生复位,所以写入时的范围为[0x40,0x7F]。
1.递减计数器T[6:0]的值小于0x40(0100 0000)时,WWDG产生复位。在0x3f(0011 1111)产生复位,因为此时T6位被减为0了。详细看WWDG节的原理图。
2.递减计数器T[6:0]在窗口W[6:0]外被重新装载时,WWDG产生复位。就是当计数值还大于比较值,计数器被重新装载产生复位(不能过早喂狗)。
3.递减计数器T[6:0]等于0x40时产生早期唤醒中断(EWI),用于重新装载计数值以避免WWDG产生复位。(在递减到0x3F时会产生复位信号,继而产生复位。所以在复位的前一时刻,产生EWI中断提醒CPU你要不要做一点事)死前中断。可以在中断中进行喂狗防止复位。
4.定期写入WWDG_CR寄存器(喂狗)以避免WWDG复位。(在计数值小于等于比较值时写入)
与门
或门(注意圆圈 “取反“)
1.PCLK1(APB1)窗口看门狗时钟电路:
最大36MHZ,给窗口看门狗提供时钟。
2.看门狗预分频器 WDGTB对输入的时钟信号36mhz进行分频
EWI相当于一个看门狗的中断使能位,由硬件复位 0。
比较值W[6:0]从第零位到第六位。与CNT计数器的值进行比较。
3.看门狗控制寄存器 CR
CR寄存器装载这看门狗计数器的值CNT,其中T6位默认为1,当T6位由1减到0时。产生一个复位信号经过取反被或门转换得到1,进入与门产生复位。
WDGA为允许复位位(激活位)激活与门并于另一支路的复位信号相结合产生复位信号。
4. 状态寄存器 SR
状态寄存器相当于:
1.在计数值达到比较值时会被硬件置1(无论中断是否使能),通过软件复位 0。
2.或者最小复位值时。0x40为100 0000再减下去就变成011 1111,此时T6为变为0,经过取反再经过或门和与门产生复位信号。 如果中断看门狗相应中断在NVIC中使能则产生中断信号。
2.使用原理讲解
1.WDGA激活位用来激活复位是否实现。WDGA为1允许窗口看门狗进行复位,WDGA为0不允许复位。
2.当对WWDG_CR递减计数器进行写入时,使能比较(使能计数器与待定值进行比较)。使能比较器。当T6:0 > W 6:0 时,是喂狗(给WWDG_CR写入重装值)过早了,此时发生复位。
3.示例代码:
int main(void)
{
OLED_Init();
WWDG_Init();
while(1)
{
}
}
void WWDG_IRQHandler(void)
{
if(WWDG_GetFlagStatus()==SET)
{
OLED_ShowString(1,1," yes, i am free");
WWDG_ClearFlag();
}
Delay_ms(500);
WWDG_SetCounter(0x7f);//喂狗
}
void WWDG_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);
NVIC_InitTypeDef WWDG_IT;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
WWDG_IT.NVIC_IRQChannel = WWDG_IRQn;
WWDG_IT.NVIC_IRQChannelCmd = ENABLE;
WWDG_IT.NVIC_IRQChannelPreemptionPriority = 1;
WWDG_IT.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&WWDG_IT);
while(WWDG_GetFlagStatus()==SET)
{
WWDG_ClearFlag();
}
WWDG_EnableIT();
WWDG_SetPrescaler(WWDG_Prescaler_4);
WWDG_SetWindowValue(0x70);//比较寄存器的值10ms
WWDG_SetCounter(0x7f);
WWDG_Enable(0x7f);
}
2.IWDG独立看门狗的头文件函数解读
1. void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);
独立看门狗的写使能,在对PR(预分频寄存器),RLR(重装载寄存器)进行操作时,需要关闭写保护。在KR(键寄存器中)详细看前面标题相关。
相关参数:
IWDG_WriteAccess_Enable//写使能。
IWDG_WriteAccess_Disable//写失能。
应用前提:
WDG_PR和IWDG_RLR寄 存 器 具 有 写 保 护 功 能 。 要 修 改 这 两 个 寄 存 器 的 值 , 必 须 先 向IWDG_KR寄存器中写入0x5555。以不同的值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护(每次在对PR RLR寄存器进行操作前都要重新关闭写保护)。重装载操作(即写入0xAAAA)也会启动写保护功能。
2.void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);
设置预分频器的值,对输入的LSI时钟信号大概40Khz进行分频。这里说大概40khz的原因内部RC电路产生的信号受到环境因素的影响输出不稳定,就是受到温度等的影响。
相关参数:
这里示例只计算一个:
进行8分频时:
一秒LSI输入40khz的时钟信号,那么发生1hz信号需要1/40000秒=0.000025秒,进行8分频后一秒的输入频率为40000/8=5000hz,发生一个频率的脉冲信号需要1/5000=0.0002秒。看门狗减一个数走一个脉冲。方能计算出时间。
3.void IWDG_SetReload(uint16_t Reload);
设置自动重装RLR寄存器的值范围0x000到0xfff间。
4.void IWDG_ReloadCounter(void)
对RLR寄存器进行重装载,注意此时重装载时会自动开启PR寄存器与RLR寄存器的写保护。
5.void IWDG_Enable(void);
此时看门狗开始工作。注意此时会自动开启PR寄存器与RLR寄存器的写保护。
6.FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);
这个FlagStatus是一个枚举类型:
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
对上面这行代码进行翻译一下:typedef 类型重定义
定义枚举变量enum{RESET = 0, SET = !RESET}
枚举变量不同的名字 FlagStatus, ITStatus。
就是将FlagStatus作为一个新的类型名,这个类型所定义的函数只有两个返回值SET或者RESET。
相关参数:IWDG_FLAG_PVU 预分频器值的更新标志位
IWDG_FLAG_RVU 计数器值的更新标志位
函数作用:重装载值的更新实际上就是计数器值的更新,当发生重装(计数器进行更新时)时,重装需要5个40khz时钟周期大概是1ms,所以在这一ms会将自动重装标志位置为1,这个函数就是检查这个标志位是不是1。当对预分频器的值进行改变时,重新设定预分频器的值,会发生一个1ms的标志位的变化。此时对这个标志位进行检测。
3.WWDG窗口看门狗的头文件函数解读
注意:WWDG没有自动重装计数器,直接对计数器进行写操作就行。
1.void WWDG_DeInit(void);
函数作用:这个函数的目的是将看门狗相关的所有寄存器和配置重置为它们的默认状态或上电复位状态。
函数通常会执行以下操作:
- 关闭看门狗。WDGA位被置为0
- 重置看门狗的所有配置寄存器,包括预分频寄存器、重装载寄存器、控制寄存器等。
- 清除任何与看门狗相关的中断标志。
2.void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
函数作用:设置WWDG的预分频器的值。
输入参数:
WWDG_Prescaler_1: (PCLK1/4096)/1
WWDG_Prescaler_2: (PCLK1/4096)/2
WWDG_Prescaler_4: (PCLK1/4096)/4
WWDG_Prescaler_8: (PCLK1/4096)/8
PCLK1时钟:
这里只计算一个WWDG_Prescaler_2,经过分频后一秒产生的脉冲信号频率:(36000000/4096)/2=4394.53125hz。一个脉冲需要的时间1/4394.53125=0.00022755555秒
在通过计算你可以得到看门狗的监控时间。
注意:
1.WWDG窗口看门狗所能计时的最大时间从0x80减到0x3f复位,但在0x40时会产生中断提醒一下CPU马上要复位了,要不要做点啥。(这个中断可以启用也可以不启用)可以在这个中断中执行喂狗的操作。
2.但喂狗时间也是限制的不能过早喂狗不然会产生复位信号。喂狗时间必须,计数值小于等于窗口值才可以。窗口值也叫比较值。
3.void WWDG_SetWindowValue(uint8_t WindowValue)
函数功能:设置窗口值,最小喂狗值。
参数范围:小于0x80(1000 000),你看一下比较器的结构发现窗口值的第一位是默认不进行比较的。所以真正有效的比较范围为后七位。所以给定0x80(1000 0000)导致计数值恒大于比较值。所以无论何时喂狗都会产生复位,不喂狗系统会自动复位。
其次T6位也是一个标志位,当系统从0x7f(0111 1111)减到0x40(0100 0000)时,再来一个时钟脉冲从0x40(0100 0000)减到0x3f(0011 1111)T6为由1变为0根据内部电路关系,系统将自动产生复位信号
4.void WWDG_EnableIT(void);
函数功能:开启中断使能,当计数值减到0x40时发生一个中断(EWI)。在这个中断函数中处理一些复位前的事情,比如喂狗,关闭危险外设等。
5.void WWDG_SetCounter(uint8_t Counter);
函数功能:设置计数值
参数范围:计数值设置WDGA为激活位,当只有开启WDGA时才能允许看门狗复位。所以WDGA位单独开启,此时只需要给后七位计数值就行。所以参数范围0x7F到0x3F。
6.FlagStatus WWDG_GetFlagStatus(void);
函数功能:获取标志位(中断或者复位前的标志位)
7.void WWDG_ClearFlag(void);
函数功能:清除在0x40时产生的标志位。