9.独立看门狗IWDG&窗口看门狗WWDG编码思路

前言:

看门狗是维护系统稳定性的一向技术,可以让代码跑飞及时复位,在产品中非常常用,俗话说,重启能解决90%的问题,作为产品来说,你总不能因为一次bug就让程序卡死不动了,肯定要试着重启一下的。看门狗的原理简单的说就是它是一个倒数的计数器,倒数到某个数,它就重启,我们正常的程序当然不能莫名其妙重启,所以在它倒数的期间,往它的计数器写一个新的倒数的值,这样它就不会重启了。更简明地说,就是要定时地,往它的某个寄存器写一个值以防它重启。

独立看门狗和窗口看门狗原理一致,差异只在于倒数到哪个值就重启。独立看门狗是倒数到0就重启,而窗口看门狗是你只能在某一个时间区间给它的寄存器写重载值,提早写寄存器或者过晚写重载值,都会导致重启。

我们说看门狗的本质是个定时器,所以对于定时器,要关注的有几个点:1.时钟频率2.重载值&&计数值 3.中断事件4.定时器开关

独立看门狗:

1.时钟:由独立的内部RC时钟(32Khz)提供,即计数一次是1/32K 秒。当然时钟可以分频,对应的寄存器是IWDG_PR可以4,8,16,32.。。。256分频,这样就可以比较久再喂狗一次。

2.重载值&&计数值:

存重载值的寄存器是IWDG_RLR,只有12位有效即可以计数2^12-1 = 4095次,结合时钟频率,可知重启期限是 4095 / 时钟频率

只是,这个寄存器是有写保护的,要操作它需要先解锁,相关寄存器是IWDG_KR

对IWDG_KR写0x5555,就可以修改重载值IWDG_RLR以及分频值IWDG_PR

对IWDG_KR写0xAAAA,能够刷新计数值(即将重载值赋给计数值)

对IWDG_KR写0xCCCC,就能够开启看门狗(3.时钟开关 开了就没法关掉了)

没了,这个定时器连中断都没有~

初始化步骤是:

1.配置时钟分频系数**IWDG_PR,**设置重载值IWDG_RLR

复制代码
IWDG->KR=0X5555;//解锁
IWDG->PR=prer;  //设置分频系数   
IWDG->RLR=rlr;  //设置重载值
IWDG->KR=0XAAAA;//装载计数值
  1. 开启独立看门狗

    IWDG->KR=0XCCCC;

3.定时喂狗

复制代码
IWDG->KR=0XAAAA;//就是将重载值赋给计数值

完整代码:

初始化:

复制代码
void IWDG_Init(u8 prer分频值,u16 rlr重载值) 
{
	IWDG->KR=0X5555;//使能对IWDG->PR和IWDG->RLR的写		 										  
  	IWDG->PR=prer;  //设置分频系数   
  	IWDG->RLR=rlr;  //从加载寄存器 IWDG->RLR  
	IWDG->KR=0XAAAA;//reload											   
  	IWDG->KR=0XCCCC;//使能看门狗	
}

喂狗:

复制代码
void IWDG_Feed(void)
{
	IWDG->KR=0XAAAA;//reload											   
}

独立看门狗就是这么简单啦~

窗口看门狗:

窗口看门狗的原理,一个图就可以阐释清楚:

主要注意红色框的部分,只有在刷新窗口这个区间(W[6:0]~0X40)才能喂狗,否则无论是计数器还没倒数到W[6:0]之前就喂狗,亦或者计数器直到0X40还没喂狗,都会导致单片机复位。下面来看怎么配置。还是那样,关注定时器的核心要素:

初始化步骤是:

1.时钟频率

很离谱的是没有在时钟树看到WWDG的时钟分支,只好来在总线结构这里找,可知WWDG是附属于APB1的,由时钟系统配置我们直到APB1时钟是主频的4分频,即168M/4 = 42M

查看手册我们可以得知WWDG_CFR[8:7]可以配置时钟分频,既然提到了这个寄存器,那顺便就配置一下吧。

