You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何中断模式下的Watchdog仍导致Arduino Mega 2560复位?

环境

我正在使用Arduino Mega 2560,以下是源代码:

#ifndef F_CPU
#define F_CPU 16000000L
#endif

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>

void start_system_timer(void)
{
    cli();
    
    // 清除WDRF标志,避免超时复位循环
    MCUSR &= ~(1<<WDRF);
    // 复位看门狗定时器
    wdt_reset();
    // 启用看门狗配置模式
    WDTCSR |= 1 << WDCE | 1 << WDE;
    // 重置看门狗定时器寄存器
    WDTCSR = 0;
    // 配置超时周期
    wdt_enable(WDTO_1S);
    // 设置看门狗为中断模式
    WDTCSR |= 1 << WDIE;

    sei();
}

int main(void)
{
    // 将PORTB7设为输出并点亮LED
    DDRB |= (1<<PB7);
    PORTB |= (1<<PB7);
    
    start_system_timer();
    sei();

    while (1)
    {
    }
}

ISR (WDT_vect, ISR_NAKED)
{
    // 关闭LED
    PORTB &= ~(1<<PB7);
    
    // 重新启用看门狗中断以避免复位
    WDTCSR |= 1 << WDIE;
    
    reti();
}

问题

我把看门狗定时器设置为中断模式,但不在中断处理函数中复位定时器时,设备还是会复位。根据数据手册,处于中断模式时不应该触发系统复位。我还试过在设置中断模式后清除WDIE位(WDTCSR &= ~(1<<WDIE);),但还是解决不了问题。


问题原因及解决方案

你的代码存在两个核心问题,导致看门狗触发了复位:

  1. wdt_enable()的默认行为:调用wdt_enable(WDTO_1S)时,会同时启用看门狗的复位模式(WDE位被置1)。此时即使后续设置了WDIE位,看门狗实际处于「中断+复位」的组合模式——第一次超时触发中断,第二次超时就会触发系统复位。

  2. 中断处理逻辑缺失:中断触发后,WDIE位会被硬件自动清零,且你没有复位看门狗计数器。即使是中断模式,若不重置计数器,下一次超时依然会触发预设的动作(组合模式下就是复位)。

修正步骤:

  • 切换为纯中断模式配置:放弃使用wdt_enable(),直接手动配置WDTCSR寄存器,确保WDE位为0(禁用复位)、WDIE位为1(启用中断):
    替换start_system_timer()中的wdt_enable(WDTO_1S);和WDTCSR |= 1 << WDIE;为以下代码:

    // 进入看门狗配置模式
    WDTCSR = (1 << WDCE) | (1 << WDE);
    // 配置1秒超时、仅中断模式(WDP2|WDP1对应1秒分频,WDE=0禁用复位)
    WDTCSR = (1 << WDIE) | (1 << WDP2) | (1 << WDP1);
    
  • 在中断中复位看门狗:每次触发中断后,必须调用wdt_reset()重置计数器,避免后续超时触发复位。修改中断函数:

    ISR (WDT_vect, ISR_NAKED)
    {
        wdt_reset(); // 复位看门狗计数器
        PORTB &= ~(1<<PB7); // 关闭LED
        WDTCSR |= 1 << WDIE; // 重新启用中断
        reti();
    }
    
  • 删除冗余代码:start_system_timer()末尾已调用sei(),main()中的重复调用可删除。

修正后的start_system_timer()函数:

void start_system_timer(void)
{
    cli();
    
    MCUSR &= ~(1<<WDRF); // 清除看门狗复位标志
    wdt_reset(); // 初始复位看门狗
    
    // 进入配置模式
    WDTCSR = (1 << WDCE) | (1 << WDE);
    // 配置纯中断模式+1秒超时
    WDTCSR = (1 << WDIE) | (1 << WDP2) | (1 << WDP1);

    sei();
}

配置完成后,看门狗只会触发中断,不会触发系统复位,只要在中断中及时复位计数器,即可维持正常运行。

内容的提问来源于stack exchange,提问作者itasahobby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 06:05:33