timer - Arduino 纳米定时器

标签 timer arduino avr atmel atmega

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

  1. 有哪些计时器?
  2. 它们会产生中断吗?
  3. 什么代码会将中断处理程序附加到它们?
  4. delay()delayMicroseconds() 是如何实现的...
    • 他们使用定时器中断吗? (如果是这样,我怎样才能在此期间执行其他代码?)
    • 或者它们会重复轮询直到计时器达到特定值?
    • 或者它们是否将某个值增加 X 次?
    • 或者他们会采用其他方式吗?

最佳答案

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

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

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

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

不幸的是,Arduino 没有函数将中断附加到定时器。要使用定时器中断,您需要编写稍微低级的代码。基本上,您需要声明 interrupt routine像这样的东西:

ISR(TIMER1_OVF_vect) {
   ...
}

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

TIMSK1 |= (1<<TOIE1);

TIMSK1 |= BV(TOIE1);

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

<小时/>

Arduino delay() 函数在源代码 (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 延迟没有任何作用(函数调用就是延迟)
  • 较长的延迟使用左移操作来计时延迟。

关于timer - Arduino 纳米定时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16058695/

相关文章:

.net - 捕获导致内存不足异常的位图

c++ - 使用 SPI 从从机读取

timer - XMega 定时器和微秒

android - 使用计时器在 map 上放置标记

android - 在 Android 中安排保证在接近预定时间运行的任务的最佳方法是什么?

linux - Arduino在Fedora上传错误 "stk500_recv(): programmer is not responding"

c# - 如何使用 USB 端口将数字从 C# 发送到 Arduino Uno?

timer - 如何停止 ATmega328 上的定时器

c - 从红外传感器获取中断

vb.net - 在线程运行时使用定时器