[英]16-bit timer in AVR CTC mode
我正在尝试使用Arduino Uno开发板( ATmega328,16 MHz)实现这一目标。 因此,我在Internet上进行搜索,然后想到了以下内容:
unsigned long Time=0;
int main (void)
{
Serial.begin(9600);
cli();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 15999; // Compare value
TCCR1B |= (1 << WGM12)| (1 << CS10); // Prescaler
TIMSK1 |= (1 << OCIE1A); // Enable timer compare interrupt
sei();
while(1) {
Serial.println(TCNT1);
}
return 0;
}
ISR(TIMER1_COMPA_vect)
{
Time++;
Serial.println(Time);
}
我正在尝试达到1 kHz的频率,因此我将能够创建几毫秒长的间隔。
这就是为什么我将比较值选择为15999(即16000-1),并将预分频器选择为1的原因,所以我得到了(至少我认为是正确的计算结果):
Frequency = 16.000.000 MHz/16000 = 1000 Hz = 1 kHz
现在的问题是,即使Serial.println(TCNT1)
向我显示的数字最多计数为16000,回零,最多16000,返回零,..., Serial.println(Time)
最多计数为8 ,尽管TCNT1仍在计数,但它只是停止计数。
我想到某处有某种溢出,但我想不到哪里。 我唯一想到的是比较值可能太大了-正如我认为-显然不是这样,因为2^16 -1=65.535>15999
。
例如,如果我将预分频器设为64,并保留比较值,则Time
按预期计数。 所以我想知道:为什么ISR()
停止以值8调用,而在调高预分频器时起作用?
我不确定,但是根据您使用的Arduino版本,println调用将被阻塞。 如果调用它的速度超出了在ISR中完成的速度,则堆栈将溢出。
如果您想要更高分辨率的计时,则可以尝试在Loop()
对getMicroseconds结果进行差分。 您在Loop()
中Loop()
速度应远远超过每毫秒一次。
如果要每毫秒执行一次操作,请捕获一个开始的微秒,然后在Loop()
函数的条件中从当前的微秒中减去它。 当您看到1000多个任务时...
对于我的Arduino Uno(16 MHz)而言,计时器的分辨率似乎过高。 选择较低的分辨率(即较高的比较值)可以解决我的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.