基于STM32F103ZET6主控平台实现看门狗驱动

一个热爱代码的工程师,唯有凭借双手不断敲打,才可以快速提升实力!

本文谨以记录,日后相忘时再作复习,代码没有贵贱,既来之则安之。

STM32F1内部自带了 2 个看门狗:独立看门狗( IWDG)和窗口看门狗( WWDG)

一、独立看门狗( IWDG)

第一步:清楚看门狗的工作模式

IWDG看门狗拥有独立的32KHZ的时钟,为其提供计数服务。通过设置预分频和重装载值来设定递减时长,

该时间的计算方式为:Tout=((4× 2^prer) × rlr) /40

其中 Tout 为看门狗溢出时间(单位为 ms); prer 为看门狗时钟预分频值( IWDG_PR 值),
范围为 0~7; rlr 为看门狗的重装载值( IWDG_RLR 的值);

比如我们设定 prer 值为 4, rlr 值为 625,那么就可以得到 Tout=64× 625/40=1000ms,这样,看门狗的溢出时间就是 1s,只要你在一秒钟之内,有一次写入 0XAAAA 到 IWDG_KR,就不会导致看门狗复位(当然写入多次也是可以的)。

向 IWDG_KR 写入 0XAAAA实现喂狗操作,向 IWDG_KR 写入 0XCCCC开启看门狗。

第二步:编写iwdg.h头文件

#ifndef __IWDG_H
#define __IWDG_H

#include "sys.h"

void IWDG_Init(u8 prer,u16 rlr);//独立看门狗初始化
void IWDG_Feed(void);
#endif 

第二步:编写iwdg.c

#include "iwdg.h"

/*初始化独立看门狗
  prer:分频数:0~7(只有低 3 位有效!)
				分频因子=4*2^prer.但最大值只能是 256!
				
  rlr:重装载寄存器值:低 11 位有效.
				时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
*/
void IWDG_Init(u8 prer,u16 rlr)
{
	IWDG->KR=0X5555;//使能对 IWDG->PR 和 IWDG->RLR 进行写
	IWDG->PR=prer;
	IWDG->RLR=rlr;
	IWDG->KR=0XAAAA;//喂狗
	IWDG->KR=0XCCCC;//开启独立看门狗
}

void IWDG_Feed(void)//喂狗防止复位
{
	IWDG->KR=0XAAAA;
}

第三步:编写main函数

/*
 * 自学DIY
 */
#include "sys.h"
#include "usart.h"		
#include "delay.h"

#include "led.h"
#include "beep.h"
#include "key.h"
#include "exit.h"
#include "iwdg.h"
u8 Wl_stat=0;
int main(void)
{		
	Stm32_Clock_Init(9);	  //系统时钟设置
	delay_init(72);	  		  //延时初始化
	uart_init(72,115200); 	//串口初始化为115200
	LED_Init();
	BEEP_Init();
	EXIT_Init();
	KEY_Init();
	IWDG_Init(4,625);
	printf("-------------------- \r\n");
	printf("    自学->嵌入式     \r\n");
	printf("    版本:1.0.0       \r\n");
	printf("-------------------- \r\n");
        delay_ms(300);
	LED0=0;
	while(1)
	{
		if(Wl_stat==0)//代表进入WHILE循环
		{
			printf("Input While(1)-->\r\n");
			Wl_stat=1;
		}
		if(Key_Scan(0)==KEYUP_PRES)
		{
			IWDG_Feed();
		}
		delay_ms(10);
	}
	
} 

第四步:编译通过后,烧录进STM32F103ZET6开发板,实现程序设计效果即可。

效果:【在编译成功之后,我们就可以下载代码到精英 STM32 V1 开发板上,实际验证一下,我们
的程序是否正确。下载代码后, 可以看到 DS0 不停的闪烁,证明程序在不停的复位,否则只会
DS0 常亮。这时我们试试不停的按 KEY_UP 按键,可以看到 DS0 就常亮了,不会再闪烁。说
明我们的实验是成功的。】
二、独立看门狗( WWDG)

