目录
实现目的:测试看门狗复位系统,并利用串口打印进行反馈
实验平台:正点原子精英版
一、简介
1.IWDG简介
Independent watchdog,即独立看门狗。能产生系统复位信号的计数器,递减的计数器时钟由独立的RC振荡器提供(可在待机和停止模式下运行)。看门狗被激活后,当递减计数器计数到0x000时产生复位。
喂狗原则:在计数器计数到0之前,重装载计数器的值,防止复位。
适用范围:主要用于检测外界电磁干扰,或硬件异常导致的程序跑飞问题。在一些需要高稳定性的产品中,并且对时间精度要求较低的场合(由于RC振荡器频率较低,由内部低俗时钟提供)。
工作原理:
12位计数器:最大值4096
溢出时间的计算:
本次实验的分频系数是256,计数个数是4096。所以复位时间是26.2144s
2.WWDG简介
Window watchdog,即窗口看门狗。能产生系统复位信号和提前唤醒中断的计数器。
两个复位方式:
1)递减的计数器 当递减计数器值从 0x40减到0x3F时复位(即T6位跳变到0)。
2)计数器的值大于W[6:0]值时喂狗会复位。
提前唤醒中断 (EWI):当递减计数器等于 0x40 时可产生。
喂狗原则:要想不产生复位,必须在窗口期喂狗。
适应场景:用于监测单片机程序运行时效是否精准,主要检测软件异常。需要精准检测程序运行时间的场合。
一些解释:最大的计数值是127,最大的窗口期上限也是127,复位复位值是63,所以最小窗口期是64。计数值初始值>=窗口期上限,并且计数值在初始值和窗口期上限之间的位置时进行喂狗,会产生复位(即第一个复位条件)。
本次实验的计数器初始值和窗口期上限值相同,即没有非窗口期。所以复位时间是58.25ms。
二、HAL库配置
1.时钟树的配置
参考:STM32 hal库使用笔记(一)GPIO的使用—流水灯_乱码小伙的博客-优快云博客
2.看门狗配置
2.1 独立看门狗(代码参考3.1)
2.2 窗口看门狗的设置(代码参考3.2)
两次实验均用到了串口打印,串口配置参考:STM32 hal库使用笔记(二)中断—串口中断_乱码小伙的博客-优快云博客z
定时器的配置参考:STM32 hal库使用笔记(二)中断—定时器中断_乱码小伙的博客-优快云博客
两次的定时器中断时间间隔不一样,不过效果都是1分钟复位一次,ARR和PSC的设置再代码编辑的时候补充。
三、代码编写
用户只需要定时进行“喂狗”操作即可。特别注意:看门狗初始化必须在定时器初始化之前。
3.1
修改定时的值,修改后定时器中断5s产生一次:
void MX_TIM6_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim6.Instance = TIM6;
htim6.Init.Prescaler = 11999;//修改
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
htim6.Init.Period = 29999;//修改
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_Base_Start_IT(&htim6);//用户添加
}
在定时器中断更新回调函数中进行“喂狗”:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static unsigned char i=0;
if (htim->Instance == TIM6)//5s进((12000*2000)/72000000)
{
i++;
if(i<=8)
{
HAL_IWDG_Refresh(&hiwdg);
}
}
}
实验现象:可以看出,1分钟系统复位一次(时间计算略有偏差,只做测试)
3.1
修改定时器的值,50ms进一次中断:
void MX_TIM6_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim6.Instance = TIM6;
htim6.Init.Prescaler = 7199;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
htim6.Init.Period = 499;
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_Base_Start_IT(&htim6);//用户添加
}
在定时器中断更新回调函数中进行“喂狗”:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static unsigned int i=0;
if (htim->Instance == TIM6)
{
i++;
if(i<=1198)
{
HAL_WWDG_Refresh(&hwwdg);
}
}
}
实验现象:可以看出,1分钟系统复位一次(时间计算略有偏差,只做测试)
四、IWDG和WWDG的比较
对比点 | 独立看门狗 | 窗口看门狗 |
时钟源 | LSI(40KHz或32KHz) | PCLK1或PCLK3 |
复位条件 | 递减计数到0 | 计数值大于W[6:0]值喂狗或减到0x3F |
中断 | 没有中断 | 计数值减到0x40可产生中断 |
递减计数器位数 | 12位(最大计数范围:4096~0) | 7位(最大计数范围:127~63) |
应用场合 | 防止程序跑飞,死循环,死机 | 检测程序时效,防止软件异常 |
欢迎大家交流和指正!!!