18_独立开门狗试验

目录

独立看门狗概述

独立看门狗功能描述

 IWDG独立看门狗操作库函数

 独立看门狗操作步骤

实验源码:

实验结果:


独立看门狗概述

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

看门狗解决的问题是在启动正常运行的时候,系统不能复位。在系统跑飞(程序异常执行)的情况下,系统复位,程序重新执行。

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

独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它任有效,独立看门狗适合应用于需要看门狗作为一个主程序之外能够完全独立工作,并且对时间精度要求低的场合。

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

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

独立看门狗功能描述

在键值寄存器(IWDG_KR)中写入0xcccc开始启用独立看门此时计数器开始从其复位值0xFFF递减,当计数器值计数到0x000时会产生一个复位信号(IWDG_RESET)。

无论何时,只要键值寄存器IWDG_KR中写入0xAAAA(通常说的喂狗),自动重装载寄存器IWDG_RLR的值就会重新加载到计数器,从而避免看门狗复位。

如果程序异常,就无法正常喂狗,从而系统复位。

键值寄存器IWDG_KR:0~15位有效

预分频寄存器IWDF_PR:0~2位有效  具有写保护功能,要操作先取消写保护

重装载寄存器IWDG_RLR:0~11位有效 具有写保护功能,要操作先取消写保护

状态寄存器IWDG_SR:0~1位有效

解除写保护写0x5555到KR寄存器

 

 

 IWDG独立看门狗操作库函数

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)//状态:重装载/预分频更新

 独立看门狗操作步骤

1.取消寄存器写保护

IWDG_WriteAccessCmd();

2.设置独立看门狗的预分频系数,确定时钟

IWDG_SetPrescaler();

3.设置看门狗重装载值,确定溢出时间

IWDG_SetReload();

4.使能看门狗

IWDG_Enable();

5.应用程序喂狗

IWDG_ReloadCounter();

实验源码:

实验介绍在外部中断在中喂狗,程序加打印1s没有喂狗会复位。

