1

我有一个 atmega168a 芯片。我使用通过使用和中断子例程Counter 0来切换。我想激活条件为真时。所以,我使用,但是这条线立即调用中断,我希望 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

我认为问题可能是在 CTC 模式下,OCF1A设置标志时会产生中断(在 中TIFR)。由于您的计时器始终在运行,只是不产生中断,因此它设置了OCF1A标志,该标志永远不会被清除。在数据表的第 142 页上,它说:

当执行输出比较匹配 B 中断向量时,OCF1B 会自动清零。或者,可以通过将逻辑 1 写入其位位置来清除 OCF1B。

这意味着当您设置计时器 1 时,您还需要清除OCF1A

TIFR1 &= ~(1<<OCF1A)

不过,我认为你可以做得更好。您可以在不需要时停止计时器,并在需要时启动它,而不是TIMSK一直在运行并让计时器 1 运行。如果您设置TCCR1B为零,则清除CS12CS11CS10,根据数据表,这意味着“定时器停止”。然后,当您的计数器达到 4 时,您可以像上面那样打开 timer1:

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

如果你这样做,你不需要打开和关闭定时器 1 的中断:只要让它们打开,只在需要时打开计数。

另外我想知道是否真的有必要触发两个中断来切换引脚PORTC?您是否没有为此使用 PWM,因为它不能为您提供足够精确的脉冲长度?

于 2013-03-09T18:54:54.280 回答