STM32F103 独立看门狗实验

  • Post author:
  • Post category:其他




看门狗的基础知识


什么是看门狗

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


看门狗的作用


在微控制器进入错误状态后的一定时间内复位程序,重新运行。当看门狗使能时,如果用户程序没有在溢出周期内喂狗(给看门狗定时器重装定时值),看门狗会产生一个系统复位,这样在程序运行时开启看门狗,对程序进行监视,可防止程序跑飞而死机。



IWDG(独立看门狗)简介


IWDG_KR 键寄存器



IWDG_PR 预分频寄存器



IWDG_RLR 重载寄存器

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

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

号(IWDG_RESET)。

无论何时,只要键寄存器IWDG——KR中被写入0xAAAA,IWDG_RLR中的值就会被重新加载到计数器中从而避免产生看门狗复位。

IWDG_PR和IWDG_RLR寄存器具有写保护功能。要修改这两个寄存器的值,必须先向IWDG_KR寄存器中写入0x5555,将其他值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入0xAAAA)也会启动写保护功能。

注意IWDG在一旦启用,就不能再被关闭!想要关闭,只能重启,并且重启之后不能打开IWDG,否则还是不能关闭。



IWDG的寄存器版介绍


test.c


//实验现象很简单,如果不喂狗,那么LED闪烁,因为超过了时间,系统进行了复位,按下KEY1键进行喂狗,那么就不会复位那么LED将一直亮。

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

int main(void)
{
	Stm32_Clock_Init(9);
	uart_init(72,115200);
	delay_init(72);
	LED_Init();
	KEY_Init();
	delay_ms(500);
	IWDG_Init(4,625);
	//4二进位制 100,对应分频64
	//重载值625,如何计算在wdg.c
	LED1 = 0;
	
	while(1)
	{
		if(KEY_Scan(0) == KEY1_PRES)
		{
			IWDG_Feed();
		}
		delay_ms(10);
	}
}


wdg.h

#ifndef __WDG_H
#define __WDG_H

#include "sys.h"

void IWDG_Init(u8 prer,u16 rlr);

void IWDG_Feed(void);

#endif 


wdg.c


//我感觉这章看代码还是很容易理解的

#include "wdg.h"

void IWDG_Init(u8 prer,u16 rlr)
{
	IWDG->KR = 0x5555;
	//对独立看门狗的键值寄存器输入0x5555,
	//使能IWDG->PR(预分频寄存器)和IWDG
	//->RLR(重装载寄存器)
	IWDG->PR = prer;
	//设置分频系数
	IWDG->RLR = rlr;
	//重装载寄存器值
	//Tout=((4×2^prer) ×rlr) /40 
	// 假设prer 值为 4,rlr 值为 625,那么就
	//可以得到 Tout=64×625/40=1000ms
	IWDG->KR = 0xAAAA;
	//喂狗,
	IWDG->KR = 0xCCCC;
	//使能启动看门狗
}


void IWDG_Feed(void)
{
	IWDG->KR = 0xAAAA;
	//喂狗
}



IWDG的HAL库介绍


头文件:stm32f1xx_hal_iwdg.h

源文件:stm32f1xx_hal_iwdg.c


重要函数


IWDG初始化函数

HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)


IWDG启动函数

HAL_StatusTyPeDef HAL_IWDG_Start(IWDG_HandleTypeDef *hiwdg)

IWDG喂狗函数

HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)



代码


main.c

#include "MyIncludes.h"

u16 sys_cnt = 0;
//systick滴答定时器计时器
void systick_isr(void)
{
  if(sys_cnt <100)
  {
    sys_cnt++;
  }
  else
  {
    sys_cnt = 0;
    HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5);
    //反转PC4 PC5 LED
    
  }
}

int main(void)
{
  System_Init();
  LED_Init();
  Key_Init();
  HAL_GPIO_WritePin(GPIOC,GPIO_PIN_4|GPIO_PIN_5,GPIO_PIN_RESET);
  //打开PC4 PC5 LED
  delay_ms(2000);

  SysTick_Init(systick_isr);
  Iwdg_Init(500);
  //独立看门狗初始化
  while(1)
  {
     Key_Read();
     if(Key_Info.Num != 0)
     {
       switch( Key_Info.Num )
       {
         case KEY_ONE:
         Iwdg_Feed();
         //喂狗
         break;
         default:break;
       }
     }
  }
}
/*可能刚看到这个程序有点懵,其实这个实验就是如果
没有按key1键,也就是没有喂狗,那么实验现象就是D5
D6 长亮一下,然后闪烁,然后一直重复此现象,因为没
有喂狗系统就会系统复位。但是如果长按key1,就会喂狗
,那么系统就不会复位,然后将一直进行systick滴答定
时器里面的内容,也就是会D5 D6一直闪烁*/


iwdg.h

#ifndef __IWDG_H_
#define __IWDG_H_

#include "stm32f1xx.h"
#include "stm32_types.h"
#include "stm32f1xx_hal.h"

void Iwdg_Init(u16 ms);
//独立看门狗初始化函数
void Iwdg_Feed(void);
//喂狗函数

#endif


iwdg.c

#include "iwdg.h"
IWDG_HandleTypeDef  IwdgHandle;

void Iwdg_Init(u16 ms)
{
   u16 timeout;
   if(ms >= 2048)
   //独立看门狗重装载寄存器低12位有效 也就是 0 - 11,一共12个端口
   //不要钻牛角尖 一定要是 2的12次方也就是4096,也可以是1024 512等 
   timeout = 2048;
   else
   timeout = ms;
   if(__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET )
   //检查系统是否已从IWDG复位恢复
   {
     __HAL_RCC_CLEAR_RESET_FLAGS();
     //清除重置标志
   }
  IwdgHandle.Instance = IWDG;//寄存器基址为 IWDG
  IwdgHandle.Init.Prescaler = IWDG_PRESCALER_32;//预分频32khz
  IwdgHandle.Init.Reload = timeout;//计数
  HAL_IWDG_Init(&IwdgHandle);
  HAL_IWDG_Start(&IwdgHandle);  //启动看门狗
}

void Iwdg_Feed(void)
//喂狗
{
  HAL_IWDG_Refresh(&IwdgHandle);
}



版权声明:本文为weixin_46567262原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。