簡體   English   中英

如何在AVR編程上激活16位定時器

[英]how to activate 16bit timer on AVR programming

我有一個atmega168a芯片。 我使用Counter 0通過使用ISR(TIMER0_COMPA_vect)ISR(TIMERB_COMPA_vect)中斷子程序來切換PORTC if條件為真,我想激活16-bit timer 因此,我使用TIMSK1 = (1<<OCIE1A) ,但此行立即調用ISR(TIMER1_COMPA_vect)中斷,我希望只有當計數器reaches OCR1A值時才會中斷16位定時器。 如何在運行時激活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。 在此輸入圖像描述

我認為問題可能是在CTC模式下,當設置OCF1A標志時(在TIFR )會產生中斷。 由於您的定時器始終在運行,只是沒有產生中斷,因此它會設置OCF1A標志,該標志永遠不會被清除。 在數據表的第142頁上,它說:

執行輸出比較匹配B中斷向量時,OCF1B自動清零。 或者,可以通過將邏輯1寫入其位位置來清除OCF1B。

這意味着當您設置計時器1時,您還需要清除OCF1A

TIFR1 &= ~(1<<OCF1A)

但是,我認為你可以做得更好。 您可以在不需要時停止計時器,並在執行時啟動計時器,而不是整理TIMSK並始終運行計時器1。 如果將TCCR1B設置為零,則清除CS12CS11CS10 ,根據數據表顯示“定時器已停止”。 然后,當你的計數器達到4時,你可以打開上面的計時器1:

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

如果這樣做,你不需要打開和關閉定時器1中斷:只需打開它們,只在你需要時打開計數器。

另外,我想知道是否真的有必要在PORTC上觸發兩個中斷來切換引腳? 你沒有使用PWM,因為它沒有給你足夠的脈沖長度嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM