2010-11-09 184 views
4

这里在程序中,通过使用定时器中断&来循环使用LED,如果有人按下开关,它应该停止第一个中断&触发第二个应该根据开关点亮LED按下。在这里,我有点困惑,哪个中断被调用。我提到了一些针对变化中断的书籍&写了几行设置PCMSK2。所得到的输出是“最初所有的LED都是循环的,当按下一个开关时......再次启动LED循环(这意味着程序正在读输入,而不是触发第二次中断),它不停止或者暂停&后面的led不亮。“任何人都可以帮忙吗?引脚电平变化中断 - 带内部中断的外部中断

#include <avr/io.h> 
#include <avr/interrupt.h> 
#define PINK_MASK \ 
    ((1<<PINK0)|(1<<PINK1)|(1<<PINK2)|(1<<PINK3)|(1<<PINK4)|(1<<PINK5)|(1<<PINK6)|(1<<PINK7)) 


volatile unsigned int intrs, i=1; 

void enable_ports(void); 
void delay(void); 

extern void __vector_23 (void) __attribute__ ((interrupt)); 

extern void __vector_25 (void) __attribute__ ((signal)); 

void enable_ports() 
{ 
    DDRB = 0xff; //PORTB as output for leds 

    PORTB = 0xff; 

    DDRK = 0x00; //PORTK as input from switches 

    PORTK |= PINK_MASK; 

    PCMSK2 = PINK_MASK;  //ENABLE PCMSK2, Setting interrupts 

    PCICR = 0x04; 

    PCIFR = 0x04; 

    TCCR0B = 0x03;  //Setting TIMER 

    TIMSK0 = 0x01; 

    TCNT0 = 0x00; 

    intrs = 0; 
} 
void __vector_23 (void) 
{ 
    intrs++; 
    if(intrs > 60) 
    { 
     intrs = 0; 
     PORTB = (0xff<<i); 

     i++ ; 
     if(i == 10) 
     { 
      PORTB = 0xff; 
      i = 1 ; 
     } 
    } 
} 

void __vector_25 (void) 
{ 
    unsigned char switches; 

    switches = ((~PINK) & (PINK_MASK)); //Reading from switches 

    if(switches & (1<<PINK0)) 
     PORTB = (PORTB<<PINK0); 

    else if (switches & (1<<PINK1)) 
     PORTB = (PORTB<<PINK1); 

    else if (switches & (1<<PINK2)) 
     PORTB = (PORTB<<PINK2); 

    else if (switches & (1<<PINK3)) 
     PORTB = (PORTB<<PINK3); 

    else if (switches & (1<<PINK4)) 
     PORTB = (PORTB<<PINK4); 

    else if (switches & (1<<PINK5)) 
     PORTB = (PORTB<<PINK5); 

    else if (switches & (1<<PINK6)) 
     PORTB = (PORTB<<PINK6); 

    else if (switches & (1<<PINK7)) 
     PORTB = (PORTB<<PINK7); 
} 

int main(void) 
{ 
    enable_ports(); 
    sei(); 

    while(1) 
    { 

    } 
} 

感谢您的支持。

+0

任何人都请帮忙! – sneezy 2010-11-10 00:11:04

+0

对不起,我不使用AtmelμC。但是,也许你可以问http://embdev.net/ – AndreKR 2010-11-10 00:15:53

+1

你的目标是什么特定设备? – evilspacepirate 2011-01-09 15:17:17

回答

5

AVR架构中的外部中断令人困惑,但并非不可能。我发现最适合我的资源是AVR libc page on interrupts。我想你已经让代码太复杂了,无法实现你想要的功能。让我们从头开始:

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

void main() { 
    sei(); 
    while(1) {}; 
} 

AVR libc实际上使处理中断非常轻松。在上面链接的页面中,列出了每个AVR芯片上所有支持的中断向量。假设您使用的是Mega32,现在您希望使用定时器中断使LED闪烁。让我们添加到程序:

uint8_t led_state; 

ISR(TIMER0_COMP_vect) { 
    led_state = ~led_state; 
    PORTB = led_state; 
} 

void setup_timer_interrupt() { 
    TCCR0B = 0x03; 
    TIMSK0 = 0x01; 
    TCNT0 = 0x00; 
} 

这应该每天定时中断发生时闪烁在PORTB的指示灯。请注意,它应该设置的方式是使用ISR(...)宏;您正在使用的__vector_...调用已被弃用,并且更令人困惑。

最后,如果我正确理解你的问题,最后你想用一组开关来保持LED点亮。我实际上不会使用外部中断,只需在ISR(TIMER0_COMP_vect)期间使用PINK来读取开关的值,但我们可以根据需要使用它。我们需要添加以下代码:

uint8_t switch_state; 

void setup_switch_interrupt() { 
    // I'm assuming this code to enable external interrupts works. 
    DDRK = 0x00; 
    PORTK = 0xff; 
    PCMSK2 = 0xff; // set to all 1s 
    PCICR = 0x04; 
    PCIFR = 0x04; 
} 

ISR(INT0_vect) { 
    switch_state = PINK; 
} 

这是干什么的?我们将保持switch_state的开关状态,每次外部中断触发时都会读取(我猜你已经在0-> 1和1-> 0转换中发生了这种情况)。剩下的就是让LED输出取决于switch_state的值。我们将在计时器中断中执行此操作,因为那是我们迄今为止切换LED的地方。新版本看起来像:

ISR(TIMER0_COMP_vect) { 
    led_state = ~led_state | switch_state; 
    PORTB = led_state; 
} 

而且应该这样做!

脚注:我刚才说过,使用外部中断来读取开关并不是必须的。这是因为您可以在定时器中断期间使用PINK来读取开关值。你可以摆脱switch_statesetup_switch_interrupt()ISR(INT0_vect),只是修改定时器中断是这样的:

ISR(TIMER0_COMP_vect) { 
    led_state = ~led_state | PINK; 
    PORTB = led_state; 
} 

这应该使程序更简单一点。

0

所以无论如何,每次执行__vector_23时,都会通过增加i来分配指定给PORTB的LED。如果我明白你想要做什么,你应该做的只是在__vector_25,当按下开关时递增i

+0

那么我该写些什么呢? – sneezy 2010-11-10 00:29:53

+0

@sneezy,我想我在第一次回答时遇到了错误,请参阅我的编辑,其中包含一些更好的说明。 – 2010-11-10 00:32:13

+0

我没有看到__vector_25被调用。 – sneezy 2010-11-10 00:48:57