8

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

  1. 有哪些计时器?
  2. 他们会产生中断吗?
  3. 什么代码会将中断处理程序附加到它们?
  4. 如何delay()delayMicroseconds()实施...
    • 他们使用定时器中断吗?(如果是这样,在此期间如何执行其他代码?)
    • 还是他们反复轮询直到计时器达到某个值?
    • 还是他们将值增加 X 次?
    • 还是他们以另一种方式做到这一点?
4

1 回答 1

20

考虑 Arduino Nano 计时器的最佳方式是考虑底层芯片中的计时器:ATmega328。它有三个定时器:

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

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

  • “值匹配”中断发生在与定时器的每个滴答相加的定时器值达到定时器寄存器中的比较值时。
  • 当定时器值达到最大值时发生定时器溢出中断

不幸的是,没有 Arduino 函数可以将中断附加到定时器。要使用定时器中断,您需要编写更多的低级代码。基本上,您需要声明一个中断例程,如下所示:

ISR(TIMER1_OVF_vect) {
   ...
}

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

TIMSK1 |= (1<<TOIE1);

或者

TIMSK1 |= BV(TOIE1);

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


Arduinodelay()函数在源代码 ( ) 中如下所示wiring.c

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

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

所以在内部它使用该micros()函数,该函数确实依赖于 timer0 计数。Arduino 框架使用 timer0 来计算毫秒数,实际上, timer0 计数是millis()函数获取其值的地方。

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 µs 延迟什么都不做(函数调用就是延迟)
  • 较长的延迟使用左移操作来计算延迟时间。
于 2013-04-17T20:27:43.280 回答