2013-03-09 109 views
1

我有一個atmega168a芯片。我使用Counter 0通過使用ISR(TIMER0_COMPA_vect)ISR(TIMERB_COMPA_vect)中斷子例程來切換PORTC。當if條件成立時,我想激活16-bit timer。所以,我使用TIMSK1 = (1<<OCIE1A),但是這行呼籲ISR(TIMER1_COMPA_vect)立即中斷我想要的16位定時器只有當計數器reachesOCR1A值被中斷。如何在運行時激活16位定時器而不引起即時中斷?如何在AVR編程中激活16位定時器

這裏是我的代碼:

#define F_CPU 8000000 
#include <avr/io.h> 
#include <avr/interrupt.h> 
#include <stdint.h> 

volatile uint8_t counter; 

int main (void){ 
    DDRC = 0xFF; //sets PORTC as output 
    PORTC = 0xFF; //initial output value 
    /*COUNTER0 settings*/ 
    TIMSK0 = ((1<<OCIE0A) | (1<<OCIE0B)); // Enable Interrupt TimerCounter0 Compare Match A & B 
    TCCR0A = (1<<WGM01); // Mode = CTC 
    TCCR0B = (1<<CS01) | (1<<CS00); // Clock/64, 1/(8000000/64)= 0.000008 seconds per tick 
    OCR0A = 200;  // 0.000008 *230 = 1.6 ms 
    OCR0B = 100;  //  0.8 ms 

    /*16bit timer - counter1 settings*/ 
    TIMSK1 &= ~(1<<OCIE1A); // Disable Interrupt Counter 1, output compare A (TIMER1_CMPA_vect) 
    TCCR1B = ((1<<CS12) | (1<<CS10) | (1<<WGM12)); // Clock/1024, 1/(8000000/1024) = 0.000128 seconds per tick, Mode=CTC 
    OCR1A = 40;      // 0.000128*40 ~= 5.12 milliseconds 

    sei(); //interrupts are globally switched on 
    counter =0; 
    while(1){ 
     if(counter >= 4){ 
      TCNT1 = 0; // clear the counter 1 
      TIMSK1 = (1<<OCIE1A);// Enables the interrupt for Counter 1,(TIMER1_CMPA_vect) 
      TIMSK0 &= ~((1<<OCIE0A) | (1<<OCIE0B)); //disables the Counter 0's interrupts 
      counter = 0; 
     } 
    } 
    return 0; 
} 

ISR(TIMER0_COMPA_vect){ //1.6ms 
    PORTC = 0xFF; 
    counter++; 
} 

ISR(TIMER0_COMPB_vect){ //0.8 ms 
    PORTC = ~PORTC; 
} 

ISR(TIMER1_COMPA_vect){ // 5.2 milisecond interrupt 
    PORTC = 0x00; 
    TCNT0 = 0; //clear the counter of counter0 
// TIMSK0 = ((1<<OCIE0A) | (1<<OCIE0B)); //Enable the Counter 0 interrupts 
// TIMSK1 &= ~(1<<OCIE1A);// Disable Interrupt Counter 1, output compare A (TIMER1_CMPA_vect) 
} 

這裏是一個示波器輸出顯示了爲什麼我不希望中斷被立即設置,因爲它設置信號0立即做。 enter image description here

回答

2

我想這個問題可能是,在CTC模式,產生中斷時OCF1A標誌設置(在TIFR)。由於您的計時器始終運行,只是不產生中斷,所以它會設置OCF1A標誌,該標誌永遠不會被清除。在數據表的第142頁上它說:

當執行中斷向量時,OCF1B自動清零。或者,OCF1B可以通過 向其位位置寫入邏輯1來清除。

這意味着,當您設置定時器1,您還需要明確OCF1A

TIFR1 &= ~(1<<OCF1A) 

不過,我覺得你可以做的更好。您可以在不需要時停止計時器,然後在啓動時啓動計時器,而不是撥打TIMSK並讓計時器1始終運行。如果將TCCR1B設置爲零,則清零CS12,CS11CS10,其中根據數據表意思是「計時器已停止」。然後,當您的計數器達到4您可以打開定時器1,你有上面:

TCCR1B = ((1<<CS12) | (1<<CS10) | (1<<WGM12)); 

如果你這樣做,你不應該需要打開定時器1和關閉:剛剛離開他們,和只有在你需要時才能打開計數。

另外我想知道是否實際上有必要發起兩個中斷來切換PORTC上的引腳?你是否沒有使用PWM,因爲它沒有給你足夠精確的脈衝長度?

+0

非常感謝你,現在它工作正常。它不是一個完整的代碼,我打算使用16位定時器來阻塞信號輸出幾毫秒。我只是在試驗上面的代碼。 – johan 2013-03-09 19:06:20

+0

非常好。很高興現在可以工作。 – angelatlarge 2013-03-09 19:08:08