一个热爱代码的工程师,唯有凭借双手不断敲打,才可以快速提升实力!
本文谨以记录,日后相忘时再作复习,代码没有贵贱,既来之则安之。
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:本文的代码参考正点原子