关于我对stm32看门狗的一些理解(基于正点原子)

2022-08-27 13:19:18 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

咕咕咕之后想更会儿stm32哈哈哈,但是其实是之前自己写的笔记,想着以后就写在一起吧,我自己也更好去找到自己写的玩意~毕竟总所周知,博客都是写给自己的。 (虽然好像现在自己都看不懂了我的天哪)

一.什么是看门狗

在stm32中,我们会学到独立看门狗和窗口看门狗的实验。第一眼肯定是一脸懵逼啊,啥是看门狗啊?

看门狗在日常生活中,大概的印象就是,起到一个保证安全,防止外来人员搞事的作用。

stm32中的看门狗也起着差不多的意思:

看门狗就是起到一个监督单片机是否正在正常运行的作用。如果程序运行异常(跑飞),那么让系统复位,程序重新执行。

看一下百科解释:

在由单片机构成的微型计算机系统中,由于单片机的工作常常会受到来自外界电磁场的干扰,造成程序的跑飞,而陷入死循环,程序的正常运行被打断,由单片机控制的系统无法继续工作,会造成整个系统的陷入停滞状态,发生不可预料的后果,所以出于对单片机运行状态进行实时监测的考虑,便产生了一种专门用于监测单片机程序运行状态的模块或者芯片,俗称“看门狗”(watchdog)

那么看门狗怎么去实现这些操作呢?再讨论这个之前,我们先来看看stm32中的看门狗有哪些?

1.两种看门狗

STM32F10xxx内置两个看门狗,提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看门狗)或产生系统复位。

独立看门狗(IWDG)

独立看门狗由专用的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效。

IWDG最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合。

窗口看门狗(WWDG)

窗口看门狗由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作。

WWDG最适合那些要求看门狗在精确计时窗口起作用的应用程序。

但是单独看这个确实。。。有点迷,就有点印象哈。 但是大概应该也对看门狗有了一点概念,至少你知道了有两种看门狗。 那么我们现在详细来介绍一下独立看门狗(窗口看门狗留在下一个主题)

2.独立看门狗

之前看独立看门狗的介绍,我们知道他由一个专门的时钟驱动

这里给出更详细的介绍一下:

STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效。这里需要注意独立看门狗的时钟是一个内部 RC 时钟,所以并不是准确的 40Khz,而是在 30~60Khz 之间的一个可变化的时钟,只是我们在估算的时候,以 40Khz 的频率来计算,看门狗对时间的要求不是很精确,所以,时钟有些偏差,都是可以接受的。

我们这里可以理解为:他在主程序之外工作,可以监视主程序是否正常运行。

ok,那么他是怎么工作的?

先简单一点:

独立看门狗可以先设置一个时间(比如1s),如果超过这个时间,那么就代表主程序出了异常,然后让系统复位,程序重新执行。–在这里这个时间的流逝我们理解成一个倒计时

但是很多时候主程序本身就是一个死循环–肯定运行不止1s啊

于是我们需要在主程序之中重置这个时间(倒计时重新开始),如果主程序出现了问题—那么倒计时无法重置,但是我们的看门狗任然在运行,最终超过时间,看门狗让系统复位,程序重新执行。

我觉得我大概是理解了。。。

那么怎么去开启看门狗,又怎么去重置时间呢?

身为单片机—那只能用相关的寄存器去操作了

二.独立看门狗相关寄存器

咱先不去分析单独的寄存器啊,先去直接上框图:

先总体把握一下:这里我觉得官方说的就很好:

在键寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。 无论何时,只要在键寄存器IWDG_KR中写入0xAAAA, IWDG_RLR中的值就会被重新加载到计数器,从而避免产生看门狗复位 。

其实这里也就是看门狗原理的实现,倒计时就是计数器计数到末尾的时间

并且应该注意一下的是–

IWDG_PR和IWDG_RLR寄 存 器 具 有 写 保 护 功 能 。

要 修 改 这 两 个 寄 存 器 的 值 , 必 须 先 向IWDG_KR寄存器中写入0x5555。

以不同的值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。

重装载操作(即写入0xAAAA)也会启动写保护功能。

那先看一下键寄存器:

1.键寄存器(IWDG_KR)

