AVR C 不会运行中断



我正在摆弄我的MEGA-1284p套件和avr工作室,我需要一些帮助来解决问题。我需要它在按下 SW3 按钮时切换 LED0。

这是 AVR C 代码:

#define F_CPU 11059200UL // The Xplained kit runs at 11.0592 MHz
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
int ex37() {
    DDRB = 0x04;// LED3 as output
    PORTB = 0x04; //LED3 off    
    EIMSK |= (1<<INT0) | (0<<INT1) | (0<<INT2); // Enable external interrupt 0 (SW0)
    MCUCR |= (1<<ISC01) | (1<<ISC00); // INT0 on rising edge.
    sei(); // Start interrupts
    _delay_ms(1000); //wait 1000 ms = 1 sec
    PORTB = 0x00; //LED3 on
    _delay_ms(1000); //wait 1000 ms = 1 sec
    PORTB = 0x04; //LED3 off
    while(1) {  
    };
    return 0;
}
ISR(INT0_vect) {
    _delay_ms(1000); //wait 1000 ms = 1 sec
    if (PORTB == 0x04){
        PORTB = 0x00;
    } else {
        PORTB = 0x04;
    }
}

但据我所知,改变 LED3 的功能从未被调用过。

SW0连接到PB0,这不是任何外部中断处于活动状态的引脚。

相反,您需要使用引脚更改中断,PCIE1并正确配置它。有关寄存器说明,请参阅数据表。

您需要禁用看门狗定时器或定期执行看门狗定时器复位 (WDR) 指令。否则,控制器将在过期时重置。数据手册给出了禁用它的代码:

void WDT_off(void)
{
    __disable_interrupt();
    __watchdog_reset();
    /* Clear WDRF in MCUSR */
    MCUSR &= ~(1<<WDRF);
    /* Write logical one to WDCE and WDE */
    /* Keep old prescaler setting to prevent unintentional
    time-out */
    WDTCSR |= (1<<WDCE) | (1<<WDE);
    /* Turn off WDT */
    WDTCSR = 0x00;
    __enable_interrupt();
}

这可能不是您的代码中的主要问题,但首先想到的是中断服务例程中的巨大延迟

ISR(INT0_vect) {
_delay_ms(1000); //wait 1000 ms = 1 sec
if (PORTB == 0x04){
    PORTB = 0x00;
} else {
    PORTB = 0x04;
}
}

整一秒对于微控制器来说是一个非常非常长的时间。 正如有人提到的,您的看门狗计时器很可能超时了。 与其摆弄看门狗启用/禁用,不如考虑先重写 ISR,看看是否能解决您的问题。

通常,最好使用尽可能短的 ISR 编写代码。我建议使用 ISR 来创建一个标志,并在您的while(1)循环中对其进行响应。 现在您的 ISR 延迟 1 秒可能不会引起问题,但一旦事情开始累积,它真的可能会使您的 MCU 陷入困境。

我希望这有所帮助。

而不是:

if (PORTB == 0x04){
    PORTB = 0x00;
} else {
    PORTB = 0x04;
}

您只能编写:端口 ^= 0x04;

最新更新