2010-11-04 20 views
3

對於過去兩週幫我努力學習計時器&中斷&寫了一個程序(我的理解)閃爍的ATMEGA2560的LED,但無論我做什麼TCNT0從未遞增& ISR()函數不會被調用。我在哪裏出錯了,我該如何解決?這裏是我的代碼:需要用定時器

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

#define READ_ATMEGA(ADDR) *((P_CHAR)(BASE_ADDR + ((ADDR) * ADDR_MULTIPLIER))) 
#define WRITE_ATMEGA(ADDR, DATA) *((P_CHAR)(BASE_ADDR + ((ADDR) * ADDR_MULTIPLIER))) = DATA 

#define BASE_ADDR 0x20 

void init_timer0_ovf_interrupt(void); 
void timer0_interrupt_isr(void); 
void initialize_ports(void); 
void delay(unsigned int no_65_5ms_interrupts); 

void __attribute__((ISR)) timer0_interrupt_isr(void); 

//#pragma interrupt_handler timer0_interrupt_isr:24 

unsigned int delay_timer; 

int main(void) 
{ 
    initialize_ports(); 
init_timer0_ovf_interrupt(); 
delay(46); 
return 0; 
    } 

void initialize_ports(void) 
{ 
    READ_ATMEGA(4) = 0xff; 
    WRITE_ATMEGA(5, 0x00); 
} 

void delay(unsigned int no_65_5ms_interrupts) 
{ 
    TCNT0 = 0x00; 
    delay_timer = 0; 
    while(delay_timer <= no_65_5ms_interrupts) 
    { 
    ; 
    } 
} 

void init_timer0_ovf_interrupt(void) 
{ 
    TCCR0A = 0X00; 
    TCCR0B = 0x02; 
    TIMSK0 = 0x01; 
    TIFR0 = 1<<0; 
    OCR0A = 25; 
    sei(); 
} 

void timer0_interrupt_isr(void) 
{ 
    delay_timer++; 
    if(delay_timer >= OCR0A) 
    { 
    PORTB = ~(PORTB); 
    delay_timer = 0; 
    } 
} 
+0

僅供參考要格式化代碼塊,請選擇它並單擊代碼按鈕;看起來像二進制數字的那個。 – meagar 2010-11-04 17:40:46

+0

當然,謝謝你的信息。 – sneezy 2010-11-04 18:11:34

回答

1

3 -4天前,我寫了相同的程序有點不同&得到的LED閃爍,但仍不確定是否使用定時器&中斷的正確方法。任何人都可以看到這個&告訴我它是否正確?我設法通過讀取定時器,中斷程序來編寫這個程序。

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

volatile uint8_t intrs; 

ISR(TIMER0_OVF_vect) { 
    /* this ISR is called when TIMER0 overflows */ 
    intrs++; 

    /* strobe PORTB.5 - the LED on arduino boards */ 
    if (intrs >= 61){ 
     PORTB = ~PORTB; 
     intrs = 0; 
    } 

} 


int main(void) { 

    TCCR0B = 0x02; 

    /* Enable Timer Overflow Interrupts */ 
    TIMSK0 = 0x01; 

    /* other set up */ 
    DDRB = 0xff; 
    TCNT0 = 0; 
    intrs = 0; 

    /* Enable Interrupts */ 
    sei(); 

    while (1) 
     ; /* empty loop */ 
} 

如果這是正確的方法,那麼我可以開始下一步的工作。

謝謝

+0

我對Atmega/Arduino產品並不熟悉,所以我不能肯定地說,但看起來你正在設置定時器頻率(TCCROB ),啓用定時器中斷(TIMSK0),復位計數器(TCNT0)和啓用系統中斷(sei)。這應該是獲得定時器工作所需的一切。至於你原來的程序,我不知道爲什麼它不起作用,因爲你似乎設置了所有相同的寄存器,再加上幾個。也許在你的原始程序中,timer0_interrupt_isr與定時器溢出中斷沒有正確關聯? – 2010-11-09 14:57:21

0

如果可能,在延時功能while循環沒有做任何事情,也不會增加delay_timer所以你是停留在一個無限循環:

void delay(unsigned int no_65_5ms_interrupts) 
{ 
    TCNT0 = 0x00; 
    delay_timer = 0; 
    while(delay_timer <= no_65_5ms_interrupts) 
    { 
    ; //Nothing is happening here!! 
    } 
} 
1

的全局變量delay_timer在中斷代碼和非中斷代碼之間共享。應該聲明爲volatile,因爲值可以在delay()以外更改。

如果你看一下生成的代碼delay()你可能會看到,而在while環紡紗是delay_timer的價值沒有被重新讀取。

另外,volatile是不夠的。你有非中斷代碼和中斷代碼都寫入相同的變量(delay_timer)。您需要在非中斷代碼中保護對變量的寫入,這裏存在競爭條件。簡單/懶惰的方式是禁止中斷&在非中斷代碼中恢復它們。

(至於設置你的中斷&開始你的計時器,這些信息應該是在芯片的數據表,通常就是這樣更容易得到正確的部分,它是共享數據的東西,叮咬人。)

+0

因爲我明天就要提交這個項目,所以我實際上已經嚇壞了,而且我仍然不完全理解定時器和中斷。 (這不是我必須提交的實際項目)。我必須鏈接LED和開關,通過LED循環,並在按下開關時...使用定時器和中斷點亮適當的LED並且不使用「avr」頭文件。 Dan ..你在帖子中提到的,我還在想它 – sneezy 2010-11-04 20:38:33