C- atmega328上的timer2的怪异行为



我当前正在处理一项代码,该代码应该等待比较器中断并在设定的时间后执行其他代码。现在,我认为在CTC模式下使用timer2是一个好主意,确保程序等待适当的时间并提出这一点:

void setup(){
  ...
  // Set up the timer
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;
  OCR2A  = 255;                         // compare match register
  TCCR2A = (1 << WGM21);                // CTC mode
  TCCR2B = ((1 << CS22) | (1 << CS21)); // 256 prescaler
  TIMSK2 &= ~(1 << OCIE2A);             // disable interrupt
}
ISR(ANALOG_COMP_vect) {
  // switchTime is in µs, usual value: around 500µs
  // with a 16 Mhz crystal and a 256 prescale we need to devide
  // the switchTime by 16 (2^4)
  OCR2A = switchTime >> 4;
  TCNT2 = 0;                   // reset counter
  TIMSK2 |= (1 << OCIE2A);     // enable timer compare interrupt
}
ISR(TIMER2_COMPA_vect) {
  TIMSK2 &= ~(1 << OCIE2A);    // disable interrupt
  // do stuff
}

尴尬的事情是,它行不通。我们离开ISR比较器后立即调用ISR计时器(我通过在例程中切换引脚并使用示波器测量来对此进行检查。经过几个小时的读取数据表并随机更改代码,我提出了一行已修复的代码:

 ISR(TIMER2_COMPA_vect) {
  TIMSK2 &= ~(1 << OCIE2A);    // disable interrupt
  OCR2A = 255;                 // <- apparently fixes all my problems
  // do stuff
}

我对此感到非常困惑,因为计时器的频率不应该是一个问题我们称之为例程并停用中断。

现在,我很高兴找到解决方案,但我想知道为什么它有效。关于如何通过随机插入代码钓鱼并意外捕获鱼的一些东西。

我认为您错过了待定计时器中断的清理。

ISR(TIMER2_COMPA_vect) {
   TIMSK2 &= ~(1 << OCIE2A);    // disable interrupt
   /* Clear pending interrupts */ 
   TIFR2 = (1 << TOV2) | (1 << OCF2A) | (1 << OCF2B);
   // do stuff
} 

最新更新