2010-11-09 188 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