昨天主要介绍了视窗看门狗和独立看门狗的差别,今天来看这如何计算,这计算方式再参考手册里面有举例说明,如下图:
从图的下方可以看到,他已Tpclk=48MHz来举例,最下有个式子48000k,这手册没标示出来我也不知道位什麽?或许这是常识?...哈哈刚开始怀疑了一下子为甚麽是48000,经过按计算机才确定那是指48M分之1。
WWDG一般用来监测外部干扰或不可预见的逻辑条件,造成的应用程序背离正常的运行序列而产生的软件故障。
假设一个程序段正常运行的时间是50ms,在运行完这个段程序之後紧接着进行喂狗,如果在规定的时间视窗内还没有喂狗,那就说明我们监控的程序出故障了,那麽就会产生系统重置,让程序重新运行。
硬体需两个LED来观看喂狗状态。
bsp_wwdg.h
#ifndef __WWDG_H
#define __WWDG_H
#include "stm32f0xx.h"
void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv);
void WWDG_Feed(void);
#endif
宣告两个函式,初始化WWDG,喂狗
再来看中断的部分
void WWDG_IRQHandler(void)
{
// 清除中断标志位元
WWDG_ClearFlag();
//黄灯亮,点亮LED只是示意性的操作,
//真正使用的时候,这里应该是做最重要的事情
LED1_ON;
}
#include "./wwdg/bsp_wwdg.h"
static uint8_t wwdg_cnt; //用於记录看门狗 递减计数器的值,方便喂狗函数直接使用
static void WWDG_NVIC_Config(void) // WWDG 中断优先顺序初始化
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
在递减计数器减到0X40的时候,我们开启了提前唤醒中断,这个中断我们称它为死前中断或者叫遗嘱中断,在中断函数里面我们应该出来,是很重要的事情而且必须得快,因为递减计数器再减一次,就会产生系统重置。
void WWDG_Config(uint8_t tr, uint8_t wr, uint32_t prv)
{
wwdg_cnt = tr; //保存CNT配置,用在喂狗函数
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); // 开启 WWDG 时钟
WWDG_SetPrescaler(prv); // 设置预分频器的值
WWDG_SetWindowValue(wr); // 设置上视窗值
WWDG_Enable(tr); // 设置计数器的值,使能WWDG
WWDG_ClearFlag(); // 清除提前唤醒中断标志位元
WWDG_NVIC_Config(); // 配置WWDG中断优先顺序
WWDG_EnableIT(); // 开WWDG 中断
}
void WWDG_Feed(void) // 喂狗
{
WWDG_SetCounter( wwdg_cnt ); // 喂狗,刷新递减计数器的值,设置成最大WDG_CNT=0X7F
}
void WWDG_Config,来解释这函式里的三个数值要填怎样的数值
WWDG 配置函数
tr :递减计时器的值, 取值范围为:0x7f~0x40,超出范围会直接复位
wr :视窗值,取值范围为:0x7f~0x40
prv:预分频器值,取值可以是
WWDG_Prescaler_1: WWDG counter clock = (PCLK1(45MHz)/4096)/1 约10968Hz 91us
WWDG_Prescaler_2: WWDG counter clock = (PCLK1(45MHz)/4096)/2 约5484Hz 182us
WWDG_Prescaler_4: WWDG counter clock = (PCLK1(45MHz)/4096)/4 约2742Hz 364us
WWDG_Prescaler_8: WWDG counter clock = (PCLK1(45MHz)/4096)/8 约1371Hz 728us
例:tr = 127(0x7f,tr的最大值) wr = 80(0x50, 0x40为最小wr最小值) prv = WWDG_Prescaler_8~728 * (127-80) = 34.2ms < 刷新窗口 < ~728 * 64 = 46.6ms也就是说调用WWDG_Config进行这样的配置,若在之後的34.2ms前喂狗,系统会重定,在46.6ms後没有喂狗,系统也会重定。需要在刷新视窗的时间内喂狗,系统才不会重定。再来看main.c
#include "stm32f0xx.h"
#include "bsp_led.h"
#include "bsp_wwdg.h"
int main(void)
{
uint8_t wwdg_tr, wwdg_wr;
LED_GPIO_Config(); // LED_GPIO初始化
LED2_ON(); //LED2量
delay_ms(20);
WWDG_Config(127,80,WWDG_Prescaler_8); // 初始化WWDG
wwdg_wr = WWDG->CFR & 0X7F; //视窗值我们在初始化的时候设置成0x5F,这个值不会改变
while(1)
{
LED2(OFF);
wwdg_tr = WWDG->CR & 0X7F;
if( wwdg_tr < wwdg_wr )
{
WWDG_Feed(); // 喂狗,重新设置计数器的值为最大0X7F
}
}
}
烧入後的动作:
把编译好的程序下载到开发板,LED2 被点亮一段时间之後熄灭,之後LED2 一直就没有被点亮过,说明系统没有产生重定,如果产生重置的话LED2会再被点亮一次。中断服务程序中的LED1也没被点亮过,说明喂狗正常。
看门狗的介绍就到这了,目前我在练习韧体还没实际用到这个功能。
>>: Day 29:开始来学资料系结:使用目前所学,来个简单实作吧!(三)
前言 错误处理往往是最容易被忽略的一块,因为 程序运行顺利,那当然不用考虑 error case 程...
今天进度 鸟哥私房菜 - 第十五章、例行性工作排程(crontab) 我在 Crontab.guru...
接下来我要用一个小应用来介绍基本的 CRUD 实作:复仇者英雄列表。它的功能如下: 新增英雄到列表中...
我们回到第三天建立专案那天写的echo程序码。 结果如下: 主程序 Text Message 我们再...
4.8 可以为null 的数值型态 实例112 存取可以为null的数值型态 实例113 为Nul...