1

我正在尝试使用 Arduino Uno 板(ATmega328,16 MHz)来实现这一点。所以我在网上搜索了一下,想到了这样的东西:

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 时被调用,但在调出预分频器时有效?

4

2 回答 2

1

我不确定,但根据您使用的 Arduino 版本,println 调用会被阻塞。如果调用它的速度快于它在 ISR 中的完成速度,堆栈就会溢出。

如果您想要更高分辨率的时间,也许可以尝试在您的Loop(). 您的循环速度应该Loop()远远快于每毫秒一次。

如果您想每毫秒执行一次,请捕获开始微秒,然后在Loop()函数的条件中从当前微秒中减去它。当你看到超过 1000 人做任务时......

于 2014-01-05T02:29:14.833 回答
0

对于我的 Arduino Uno (16 MHz) 来说,计时器的分辨率似乎太大了。选择较低的分辨率(即较高的比较值)为我解决了这个问题。

于 2014-04-16T17:14:32.067 回答