但是我们会发现键寄存器其实只是写这三个值–那怎么自己设置时间呢?

所以主要看另外两个寄存器了–IWDG_PRIWDG_RLR

2.设置倒计时的两个寄存器–**IWDG_PR,**IWDG_RLR

先看图吧

ok,重点都标出来了,但是好像看了跟没看一样

再结合一下公式:

*Tout=(4*2^prer)rlr / 40 ms

(其中prer是IWDG_PR寄存器2进制化为十进制的值,rlr就是IWDG_RLR中的值)

Tout就是看门狗每次的倒计时T

公式的推导参考:https://blog.csdn.net/qq_37957854/article/details/105644138

所以通过对两个寄存器写入,我们就可以设置倒计时了—不要忘了写入之前的操作

还有一个寄存器来着。。这个就看一下就行:

3.状态寄存器(IWDG_SR)

状态寄存器指示预分频值和递减计数器是否正在被更新。

疑问:这个寄存器需要我们自己操作吗?

三.看门狗相关库函数讲解

1.看门狗相关库函数

代码语言:javascript复制
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess);

//取消写保护:0x5555使能

void IWDG_SetPrescaler(uint8_t IWDG_Prescaler);

//设置预分频系数:写PR

void IWDG_SetReload(uint16_t Reload);

//设置重装载值:写RLR

void IWDG_ReloadCounter(void);

//喂狗:写0xAAAA到KR

void IWDG_Enable(void);

//使能看门狗:写0xCCCC到KR

FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG);

//状态:重装载/预分频 更新

大概有些印象就行

几乎传入的参数也全都是具体的数值–分别就是设置那几个寄存器的值

我们现在直接看实验,首先是实验的目的:

2.实验目的

我们会在main.c函数中创建主程序:

开始实验后,先延迟一会,然后让一个LED亮起。

并在死循环中设置–如果按下按键,那么喂狗。

一般情况下应该就是直接喂狗,这里是为了检验看门狗,就显得很不符合常理

如果不按下按键,那么就不会喂狗,也就是说—程序会一直重启,LED呈现闪烁的效果

如果按时按下按键,程序开始喂狗,那么程序不会重启,LED灯常亮

3.开始写代码(源码分析)–运行看门狗步骤

ps:这里不分析在哪个文件,直接分析函数和代码

首先还是得

启动看门狗(初始化)

代码语言:javascript复制
void IWDG_Init(u8 prer,u16 rlr) 
{ 
   	
 	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);  //使能对寄存器IWDG_PR和IWDG_RLR的写操作
	
	IWDG_SetPrescaler(prer);  //设置IWDG预分频值:设置IWDG预分频值为64
	
	IWDG_SetReload(rlr);  //设置IWDG重装载值
	
	IWDG_ReloadCounter();  //按照IWDG重装载寄存器的值重装载IWDG计数器
	
	IWDG_Enable();  //使能IWDG
}

首先就是这个init函数的两个参数,表明自己没有设置rlr和prer,

要我们在初始化的时候自己设置**(自己设置倒计时)**

主体上:

    • 先解除对两个寄存器的写操作,
    • 然后再分别设置寄存器,
    • 并重新加载一遍两个寄存器—这里的代码是 *IWDG_ReloadCounter();* (这里可以留意一下吧)
    • 最后让看门狗开始执行。

然后

在main函数里面

代码语言:javascript复制
 int main(void)
 { 
   	
 
	delay_init();	    	 //延时函数初始化 
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2 
	uart_init(9600);	 //串口初始化为9600
	LED_Init();		  	 //初始化与LED连接的硬件接口 
  KEY_Init();          //按键初始化 
	delay_ms(300);   	 //让人看得到灭
	IWDG_Init(4,625);    //与分频数为64,重载值为625,溢出时间为1s 
	LED0=0;				 //点亮LED0
	while(1)
	{ 
   
		if(KEY_Scan(0)==WKUP_PRES)IWDG_ReloadCounter();	//如果WK_UP按下,则喂狗
		delay_ms(10);
	};
}

就两个操作和看门狗有关

第10行,引用初始化函数 并引入两个需要的数值— 套公式(寄存器的文章里面)

第14行 喂狗

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/145930.html原文链接:https://javaforall.cn

0 人点赞