第7章 窗口看门狗实验

第七章 窗口门狗(WWDG)实验

1. 硬件设计

本实验用到的硬件资源有:

  • 指示灯DS0和DS1

  • 窗口看门狗

其中指示灯前面介绍过了,窗口看门狗属于 STM32F4 的内部资源,只需要软件设置好即可正常工作。我们通过 DS0 和 DS1 来指示 STM32F4 的复位情况和窗口看门狗的喂狗情况。

2. 软件设计

2.1 看门狗初始化函数

void WWDG_Init(u8 tr,u8 wr,u32 fprer)
{
    WWDG_Handler.Instance = WWDG;               // 选择WWDG外设
    WWDG_Handler.Init.Prescaler = fprer;        // 设置分频系数
    WWDG_Handler.Init.Window = wr;              // 设置窗口值
    WWDG_Handler.Init.Counter = tr;             // 设置计数器值
    WWDG_Handler.Init.EWIMode = WWDG_EWI_ENABLE;// 使能提前唤醒中断
    HAL_WWDG_Init(&WWDG_Handler);               // 初始化WWDG
}
  1. u8 tr: 计数器初值。WWDG计数器的起始值,值越大,看门狗重置的时间越长。
  2. u8 wr: 窗口值。WWDG的窗口值,必须大于计数器值,用于监控计数器是否在规定范围内,以避免重置。
  3. u32 fprer: 分频系数。决定WWDG计数器的时钟频率。通常是一个预分频值,用于调整计数器的计数频率。

代码功能:

  • WWDG_Handler.Instance = WWDG; 选择使用WWDG外设。
  • WWDG_Handler.Init.Prescaler = fprer; 设置分频系数。
  • WWDG_Handler.Init.Window = wr; 设置窗口值。
  • WWDG_Handler.Init.Counter = tr; 设置计数器初值。
  • WWDG_Handler.Init.EWIMode = WWDG_EWI_ENABLE; 使能提前唤醒中断。
  • HAL_WWDG_Init(&WWDG_Handler); 调用初始化函数配置WWDG。

2.2 看门狗时钟及中断配置

void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
{   
    __HAL_RCC_WWDG_CLK_ENABLE();         // 使能窗口看门狗时钟
    // NVIC中断设置
    HAL_NVIC_SetPriority(WWDG_IRQn,2,3); // 抢占优先级2,子优先级为3
    HAL_NVIC_EnableIRQ(WWDG_IRQn);       // 使能窗口看门狗中断
}
  1. __HAL_RCC_WWDG_CLK_ENABLE();: 使能WWDG外设的时钟。这是必须的步骤,以确保WWDG模块的正常工作。

  2. HAL_NVIC_SetPriority(WWDG_IRQn,2,3);: 设置WWDG中断的优先级。2是抢占优先级,3是子优先级,这决定了中断处理的优先顺序。

  3. HAL_NVIC_EnableIRQ(WWDG_IRQn);: 使能WWDG中断请求,确保中断能够被处理。

2.3 窗口看门狗中断服务函数

// 窗口看门狗中断服务函数
void WWDG_IRQHandler(void)
{
    HAL_WWDG_IRQHandler(&WWDG_Handler); // 调用WWDG共用中断处理函数
}
// 中断服务函数处理过程
// 此函数会被HAL_WWDG_IRQHandler()调用
void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef* hwwdg)
{
    HAL_WWDG_Refresh(&WWDG_Handler); // 更新窗口看门狗值
    LED1 = !LED1; 
}

2.4 主函数

int main(void)
{
  HAL_Init();                   // 初始化HAL库    
  Stm32_Clock_Init(336,8,2,7);  // 设置时钟,168Mhz
  delay_init(168);              // 初始化延时函数
  uart_init(115200);            // 初始化USART
  LED_Init();                   // 初始化LED    
  KEY_Init();                   // 初始化按键
  LED0 = 0;                     // 点亮LED0
  delay_ms(300);                // 延时300ms再初始化看门狗,LED0的变化"可见"
  WWDG_Init(0X7F,0X5F,WWDG_PRESCALER_8); // 计数器值为7F,窗口寄存器为5F,分频数为8
  while(1)
  {    
      LED0 = 1; // 熄灭DS0 
  }
}

该函数通过 LED0(DS0)来指示是否正在初始化。而 LED1(DS1)用来指示是否发生了中断。我们先让 LED0 亮 300ms,然后关闭以用于判断是否有复位发生了。在初始化 WWDG 之后,我们回到死循环,关闭 LED1,并等待看门狗中断的触发/复位。

3. 小结

我们再来简单复习一下WWDG吧:

  1. 基本概念:
  • WWDG会在设定的时间内进行计数。如果计数达到预设值而没有被“喂养”或重置,系统将会复位。
  • 窗口看门狗的“窗口”机制意味着在特定的时间范围内,重载计数器的操作必须在一个有效的时间区间内完成。
  1. 窗口概念:
  • 窗口看门狗有一个“窗口”时间。在这个窗口内,系统必须在每次计数周期内发送重载命令。
  • 如果在窗口外进行重载(即太早或太晚),则不会重置计数器,系统将会复位。
  1. 应用流程:
  • 系统启动后,WWDG开始计数。
  • 在计数器到达一定值之前,主程序需要在窗口期内重载WWDG。
  • 如果未能在窗口内重载,WWDG将触发复位。