和独立看门狗类似的功能,当递减计数器在一个有限时间窗口中被刷新,则不会产生复位。

第一步:编写iwdg.h头文件 与独立看门狗共用一个头文件 不影响结果

#ifndef __IWDG_H
#define __IWDG_H

#include "sys.h"

void IWDG_Init(u8 prer,u16 rlr);//独立看门狗初始化
void IWDG_Feed(void);
void WWDG_Init(u8 tr,u8 wr,u8 fprer);
#endif 

第二步:编写iwdg.c

#include "iwdg.h"
#include "led.h"
//保存 WWDG 计数器的设置值,默认为最大.
u8 WWDG_CNT=0x7f;
/*初始化窗口看门狗
  tr :T[6:0],计数器值
  wr :W[6:0],窗口值
  fprer:分频系数( WDGTB) ,仅最低 2 位有效
  Fwwdg=PCLK1/(4096*2^fprer).
*/
void WWDG_Init(u8 tr,u8 wr,u8 fprer)
{
	RCC->APB1ENR|=1<<11; //开启窗口看门狗时钟 36MHz
	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_Feed(u8 value)
{
	WWDG->CR|=(value&0x7F);//取[6:0]位
}
//看门狗中断服务函数
void WWDG_IRQHandler(void)
{
	WWDG_Feed(WWDG_CNT);//喂最大值7F
	WWDG->SR=0X00;//软件置零
	LED1=!LED1;
}

/*初始化独立看门狗
  prer:分频数:0~7(只有低 3 位有效!)
				分频因子=4*2^prer.但最大值只能是 256!
				
  rlr:重装载寄存器值:低 11 位有效.
				时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
*/
void IWDG_Init(u8 prer,u16 rlr)
{
	IWDG->KR=0X5555;//使能对 IWDG->PR 和 IWDG->RLR 进行写
	IWDG->PR=prer;
	IWDG->RLR=rlr;
	IWDG->KR=0XAAAA;//喂狗
	IWDG->KR=0XCCCC;//开启独立看门狗
}

void IWDG_Feed(void)//喂狗防止复位
{
	IWDG->KR=0XAAAA;
}

第三步:编写main函数

#include "beep.h"
#include "key.h"
#include "exit.h"
#include "iwdg.h"
u8 Wl_stat=0;
int main(void)
{		
	int key_stat;
	Stm32_Clock_Init(9);	  //系统时钟设置
	delay_init(72);	  		  //延时初始化
	uart_init(72,115200); 	//串口初始化为115200
	LED_Init();
	BEEP_Init();
	WWDG_Init(0X7F,0X5F,3);
//	EXIT_Init();
//	KEY_Init();
//	IWDG_Init(4,625);
	printf("-------------------- \r\n");
	printf("    自学->嵌入式     \r\n");
	printf("    版本:1.0.0       \r\n");
	printf("-------------------- \r\n");

	LED0=0;
	delay_ms(300);
	
	while(1)
	{
		if(Wl_stat==0)//代表进入WHILE循环
		{
			printf("Input While(1)-->\r\n");
			Wl_stat=1;
		}
		LED0=1;
//		if(Key_Scan(0)==KEYUP_PRES)
//		{
//			IWDG_Feed();
//		}
//		delay_ms(10);
	}
	
} 

第四步:编译通过后,烧录进STM32F103ZET6开发板,实现程序设计效果即可。
效果:

将代码下载到精英 STM32 V1 开发板后,可以看到 DS0 亮一下之后熄灭,紧接着 DS1 开始不停的闪烁。每秒钟闪烁 8 次左右,和我们预期的一致,说明我们的实验是成功的

想太多,做太少,怎改变自己

谢谢大家的关注和支持,来自一个嵌入式软硬件工程师的内心情感!

PS:本文的代码参考正点原子

猜你喜欢

转载自blog.csdn.net/weixin_41586634/article/details/82783473