2014-10-31 39 views
0

我正在使用AVR Studio5編程atmega328p的arduino uno rev3。現在,我試圖在1秒內連續閃爍一次led。 的代碼是:以C語言連續閃爍1秒(atmega328p)

PORTD = 0b10001010; 
    TCNT1H = 0xBB; 
    TCNT1L = 0xBB; 
    TCCR1A = 0; 
    TCCR1B = 5; // prescaler is 1024 
    while((TIFR1 & (1<<TOV1)) == 0) 
    { 
     temp = TCNT1H; 
     while ((TCNT1H - temp) >= 11); 
     PORTD ^= 1<<7; // blinking as expected 
    } 
    TIFR1 = 1<<TOV1; 
    TCCR1A = 0; 
    TCCR1B = 0;  

上面的代碼顯示,我使用一個定時器1持續1秒中,我試圖閃爍PORTD.7導致每個0.032768s。 但是,現在,問題是計時器延遲1秒,但led保持點亮不閃爍。請幫忙 。 (P.S電路工作正常)

補充: 如果我使用下面的代碼,它顯示了led閃爍。

for (a = 0;a<2;a++) 
{ 
    PORTD = 0b00001010; 
    TCNT1H = 0xEE; 
    TCNT1L = 0xEE; 
    TCCR1A = 0; 
    TCCR1B = 5; // prescaler is 1024 
    while((TIFR1 & (1<<TOV1)) == 0); 
    TIFR1 = 1<<TOV1; 
    TCCR1A = 0; 
    TCCR1B = 0; 

    PORTD = 0b10001010; 
    TCNT1H = 0xEE; 
    TCNT1L = 0xEE; 
    TCCR1A = 0; 
    TCCR1B = 5; // prescaler is 1024 
    while((TIFR1 & (1<<TOV1)) == 0); 
    TIFR1 = 1<<TOV1; 
    TCCR1A = 0; 
    TCCR1B = 0; 
} 

但是,爲了簡單起見,我更喜歡最頂級的方法,如果工作。

+0

你可以使用usleep函數嗎?一些更多的信息:http://pubs.opengroup.org/onlinepubs/009695399/functions/usleep.html – MiltoxBeyond 2014-10-31 07:10:56

+0

@MiltoxBeyond我猜他沒有一個操作系統。 – RedX 2014-10-31 07:13:54

+0

如果OP使用'avr-gcc',可以使用'util/delay.h'中的'_delay_ms'函數來實現一個簡單的延遲。 – ouah 2014-10-31 07:16:21

回答

2
while ((TCNT1H - temp) >= 10) 
    { 
     PORTD ^= 1<<7; // blinking as expected 
    } 

你眨眼太快,太快了,實際上你看到的是一個半亮度的LED。您需要在兩個調用PORTD ^= 1<<7之間添加一些延遲。

+0

我重寫 「而((TCNT1H - 溫度)> = 10){ PORTD ^ = 1 << 7; //閃爍如預期 }」 到「,而((TCNT1H - 溫度)> = 30); \t \t \t PORTD^= 1 << 7;「做出更大的時間間隔,但它沒有幫助。 – 2014-10-31 07:20:20

0

這是應該用中斷來完成的事情。

void TMR_init(void) 
{ 
    DDRD|=_BV(PD7); //bit 7 of port D to output 
    TCNT1=0; //reset the timer counter 
    OCR1AL=0xC6; //depends on your osc. This values are for 12MHz 
    OCR1AH=0x2D; //with 12 000 000Hz/1024 it takes 11718 ticks for 1 sec->0x2D C6 
    TIMSK1|=_BV(OCIE1A); //enable interrupt on output compare A (when timer value == value in the OCR1AL/H-registers) 
    TCCR1A=0; //normal operation 
    TCCR1B=_BV(CS12) | _BV(CS10); //prescaler 1024 and starts the timer 

    sei(); //enable interrupts 
} 

//isr 
SIGNAL(TIMER1_COMPA_vect) 
{ 
    PORTD^=_BV(PD7); //toggle  
} 

此代碼應該工作,但未經測試。不要忘記包含avr/interrupt.h。由於編譯器的版本差異,某些宏可能會有所不同。