大家好,又见面了,我是你们的朋友全栈君。
本章介绍STM32F4**系列芯片的看门狗模块内容
STM32F4**系列芯片具有两个嵌入式看门狗外设,具有安全性高、定时准确及使用灵活的优点。两个看门狗外设(独立和窗口)均可用于检测并解决由软件错误导致的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看门狗)或产生系统复位。 独立看门狗 (IWDG) 由其专用低速时钟 (LSI) 驱动,因此即便在主时钟发生故障时仍然保持工作状态。窗口看门狗 (WWDG) 时钟由 APB1 时钟经预分频后提供,通过可配置的时间窗 口来检测应用程序非正常的过迟或过早的操作。 IWDG 最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时 间精度要求较低的场合。WWDG 最适合那些要求看门狗在精确计时窗口起作用的应用程序。
1. 独立看门狗(IWDG)
1.1 IWDG 主要特性
● 自由运行递减计数器 ● 时钟由独立 RC 振荡器提供(可在待机和停止模式下运行),默认32Khz,内部RC时钟,时钟周期并不准确,可在15~47Khz范围内变化。 ● 当递减计数器值达到 0x000 时产生复位(如果看门狗已激活)
1.2 IWDG 寄存器
1.2.1 关键字寄存器 (IWDG_KR)
1.2.2 预分频器寄存器 (IWDG_PR)
1.2.3 重载寄存器 (IWDG_RLR)
1.2.4 状态寄存器 (IWDG_SR)
1.3 喂狗时间计算
Tout=((4×2^prer) ×rlr) /32,其中Tout为看门狗溢出时间(单位为ms);prer为看门狗时钟预分频值(IWDG_PR值),范围为0~7;rlr为看门狗的重装载值(IWDG_RLR的值)。比如我们设定prer值为4(4代表的是64分频),rlr值为500,那么就可以得到Tout=64×500/32=1000ms,这样,看门狗的溢出时间就是1s,只要在一秒钟之内,有一次写入0XAAAA到IWDG_KR,就不会导致看门狗复位(当然写入多次也是可以的)。需要注意的是,看门狗的时钟不是准确的32Khz,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。
1.4 实验代码
实验板在载入程序代码后,因为没有喂狗,每隔约1s左右时间会复位,造成LED灯闪烁,若按下KEY_UP按键,会触发喂狗程序,连续按下后则不会再复位。
代码语言:javascript复制 1 //初始化独立看门狗
2 //prer:分频数:0~7(只有低3位有效!)
3 //rlr:自动重装载值,0~0XFFF.
4 //分频因子=4*2^prer.但最大值只能是256!
5 //rlr:重装载寄存器值:低11位有效.
6 //时间计算(大概):Tout=((4*2^prer)*rlr)/32 (ms).
7 void IWDG_Init(u8 prer,u16 rlr)
8 {
9 IWDG->KR=0X5555;//使能对IWDG->PR和IWDG->RLR的写
10 IWDG->PR=prer; //设置分频系数
11 IWDG->RLR=rlr; //从加载寄存器 IWDG->RLR
12 IWDG->KR=0XAAAA;//reload
13 IWDG->KR=0XCCCC;//使能看门狗
14 }
15
16 //喂独立看门狗
17 void IWDG_Feed(void)
18 {
19 IWDG->KR=0XAAAA;//reload
20 }
21
22 int main(void)
23 {
24 Stm32_Clock_Init(360,25,2,8);//设置时钟,180Mhz
25 delay_init(180); //初始化延时函数
26 LED_Init(); //初始化与LED连接的硬件接口
27 KEY_Init(); //初始化按键
28 delay_ms(100); //延时100ms再初始化看门狗,LED0的变化"可见"
29 IWDG_Init(4,500); //预分频数为64,重载值为500,溢出时间为1s
30 LED0=0; //点亮LED0
31 while(1)
32 {
33 if(KEY_Scan(0)==WKUP_PRES)//如果WK_UP按下,则喂狗
34 {
35 IWDG_Feed();//喂狗
36 }
37 delay_ms(10);
38 };
39 }
2. 窗口看门狗(WWDG)
2.1 WWDG 主要特性
窗口看门狗通常被用来监测由外部干扰或不可预见的逻辑条件造成的应用程序背离正常的运行序列而产生的软件故障。递减计数器的值在T6位(WWDG->CR)变成0 前被刷新,看门狗电路在达到预置的时间周期时,会产生一个Mcu复位。在递减计数器达到窗口配置寄存器(WWDG->CFR)数值之前,如果7位递减计数器的数值被刷新,那么也将产生一个Mcu复位。这表明递减计数器需要在一个有限的时间窗口中被刷新。
2.2 WWDG 主要寄存器
2.2.1 控制寄存器 (WWDG_CR)
2.2.2 配置寄存器 (WWDG_CFR)
2.2.3 状态寄存器 (WWDG_SR)
2.3 WWDG 配置要点
2.3.1 看门狗超时计算
最大超时设置:WWDG->CR |= 0x7F,最小超时设置:WWDG->CR |= 0x40
2.3.1 看门狗窗口值配置
如WWDG->CR |= 0x7F,WWDG->CFR |= 0x5F,则计数器在[0x7F,0x5F]的区间中不可刷新,否则会复位,在计数器区间[0x5F,0x40]需要配置。
2.4 WWDG 实验测试
代码语言:javascript复制//保存WWDG计数器的设置值,默认为最大.
u8 WWDG_CNT=0x7f;
//初始化窗口看门狗
//tr :T[6:0],计数器值
//wr :W[6:0],窗口值
//fprer:分频系数(WDGTB),仅最低2位有效
//Fwwdg=PCLK1/(4096*2^fprer). 一般PCLK1=45Mhz
void WWDG_Init(u8 tr,u8 wr,u8 fprer)
{
RCC->APB1ENR|=1<<11; //使能wwdg时钟
WWDG_CNT=tr&WWDG_CNT; //初始化WWDG_CNT.
WWDG->CFR|=fprer<<7; //PCLK1/4096再除2^fprer
WWDG->CFR&=0XFF80;
WWDG->CFR|=wr; //设定窗口值
WWDG->CR|=WWDG_CNT; //设定计数器值
WWDG->CR|=1<<7; //开启看门狗
MY_NVIC_Init(2,3,WWDG_IRQn,2);//抢占2,子优先级3,组2
WWDG->SR=0X00; //清除提前唤醒中断标志位
WWDG->CFR|=1<<9; //使能提前唤醒中断
}
//重设置WWDG计数器的值
void WWDG_Set_Counter(u8 cnt)
{
WWDG->CR =(cnt&0x7F);//重设置7位计数器
}
//窗口看门狗中断服务程序
void WWDG_IRQHandler(void)
{
WWDG_Set_Counter(WWDG_CNT);//重设窗口看门狗的值!
WWDG->SR=0X00;//清除提前唤醒中断标志位
LED1=!LED1;
}
int main(void)
{
Stm32_Clock_Init(360,25,2,8);//设置时钟,180Mhz
delay_init(180); //初始化延时函数
LED_Init(); //初始化与LED连接的硬件接口
LED0=0; //点亮LED0
delay_ms(300); //延时300ms再初始化看门狗,LED0的变化"可见"
WWDG_Init(0X7F,0X5F,3); //计数器值为7f,窗口寄存器为5f,分频数为8
while(1)
{
LED0=1; //关闭LED0
};
}
测试程序中设置的计数器值为0x7F,窗口计数器为0x5F,分频数为8,时钟45MHz,最大复位时间约46ms。
测试程序使能了窗口看门狗中断(计数器在0x40时触发中断),中断中改变Led灯开关状态,并且重设窗口看门狗的值,因此程序不会复位,看到的现象为LED0只开关一次,LED1每48ms闪速一次。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/154668.html原文链接:https://javaforall.cn