STM32工作笔记0059---独立看门狗实验

技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152

这个看门狗的用处就是,时刻去检测系统,如果系统出了问题,就进行复位

保证系统正常运行.

系统正常运行的时候,看门狗只会去检测,不会去干预,发现问题了以后,就会去复位系统.

独立看门狗和窗口看门狗的提供的时钟源是不一样的,一个是低速的,一个是APB1的,

适用的情况也不一样.独立看门狗,可以独立于系统的主程序之外去运行.

这个独立看门狗的运行过程,

首先有个键值寄存器,这个寄存器会在启动时候,写入0XCCCC,来开启独立看门狗,此时计数器开始

从其复位值0XFFF递减,当计数器的值递减到0的时候,就会产生一个复位信号,来让MCU芯片,进行复位.

所以为了让咱们的程序不会在正常运行的时候,被看门狗复位掉,这个时候,就有个喂狗的操作,

意思就是,只要是比如如果向KR寄存器中写入0XAAAA的时候,这个时候就会产生喂狗,喂狗的意思是,

这个时候RLR寄存器的值就会被加载到计数器中,然后,计数器再从加载到加载进去的值开始倒计数

如果,咱们设置RLR中的值是100,那么当计数到50的时候,我们开始喂狗,那么这个时候,计数器,又会

从100开始计数,只要是不停的喂狗,那么计数器,就不会数到0,也就是不会发生复位的现象.

但是如果系统出现异常了,就会导致,不能及时喂狗,那可能,计数器就会数到0,从而

会复位MCU.然后重启后,又重新开始喂狗.

通过这样的一个过程来达到监测程序运行的过程.

看一下看门狗的框图,

可以看到这里首先,我们把0XCCCC写入到IWDG_KR寄存器,这个时候看门狗启动,

然后计数器开始从0XFFF倒数计数,这个时候,咱们再写入到IWDG_KR中一个0XAAAA,那么

这个时候,IWDG_RLR中的值就会加载到计数器中,然后从加载的这个值,再往下开始倒数,

这里以SR寄存器就是可以获取到一些状态.

注意上有两个寄存器,要想写入数据,需要先取消掉写保护的这个功能以后才能写入数据.

这个KR寄存器,这里写入0X5555的时候,表示PR,和RLR寄存器取消掉写保护的功能.

也就是允许,写入操作了.

然后看看预分频寄存器,这个好理解,只有3位能用,不同的时候,预分频因子不一样,也就是除以的那个数不一样 .

这个RLR寄存器,就是12位有效,用来定义,要重新计数的那个数是多少.

这个用的不多,主要是用来获取看门狗的一些状态,比如重装载的值更新了,预分频的值更新啦,这样的状态.

注意,这里的时钟是40000那么,预分频的话,就是

40000/4(或者8了) 这个是时钟频率,也就是一秒钟,震荡多少次.

然后一次需要多久呢,就是:比如这里的预分频系数是4,也就是prer是0的话.

然后这个1/(40000/4)=1/10000,这个是震荡一次需要多长时间.

那么这个看门狗,多久能倒数到0就可以算出来了,就是 

rlr的值 * (1/10000) 这个就是把rlr的值,倒数到0以后所需要的花费的时间了.

那么最长时间就是rlr这个值为0XFFF的时候

最短的时间就是rlr这个值是1的时候.

这里的溢出时间实际上 就是当系统出了问题,多长时间进行复位.

这里,写这个看门狗的实验,要以按键实验,来修改,添加看门狗功能

打开这个文件夹,然后

再hardware文件夹中新建上面两个文件

然后把刚新建的文件,添加进来.

编译一下,就可以看到对应的.h文件

然后把1到4步来做成一个初始化的函数.

现在.h文件中定义这个函数,然后,这个参数就是一个预分频系数,一个装载值.

这里用到了u8,u16,这个类型,所以要把sys.h文件引入.

然后把头文件.h的路径包含到工程中去

然后开始写这个.c文件,然后

写之前要把看门狗相关的库函数加进来.

加进来以后,编译一下,就可以看到头文件

