micros()文档指出,返回值将始终为4的倍数。
有什么方法可以获得更高分辨率的微秒点击,最好降至1微秒级别?
降到AVR级别是可以接受的。
micros()文档指出,返回值将始终为4的倍数。
有什么方法可以获得更高分辨率的微秒点击,最好降至1微秒级别?
降到AVR级别是可以接受的。
Answers:
是的,取决于您的Arduino基本时钟速率。例如,以下是ATMega2560的计数器2的计数器定标后的输入频率和周期,以及16MHz的基本时钟速率。计时器内置了“预分频器”值选项,这些选项确定频率/周期,如下表所示:
TCCR2B bits 2-0 Prescaler Freq [KHz], Period [usec] after prescale
0x0 (TC stopped) -- --
0x1 1 16000. 0.0625
0x2 8 2000. 0.500
0x3 32 500. 2.000
0x4 64 250. 4.000
0x5 128 125. 8.000
0x6 256 62.5 16.000
0x7 1024 15.625 64.000
为了获得更好的时序分辨率,请使用一个名为TCNT2的值。由于计时器为8位,因此内置计数器的计数范围从0到255。当计数器达到TCNT2分配的值时,它将触发一个中断。该中断称为TIMER2_OVF_vect。
给定此信息,产生的中断率将为:16MHz /(预分频器*(255-TCNT2))
您可以使计时器以全16MHz(62.5nSec)的频率运行,尽管这比所需的速度要快得多。初始计数为(255-2)的2MHz将为您提供1MHz的中断率。将您的ISR除以2:
extern uint32_t MicroSecClock = 0;
ISR(TIMER2_OVF_vect) {// this is a built in function that gets called when the timer gets to the overflow counter number
static uint_8 count; // interrupt counter
if( (++count & 0x01) == 0 ) // bump the interrupt counter
++MicroSecClock; // & count uSec every other time.
digitalWrite(53,toggle);// pin 53 is arbitrary
TCNT2 = 253; // this tells the timer when to trigger the interrupt. when the counter gets to 253 out of 255(because the timer is 8 bit) the timmer will trigger an interrupt
TIFR2 = 0x00; // clear timer overflow flag
};
MCU的数据表是基本资源;本文将为您(并给我!)提供良好的起点。
马克,我决定根据Arduino Atmega328 Timer2并使用溢出中断来编写一组新功能,以使精度达到0.5us。我的代码可在此处下载和使用:
这里是一个简短的描述:“我编写了一个“ libary”,以便在“ micros()”替换函数上获得0.5us的精度,这样我就可以在1us内读取PWM或PPM信号获得可重复的结果。互联网,找不到可比的东西(或易于使用,并保持了Arduino通过Servo Libary编写PWM信号的能力),因此我认为这是我对Arduino和Radio Control的第一项重大贡献。”
如果降到AVR级别是可以接受的(如您在问题中所提到的),则可以设置一个计时器,甚至获取AVR时钟的滴答声。
您需要参考AVR的数据表,因为在不同的ATMegas和ATTinys中它有所不同。但是过程始终是相同的。您需要做的是:
TCCR
这样可以从定时器寄存器中获取准确的滴答,但是您需要手动计算溢出。通过技术可以做到尽可能精确。
这是一些过时的AT90S2313的示例代码,但是它为您提供了一些基本的提示:
/* uC: AT90S2313 */
#include <avr/io.h>
#include <avr/interrupt.h>
int main(void)
{
// set up timer 0
TCCR0 = (1<<CS01); // Prescaler 8
// enable overflow interrupt
TIMSK |= (1<<TOIE0);
// activate interrupts
sei();
while(1)
{
/* Do whatever you like */
}
}
ISR (TIMER0_OVF_vect)
{
/*
This gets called everytime there in an overflow in the timer register
*/
}
TIMSK
,TOIE0
(从atmega328p数据表中复制计时器设置)。看来您不能使用ISR()宏,而应使用arduino.cc/en/Reference/AttachInterrupt。