ATmega328 上 timer2 的奇怪行为
Weird behaviour of timer2 on ATmega328
我目前正在编写一段代码,它应该等待比较器中断并在设定的时间后执行一些其他代码。现在,我认为在 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
}
我目前正在编写一段代码,它应该等待比较器中断并在设定的时间后执行一些其他代码。现在,我认为在 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
}