繁体   English   中英

AVR CTC模式下的16位计时器

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM