Arduino Nano定时器

9

我想了解更多关于Arduino Nano定时器的信息。

  1. 有哪些定时器?
  2. 它们是否产生中断?
  3. 如何将中断处理程序附加到它们上?
  4. delay()delayMicroseconds()是如何实现的...
    • 它们是否使用定时器中断?(如果是这样,我如何在此期间执行其他代码?)
    • 还是它们重复轮询直到定时器达到某个值?
    • 还是它们增加一个值X次数?
    • 还是以其他方式实现?
1个回答

22

关于Arduino Nano定时器的最佳理解方式是将其视为底层芯片中的定时器: ATmega328。它有三个定时器:

  • 定时器0:8位,PWM在芯片引脚11和12上
  • 定时器1:16位,PWM在芯片引脚15和16上
  • 定时器2:8位,PWM在芯片引脚17和5上

所有这些定时器都可以产生两种类型的中断:

  • “值匹配”中断发生在计时器值(添加到计时器的每个时钟周期)达到计时器寄存器中的比较值时。
  • 定时器溢出中断发生在计时器值达到其最大值时

不幸的是,没有Arduino函数可用于将中断附加到定时器上。要使用定时器中断,您需要编写略微更低级别的代码。基本上,您需要像这样声明一个中断例程

ISR(TIMER1_OVF_vect) {
   ...
}

这将声明一个函数来处理timer1溢出中断。然后,您需要使用TIMSK1寄存器启用计时器溢出中断。在上面的示例中,代码可能如下所示:

TIMSK1 |= (1<<TOIE1);
或者
TIMSK1 |= BV(TOIE1);

这会在TIMSK1寄存器中设置TOIE1(产生timer1溢出中断,请)标志。假设您启用了中断,每次timer1溢出时都会调用ISR(TIMER1_OVF_vect)


在源代码wiring.c中,Arduino的delay()函数如下:

void delay(unsigned long ms)
{
    uint16_t start = (uint16_t)micros();

    while (ms > 0) {
        if (((uint16_t)micros() - start) >= 1000) {
            ms--;
            start += 1000;
        }
    }
}

在内部,它使用micros()函数,该函数确实依赖定时器0计数。Arduino框架使用定时器0计算毫秒数,确切地说,millis()函数的值就是定时器0计数的结果。

另一方面,delayMicroseconds()函数使用某些精确计时的微处理器操作来创建延迟;所用的函数取决于处理器和时钟速度;最常见的是nop()(无操作),它需要恰好一个时钟周期。Arduino Nano使用16 MHz的时钟,以下是其源代码:

// For a one-microsecond delay, simply return. The overhead
// of the function call yields a delay of approximately 1 1/8 µs.
if (--us == 0)
    return;

// The following loop takes a quarter of a microsecond (4 cycles)
// per iteration, so execute it four times for each microsecond of
// delay requested.
us <<= 2;

// Account for the time taken in the proceeding commands.
us -= 2;

从中我们学到:

  • 1微秒的延迟几乎没有作用(函数调用本身就是延迟)。
  • 更长的延迟使用左移操作来计时延迟。

谢谢!很高兴你觉得它有用。 - angelatlarge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接