1

私はatmega168aチップを持っています。私は、サブルーチンを使用して割り込みCounter 0を切り替えるために使用します。when条件がtrueの場合にアクティブにします。だから、私はを使用しますが、この行は、カウンターが値になっているときにのみ16ビットタイマーを中断したい場合に、即座に割り込みを呼び出します。インスタント割り込みを発生させずに、ランタイムで16ビットタイマーをアクティブにするにはどうすればよいですか?PORTCISR(TIMER0_COMPA_vect)ISR(TIMERB_COMPA_vect)16-bit timerifTIMSK1 = (1<<OCIE1A)ISR(TIMER1_COMPA_vect)reachesOCR1A

これが私のコードです:

#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を瞬時に設定するため、割り込みを瞬時に設定したくない理由を示すオシロスコープの出力です。 ここに画像の説明を入力してください

4

1 に答える 1

3

OCF1A問題は、CTC モードで、フラグが設定されたときに割り込みが生成されることであると考えられます( でTIFR)。タイマーは常に実行されており、割り込みを生成していないため、OCF1Aクリアされることのないフラグを設定します。データシートの 142 ページには、次のように書かれています。

OCF1B は、出力コンペア一致 B 割り込みベクトルが実行されると自動的にクリアされます。または、OCF1B のビット位置に論理 1 を書き込むことによって、OCF1B をクリアできます。

これは、タイマー 1 を設定するときに、以下もクリアする必要があることを意味しますOCF1A

TIFR1 &= ~(1<<OCF1A)

しかし、私はあなたがもっとうまくやれると思います。TIMSKいじってタイマー1を常に実行する代わりに、必要のないときにタイマーを停止し、必要なときに開始することができます。ゼロに設定すると、 、、およびTCCR1Bがクリアされます。これは、データシートによると、「タイマーが停止した」ことを意味します。次に、カウンターが 4 に達したら、上記のように timer1 をオンにできます。CS12CS11CS10

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

これを行う場合、タイマー 1 割り込みをオンまたはオフにする必要はありません。オンのままにして、必要なときにのみカウントをオンにします。

また、ピンをオンに切り替えるために実際に2つの割り込みを発生させる必要があるかどうか疑問に思っていますPORTCか? パルス長が十分に正確に得られないため、そのために PWM を使用していませんか?

于 2013-03-09T18:54:54.280 に答える