/*!
	\brief		RCC配置
	\param[in]	none
	\param[out]	none
	\retval 	none
*/
void Rcc_config(void)
{	
	
	/*使能GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	/*使能GPIOE时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);

	/*使能复用外设时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	/*使能UART1时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

}


/*!
	\brief		GPIO初始化函数
	\param[in]	none
	\param[out]	none
	\retval 	none
*/
void Gpio_Init(void)
{	
	/*GPIO结构体*/
	GPIO_InitTypeDef GPIO_InitTypeDefstruct;
	
	/*KEY2结构体配置*/
	GPIO_InitTypeDefstruct.GPIO_Mode  = GPIO_Mode_IPU; 					   //上拉输入 没按下默认是高电平
	GPIO_InitTypeDefstruct.GPIO_Pin   = GPIO_Pin_4;  //引脚选择
	/*初始化GPIOE Pin2 3 4*/ 
	GPIO_Init(GPIOE,&GPIO_InitTypeDefstruct); 
	
	
	/*UART1发送引脚配置*/
	GPIO_InitTypeDefstruct.GPIO_Mode  = GPIO_Mode_AF_PP;//推挽复用输出
	GPIO_InitTypeDefstruct.GPIO_Pin   = GPIO_Pin_9;
	GPIO_InitTypeDefstruct.GPIO_Speed =	GPIO_Speed_10MHz;
	/*写入结构体到GPIOA*/
	GPIO_Init(GPIOA,&GPIO_InitTypeDefstruct);
	
	/*UART1接收引脚配置*/
	GPIO_InitTypeDefstruct.GPIO_Mode  = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_InitTypeDefstruct.GPIO_Pin   = GPIO_Pin_10;
	GPIO_InitTypeDefstruct.GPIO_Speed =	GPIO_Speed_10MHz;
	/*写入结构体到GPIOA*/	
	GPIO_Init(GPIOA,&GPIO_InitTypeDefstruct);
	
		
}

/*!
	\brief		UART1初始化
	\param[in]	none
	\param[out]	none
	\retval 	none
*/

void Uart1_Init(u32 bound)
{
	/*UART结构体*/
	USART_InitTypeDef USART_InitTypeDefstruct;
	/*NVIC结构体*/
	NVIC_InitTypeDef NVIC_InitTypeDefstruct;
	
	/*UART结构体配置*/
	USART_InitTypeDefstruct.USART_BaudRate = bound; //波特率
	USART_InitTypeDefstruct.USART_HardwareFlowControl =USART_HardwareFlowControl_None; //不使用硬件流
	USART_InitTypeDefstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//发送接收使能
	USART_InitTypeDefstruct.USART_Parity = USART_Parity_No; //不使用奇偶校验
	USART_InitTypeDefstruct.USART_StopBits = USART_StopBits_1; //1个停止位
	USART_InitTypeDefstruct.USART_WordLength = USART_WordLength_8b; //8个数据位
	/*写入USART1*/
	USART_Init(USART1,&USART_InitTypeDefstruct);
	
	/*使能串口1*/
	USART_Cmd(USART1,ENABLE);

	/*中断配置*/
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //UART1接收缓冲区非空中断,接收中断
	
	NVIC_InitTypeDefstruct.NVIC_IRQChannel=  USART1_IRQn; //USART1中断通道
	NVIC_InitTypeDefstruct.NVIC_IRQChannelCmd = ENABLE;  //使能USART1中断
	NVIC_InitTypeDefstruct.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级
	NVIC_InitTypeDefstruct.NVIC_IRQChannelSubPriority = 1;//子优先级
	
	/*写入NVIC中*/
	NVIC_Init(&NVIC_InitTypeDefstruct);
}

/*!
	\brief		UART1中断服务函数
	\param[in]	none
	\param[out]	none
	\retval 	none
*/

void USART1_IRQHandler(void)
{
	uint8_t Receive;
	/*接收数据*/
	Receive = USART_ReceiveData(USART1);

	printf("UART1中断,值为:%x\r\n",Receive);


}

/*!
	\brief		EXTI初始化
	\param[in]	none
	\param[out]	none
	\retval 	none
*/
void EXTIX_Init(void)
{	
	/*EXTI结构体*/
	EXTI_InitTypeDef EXTI_InitStuct;
	/*NVIC结构体*/
	NVIC_InitTypeDef NVIC_InitTypeDefstruct;
	/*映射IO口到EXTI线上*/
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
	
	
	/*触发方式设置*/
	EXTI_InitStuct.EXTI_Line = EXTI_Line4;//EXTI4
	EXTI_InitStuct.EXTI_LineCmd = ENABLE; //使能
	EXTI_InitStuct.EXTI_Mode = EXTI_Mode_Interrupt;  //中断模式
	EXTI_InitStuct.EXTI_Trigger = EXTI_Trigger_Falling; //下降验触发 按键按下是低电平
	/*触发方式写入*/
	EXTI_Init(&EXTI_InitStuct);
	
	
	/*中断配置*/
	NVIC_InitTypeDefstruct.NVIC_IRQChannel=  EXTI4_IRQn; //EXTI4中断通道
	NVIC_InitTypeDefstruct.NVIC_IRQChannelCmd = ENABLE;  //使能EXTI4中断
	NVIC_InitTypeDefstruct.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
	NVIC_InitTypeDefstruct.NVIC_IRQChannelSubPriority = 1;//子优先级
	
	/*写入NVIC中*/
	NVIC_Init(&NVIC_InitTypeDefstruct);

}

/*!
\brief		EXTI4中断服务函数
	\param[in]	none
	\param[out]	none
	\retval 	none
*/

void EXTI4_IRQHandler(void)
{
	/*消抖处理*/
	delay_ms(10);
	
	/*读取GPIOE.4电平低是按下*/
	if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4) == 0)
	{
			/*喂狗*/
			IWDG_ReloadCounter();
			/*提示语句*/
			printf("喂狗成功\r\n");
		
	}

	/*清除EXTI4中断标志位*/
	EXTI_ClearITPendingBit(EXTI_Line4);
}

/*!
	\brief		看门狗初始化函数
	\param[in]	prer 预分频系数
	\param[in]	rlr  重装载值	
	\param[out]	none
	\retval 	none
*/
void IWDG_Init(uint8_t prer, uint16_t rlr)
{	
	/*取消写保护写入0x5555*/
	IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
	
	/*写入预分频系数*/	
	IWDG_SetPrescaler(prer);
	
	/*写入重装载值*/
	IWDG_SetReload(rlr);
	
	/*加载数值到计数器里使能后直接从加载值开始计时*/
	IWDG_ReloadCounter();
	
	/*使能看门狗*/
	IWDG_Enable();
}

/* Typedef 类型----------------------------------------------------------------*/
/* Define  定义----------------------------------------------------------------*/
/* Macro   宏------------------------------------------------------------------*/
/* Variables 变量--------------------------------------------------------------*/ 
/* Constants 常量--------------------------------------------------------------*/
/* Function  函数--------------------------------------------------------------*/


 int main(void)
 {	
     
	 /*延时函数初始化*/
	 delay_init(); 	 
	 /*配置系统中断分组为2位抢占2位响应*/
	 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	 /*Rcc初始化*/	 
	 Rcc_config();
	 /*GPIO初始化*/
	 Gpio_Init();
	 /*UART1初始化*/
	 Uart1_Init(9600);
	 /*EXTI初始化*/
	 EXTIX_Init();
	 /*初始化独立看门狗*/
	 IWDG_Init(4, 625); //1000ms=((4*2^prer)*rlr)/40
	 /*提示语句*/
	 printf("程序复位******************\r\n");
	 
	/*死循环*/ 
	 while(1){
			 printf("程序运行\r\n");	
			 delay_ms(100);
		 
	 }
	
 }

实验结果:

在没有按下按键的时候一直1s复位

按键按下成功喂狗程序一直跑while里面程序

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值