micros() 文档指出,返回值始终是 4 的倍数。
有没有办法获得更高分辨率的微秒点击,最好是 1 微秒级别?
下降到 AVR 级别是可以接受的。
micros() 文档指出,返回值始终是 4 的倍数。
有没有办法获得更高分辨率的微秒点击,最好是 1 微秒级别?
下降到 AVR 级别是可以接受的。
是的,取决于您的 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 的数据表是基本资源;这篇文章会给你(也给了我!)一个良好的开端。
如果下降到 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
*/
}
马克,我决定编写一组新的函数,基于 Arduino Atmega328 Timer2,并使用溢出中断,以达到 0.5us 的精度。我的代码可在此处下载和使用:
这里有一个简短的描述:“我写了一个“库”来在“micros()”替换函数上获得 0.5us 的精度,这样我就可以在 1us 内获得读取 PWM 或 PPM 信号的可重复结果。我在周围搜索了互联网上找不到类似的东西(或者易于使用,并保持了 Arduino 通过伺服库编写 PWM 信号的能力),所以我认为这是我对 Arduino 和无线电控制世界的第一个重大贡献。”