AVR C不会运行中断

时间:2014-11-14 21:43:14

标签: interrupt avr avr-gcc

我正在摆弄我的MEGA-1284p套件和avr工作室,我需要一些帮助解决问题。我需要它按下按钮SW0上的LED3。

这是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的功能永远不会被召唤。

4 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

您需要禁用看门狗定时器或定期执行看门狗定时器复位(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();
}

答案 2 :(得分:0)

这可能不是您代码中的主要问题,但首先突然出现的是您在中断服务程序中遇到的大量延迟

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陷入困境。

我希望这会有所帮助。

答案 3 :(得分:0)

而不是:

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

你只能写: PORTB ^ = 0x04;