1.STM32的独立看门狗是一个具有独立时钟的片上外设。通常,为了防止程序卡死,可以设置看门狗定时复位。当看看门狗被使能之后,会按初始化时设置的计数值进行计数。当根据计数值计数的倒数时间为0时,便会自动复位程序,即重启系统。
计数值的计数为如下、prer为预分频值,rlr为计数值。
因此,需要及时的进行喂狗,即往寄存器中写入0xAAAA。
2.相关寄存器:
(1)IWDG_KR:
(2)IWDG_PR:
(3) IWDG_RLR:
3.设计思路:
首先,往KR寄存器中写入0x5555,取消PR和RLR寄存器的写保护。然后,设置分频系数、看门狗计数值,并加载计数值。最后,使能看门狗。
喂狗是往KR寄存器中写入0xAAAA即可。
4.代码:
(1)led:
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
void LED_Init(void);
#endif
#include "led.h"
void LED_Init(void)
{
//¶¨Òå¶Ë¿ÚµÄ½á¹¹Ìå:
GPIO_InitTypeDef GPIO_InitStruct;
//1.ʹÄÜʱÖÓ£º
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOA,ENABLE);
//2.ÅäÖö˿ڽṹÌåµÄÏà¹ØÐÅÏ¢£º£¨LED1£©
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD,&GPIO_InitStruct);
//ÅäÖÃLED0£º
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOA,&GPIO_InitStruct);
//³õʼʱ½«LEDµÄ¶Ë¿Ú¶¼ÖÃΪ1£¬¼´Ï¨Ãð
GPIO_SetBits(GPIOA,GPIO_Pin_8);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
}
(2)key:
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
#define KEY_0 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) //¶ÁÈ¡°´¼üµÄ״̬
#define KEY_1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)
#define KEY_2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
void KEY_Init(void);
void KEY_Scan(void); //°´¼üɨÃ躯Êý
#endif
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h"
#define KEY_0 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) //¶ÁÈ¡°´¼üµÄ״̬
#define KEY_1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)
#define KEY_2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
void KEY_Init(void);
void KEY_Scan(void); //°´¼üɨÃ躯Êý
#endif
#include "key.h"
#include "delay.h"
#include "led.h"
void KEY_Init(void)
{
/*1.¶¨ÒåÒý½ÅµÄ½á¹¹Ìå¡£
2.ʹÄÜÒý½Å¶ÔÓ¦µÄʱÖÓ¡£
3.ÅäÖÃÒý½ÅÐÅÏ¢*/
//¶¨ÒåÒý½Å½á¹¹Ì壺
GPIO_InitTypeDef GPIO_InitStruct;
//ʹÄÜʱÖÓ£º
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC,ENABLE);
//ÅäÖÃÒý½ÅÐÅÏ¢(KEY0)£º
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStruct);
//ÅäÖÃKEY1£º
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //ÉèÖóÉÉÏÀÊäÈë
GPIO_Init(GPIOA,&GPIO_InitStruct);
//ÅäÖð´¼üWK_UP:
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA,&GPIO_InitStruct);
}
void KEY_Scan(void)
{
static u8 key_up = 1; //°´¼üËÉ¿ª±ê־λ
if(key_up && (KEY_0 == 0|| KEY_1 == 0|| KEY_1 == 1))
{
delay_ms(10); //È¥¶¶¶¯
key_up = 0;
if(KEY_0 == 0)
{
GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
//delay_ms(1000);
}
else if(KEY_1 == 0)
{
GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
GPIO_SetBits(GPIOD,GPIO_Pin_2);
//delay_ms(1000);
}
else if(KEY_2 == 1)
{
GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
}
}
else if(KEY_0==1&&KEY_1==1&&KEY_2==0)
{
key_up = 1;
}
}
(3)IWDG:
#ifndef __IWDG_H
#define __IWDG_H
#include "stm32f10x.h"
void IWDG_Init(u8 prer,u16 rlr);
void FEED_Dog(void);
#endif
#include "iwdg.h"
void IWDG_Init(u8 prer,u16 rlr)
{
//IWDGÓÐ×Ô¼ºµÄ¶ÀÁ¢Ê±ÖÓ£¬Òò´Ë²»ÐèҪʹÄÜËüµÄʱÖÓ
//1.ÍùIWDG->KR¼Ä´æÆ÷ÖÐдÈë0x5555,È¡ÏûIWDG_PRºÍIWDG_RLR¼Ä´æÆ÷µÄд±£»¤£º
IWDG->KR = 0x5555;
//2.ÉèÖ÷ÖƵϵÊý£º
IWDG->PR = prer;
//3.ÉèÖÿ´ÃŹ·µÄ¼ÆÊýÖµ£º
IWDG->RLR = rlr;
//4.¼ÓÔؼÆÊýÖµ£º
IWDG->KR = 0xAAAA;
//5.ʹÄÜ¿´ÃŹ·£º
IWDG->KR = 0xCCCC;
}
void FEED_Dog(void)
{
//ÿ´ÎÍùKR¼Ä´æÆ÷ÖÐдÈë0xAAAA£¬¿´ÃŹ·±ã»áÖØмÓÔؼÆÊýÖµ£º
IWDG->KR = 0xAAAA;
}
(5)main:
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "iwdg.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é2
LED_Init();
KEY_Init();
IWDG_Init(4,625);
GPIO_SetBits(GPIOA,GPIO_Pin_8);
delay_ms(1000);
GPIO_ResetBits(GPIOA,GPIO_Pin_8); //´ò¿ªLED
while(1)
{
/*ʵÑéÏÖÏ󣺵±²»Í£µÄ°´Ï°´¼üʱ£¬¿ÉÒÔ¿´µ½µÆ³£ÁÁ¡£·´Ö®£¬¿ÉÒÔ¿´µ½µÆÉÁ˸*/
if(KEY_2 == 1) //Èç¹û°´¼ü±»°´Ï£¬Ôòι¹·¡£
{
FEED_Dog();
}
delay_ms(1000);
}
}
5.运行结果:
6.总结:利用看门狗可以防止程序卡死,即定时的喂狗。如果,没有及时的喂狗,系统便会一直复位。看门狗在实践中的应用很大,写入代码中,可以避免系统卡死。同时,可以避免逻辑错误,即如果系统没有执行到设定的逻辑的地方,就不喂狗,让系统复位,这样就可以知道程序在哪里出现了问题。