2014-11-14 3 views
0

Я играю с моим набором MEGA-1284p и студией avr, и мне нужна какая-то помощь в решении проблемы. Мне нужно, чтобы переключить светодиод 3 на кнопку SW0.AVR C не будет прерывать прерывание

Вот код 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 никогда не вызывается до тех пор, как я могу сказать.

ответ

2

SW0 подключен к PB0, который не является штифт, что какой-либо из внешних прерываний активны.

Вместо этого вам необходимо использовать прерывание смены контактов, PCIE1 и настроить его правильно. См. datasheet для описания регистров.

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(); 
} 
+0

Это решение, похоже, дает мне некоторые ошибки: неопределенная ссылка на '__disable_interrupt '..., неопределенная ссылка на' __watchdog_reset' ..., неопределенная ссылка на '__enable_interrupt '.... Знаете ли вы, что происходит не так? – Johannes

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). Наличие 1-секундной задержки в вашем ISR может не вызвать проблем сейчас, но это может привести к потере вашего MCU, когда все начнет складываться.

Надеюсь, это поможет.

0

Вместо:

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

вы можете написать только: PORTB = 0x04;