我正在尝试使用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 = 1kHz
现在的问题是,即使Serial.println(TCNT1)
显示我的数字高达16000,回到零,高达16000,回到零,......,Serial.println(Time)
只计算到8并且只是停止计数,尽管TCNT1仍在计算中。
我想到某处有某种溢出,但我无法想到在哪里;我想到的唯一的事情是比较值可能是大的 - 我认为 - 显然不是2^16 -1=65.535>15999
以来的情况。
例如,如果我制作预分频器,假设为64,并保留比较值,Time
按预期计数。所以我想知道:为什么ISR()
停止调用值为8,但在调出预分频器时有效?
答案 0 :(得分:1)
我不确定,但是根据你使用的Ardunio的版本,println调用会阻塞,如果你调用它更快,那么它可以在你的ISR中完成堆栈将溢出。
如果你想要更高分辨率的时序可能尝试在你的Loop()中对getMicroseconds结果进行差分处理,你应该在循环中循环远远超过每毫秒一次。
如果你想每毫秒做一次捕获一个开始的微秒,那么你可以在Loop函数的条件中从当前的微秒中减去它。当你看到1000多个任务时......
答案 1 :(得分:0)
对于我的Arduino Uno(16 MHz)来说,计时器的分辨率似乎太高了。选择较低的分辨率(即较高的比较值)可以解决我的问题。