示例代码如下:

#include "main.h"

// 初始化WWDG
void WWDG_Init(void) {
    // 启用WWDG时钟
    __HAL_RCC_WWDG_CLK_ENABLE();
    // 配置WWDG
    WWDG_HandleTypeDef hwwdg;
    hwwdg.Instance = WWDG;
    hwwdg.Init.Prescaler = WWDG_PRESCALER_8;     // 设置预分频器
    hwwdg.Init.Window = 64;                      // 设置窗口大小
    hwwdg.Init.Counter = 127;                    // 设置计数器初始值

    if (HAL_WWDG_Init(&hwwdg) != HAL_OK) 
    {
        // 初始化错误处理
        Error_Handler();
    }
}

// 重载WWDG计数器
void WWDG_Refresh(void) 
{
    HAL_WWDG_Refresh(&hwwdg);
}

// 主函数
int main(void) {
    // 初始化HAL库
    HAL_Init();  
    // 系统时钟配置
    SystemClock_Config();
    // 初始化WWDG
    WWDG_Init();
    // 主循环
    while (1) 
    {
        // 执行其他任务
        // ...
        // 定期重载WWDG
        WWDG_Refresh();    
        // 小延迟,模拟其他操作
        HAL_Delay(100); // 根据需求调整延迟
    }
}

// 错误处理函数
void Error_Handler(void) 
{
    // 用户可以添加自己的错误处理代码
    while (1) {
        // 错误状态下的处理
    }
}

4. 独立与窗口看门狗同时工作

实验目标

  1. 使用独立看门狗监控系统的总体健康状况。
  2. 使用窗口看门狗监控关键任务的执行时间。
  3. 在窗口看门狗即将超时前触发中断,并在中断服务程序中执行特定逻辑。

硬件需求

  • STM32微控制器开发板
  • LED(用于指示状态)
  • 按钮(用于模拟故障)

实验步骤

  1. 初始化看门狗:
  • 配置独立看门狗(IWDG)。
  • 配置窗口看门狗(WWDG),并使能中断。
  1. 主循环:
  • 定期喂独立看门狗。
  • 在正常情况下,定期喂窗口看门狗。
  • 模拟故障时,停止喂狗。
  1. 中断处理:
  • 在窗口看门狗中断中,执行恢复操作,如重启某个任务或记录错误。

代码示例

以下是一个基于STM32 HAL库的代码示例:

#include "stm32f4xx_hal.h"

IWDG_HandleTypeDef hiwdg;
WWDG_HandleTypeDef hwwdg;

// LED和按钮的引脚配置
#define LED_PIN GPIO_PIN_5
#define BUTTON_PIN GPIO_PIN_13

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_IWDG_Init(void);
static void MX_WWDG_Init(void);

void WWDG_IRQHandler(void)
{
    // 窗口看门狗中断处理
    HAL_WWDG_ClearFlag(&hwwdg);    
    // 执行你的处理逻辑,比如重启任务
    HAL_GPIO_TogglePin(GPIOA, LED_PIN); // 切换LED状态
}

int main(void) 
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_IWDG_Init();
    MX_WWDG_Init();
    while(1) 
    {
        // 喂独立看门狗
        HAL_IWDG_Refresh(&hiwdg);
        // 正常情况下喂窗口看门狗
        HAL_WWDG_Refresh(&hwwdg);
        // 模拟故障,例如按下按钮
        if(HAL_GPIO_ReadPin(GPIOC, BUTTON_PIN) == GPIO_PIN_RESET) 
        {
            // 不喂窗口看门狗,模拟故障
        }
        HAL_Delay(100); // 延迟以避免频繁喂狗
    }
}

static void MX_IWDG_Init(void) 
{
    hiwdg.Instance = IWDG;
    hiwdg.Init.Prescaler = IWDG_PRESCALER_64; // 设置预分频器
    hiwdg.Init.Reload = 4095; // 设置重载值
    HAL_IWDG_Init(&hiwdg);
}

static void MX_WWDG_Init(void) 
{
    hwwdg.Instance = WWDG;
    hwwdg.Init.Prescaler = WWDG_PRESCALER_8; // 设置预分频器
    hwwdg.Init.Window = 80; // 设置窗口值
    hwwdg.Init.Counter = 127; // 设置初始计数值
    HAL_WWDG_Init(&hwwdg);
    HAL_NVIC_SetPriority(WWDG_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(WWDG_IRQn); // 使能中断
}

static void MX_GPIO_Init(void) 
{
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // LED引脚配置
    GPIO_InitStruct.Pin = LED_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 按钮引脚配置
    GPIO_InitStruct.Pin = BUTTON_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

void SystemClock_Config(void) 
{
    // 系统时钟配置代码
}

2024.9.30 第一次修订,后期不再维护

posted @ 2024-09-30 13:38  hazy1k  阅读(34)  评论(0编辑  收藏  举报