然后:下面这几个函数就是上面看到那几个


void IWDG_Init(u8 prer, u16 rlr)
{
	// 1.使能对寄存器IWDG_PR和IWDG_RLR的写操作
	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
	// 2.设置IWDG预分频值:设置IWDG预分频值
	IWDG_SetPrescaler(prer);
	// 3.设置IWDG重装载值
	IWDG_SetReload(rlr);
	// 4.使能IWDG
	IWDG_Enable();
}

实际上这样就可以用了,但是这样的话,默认是从0XFFF来开始计数的

这样的话,就不是从设定的rlr值开始计数的,因为还没哟开始喂狗,开始喂狗后

才开始从RLR的值开始计数.

void IWDG_Init(u8 prer, u16 rlr)
{
	// 使能对寄存器IWDG_PR和IWDG_RLR的写操作
	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
	// 设置IWDG预分频值:设置IWDG预分频值
	IWDG_SetPrescaler(prer);
	// 设置IWDG重装载值
	IWDG_SetReload(rlr);
	// 按照IWDG重装载寄存器的值重装载IWDG计数器 //这次又把这个加上了,这个实际上就是把
    //RLR的值,加载到计数器开始计数,但是这里只是写了这个代码,装载了数据,但不会计数,因为
    //还没开始使能.
	IWDG_ReloadCounter();
	// 使能IWDG
	IWDG_Enable();
}

然后这里看一下再去写这个main.c文件

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "wdg.h"

/************************************************
 ALIENTEK精英STM32开发板实验6
 独立看门狗实验  
 技术支持:www.openedv.com
 淘宝店铺:http://eboard.taobao.com 
 关注微信公众平台微信号:"正点原子",免费获取STM32资料。
 广州市星翼电子科技有限公司  
 作者:正点原子 @ALIENTEK
************************************************/
int main(void)
{
	delay_init();									// 延时函数初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);								// 串口初始化为115200
	LED_Init();										// 初始化与LED连接的硬件接口
	KEY_Init();										// 按键初始化
	//1.前面是一堆的初始化,然后这个地方要说明一下,如果我不写
    //下面的while代码的话,仅仅是,这里调用一下这个
    //IWDG_Init(4, 625); 进行看门狗的初始化的话,
    //那么这个时候,这个看门狗他会从625进行倒数,倒数到0就会
    //执行复位,这样如果没有喂狗的操作,咱们看到是现象就是
    //LED不停的闪烁.
    //因为后面把LED=0置亮了.
    delay_ms(500);									// 让人看得到灭
	IWDG_Init(4, 625);								// 与分频数为64,重载值为625,溢出时间为1s
	LED0 = 0;										// 点亮LED0
	while (1)
	{
     //2.如果加上了这个代码的话,那么这里也就是说,如果我
     //按下了这个按键,那么他就会去喂狗
     //喂狗的话,程序就不会复位那么看到的情况,就是LED灯一直0,不会闪烁了.
		if (KEY_Scan(0) == WKUP_PRES)
		{
			IWDG_Feed(); // 如果WK_UP按下, 则喂狗
		}
		delay_ms(10);
	};
}

注意这里的:

// 喂独立看门狗
void IWDG_Feed(void)
{
    // 重装载IWDG计数器
    IWDG_ReloadCounter();
}
IWDG_Feed这个函数是在wdg.c中定义了,实际上仅仅是调用了一下喂狗的函数而已.

main.c没有写while循环的时候,也就是没有喂狗的时候,可以看到这个单片机的LED 会不停的闪烁

下面的图看不出闪烁的情况

写while循环的时候,如果按下了wk_up按键的话,就去喂狗,这样

led就会一直亮了.

这里还要注意一下,这里的,预分频系数如果设置为4,那么对应的rlr的值是625,

那么这个625是根据上面的公式计算出来的.

可以看到如果我们要想把预分频系数设置为4,溢出时间设置为1s的话,那么

根据上面的公式就可以算出rlr的值是625.

猜你喜欢

转载自blog.csdn.net/lidew521/article/details/108243748