WWDG_CFR解析:

6:0\]: 这7位是设置窗口值的,也就是上面窗口看门狗原理框图中的W\[6:0

8:7\]: 配置时钟分频的 \[9\]: 这个位设为1,那么每次定时器倒数到0x40就会产生中断,这时我们只要在中断服务函数中喂狗,就能维持程序正常运行了\~ 要素**3.中断事件 在这里,当然别忘了,凡是和中断有关就是和NVIC有关(这个是内部中断,所以没有额外操作)** 所以如果将分频设为8(42M/8 = 5.25M),窗口值设为0x5F,并且开启中断的话: RCC->APB1ENR|=1<<11; //使能wwdg时钟 WWDG->CFR = 1<<9 | 0x3<<7 | 0x5f<<0; MY_NVIC_Init(2,3,WWDG_IRQn,2);//分组,中断号,优先级 **2.重载值\&\&计数值** 寄存器WWDG_CR控制着定时器开关以及计数值 \[6:0\]: **WWDG好像没有重载值,只有这个实时计数值,不过效果是类似的。在中断中要及时给它幅值,避免系统复位。** \[7\]: 置1就是打开WWDG 要素**4.定时器开关 在这里** 如果将计数值设为0x7f,并打开定时器就是: WWDG_CR->CR = 1<<7 | 0x7f ; 除了这两个寄存器外,还有一个大材小用的,寄存器**WWDG_SR** 一共32个位,只有bit0是有用的,作用是产生中断时会置1,而且要手动清零\~ 完整代码: 初始化WWDG:其实按上面我写的那个代码也是可以用的(实测),只是正点原子这个比较通用,了解了原理之后直接调用即可,也只有三个寄存器而已就没必要造轮子了 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_Init(0X7F,0X5F,3); //计数器值为7f,窗口寄存器为5f,分频数为8 喂狗函数: u8 WWDG_CNT=0x7f; //这个变量可以设置计数值 //重设置WWDG计数器的值 void WWDG_Set_Counter(u8 cnt) { WWDG->CR =(cnt&0x7F);//重设置7位计数器 } WWDG中断服务函数: //窗口看门狗中断服务程序 void WWDG_IRQHandler(void) { WWDG_Set_Counter(WWDG_CNT);//重设窗口看门狗的值! WWDG->SR=0X00;//清除提前唤醒中断标志位 //业务代码 } 无论是开发哪个模块,都需要根据核心思想来编码。第一次学习应力争总结出模块对应的开发流程,日后碰到不同的单片机才不至于完全没有思路。 完\~

相关推荐
小智学长 | 嵌入式4 小时前
单片机-STM32部分:17、数码管
stm32·单片机·嵌入式硬件
百里东风5 小时前
STM32外设DA实战-DAC + DMA 输出正弦波
stm32·单片机·嵌入式硬件
赵谨言8 小时前
基于单片机的防盗报警器设计与实现
经验分享·单片机·毕业设计
aloneboyooo8 小时前
STM32H7时钟树
stm32·单片机·嵌入式硬件
技术流浪者8 小时前
PCB设计(十九)PCB设计中NPN/PNP选型策略
单片机·嵌入式硬件·硬件工程·pcb工艺
长流小哥9 小时前
STM32实战指南:SG90舵机控制原理与代码详解
stm32·单片机·嵌入式硬件·keil5
xduryan12 小时前
16.1 - VDMA视频转发实验之TPG
嵌入式硬件
逼子格16 小时前
硬件工程师笔记——二极管Multisim电路仿真实验汇总
笔记·嵌入式硬件·硬件工程师·multisim·硬件工程师学习·电子器件·电路图
「QT(C++)开发工程师」16 小时前
STM32 | FreeRTOS 递归信号量
python·stm32·嵌入式硬件
芯眼17 小时前
ALIENTEK精英STM32F103开发板 实验0测试程序详解
开发语言·c++·stm32·单片机·嵌入式硬件·社交电子