index

  • 什么是计时器?
    • 定时器0:
    • 计时器1:
    • 定时器2:
    • Timer3,Timer4,Timer5:
  • 计时器寄存器
  • 时钟选择和定时器频率
  • 计时器模式
  • 什么是中断?
    • 定时器中断
    • 计时器溢出:
    • 输出比较匹配:
    • 定时器输入捕捉:
  • PWM和计时器

本教程说明了Arduino板的计时器和中断的用法。作为Arduino程序员,您将在没有知识的情况下使用计时器和中断,因为Arduino API隐藏了所有底层硬件。许多Arduino函数使用计时器,例如时间函数:delay( )millis( )micros( ))和delayMicroseconds( )。PWM函数AnalogWrite( )使用计时器,就像tone( ) 和notone( ) 函数一样。甚至伺服库也使用定时器和中断。

什么是计时器?

计时器或更准确地说是计时器/计数器是Arduino控制器内置的一块硬件 (其他控制器也具有计时器硬件)。它就像一个时钟,可用于测量时间事件。定时器可以通过一些特殊的寄存器进行编程。您可以为计时器配置预分频器,或者为操作模式配置其他功能。

Arduino的控制器是Atmel AVR ATmega168或ATmega328。这些芯片引脚兼容,只是内部存储器的大小不同。两者都有3个定时器,分别称为timer0Timer1timer2timer0timer2 是8位定时器,其中Timer1是16位定时器。8位和16位定时器之间最重要的区别是定时器分辨率。8位表示256个值,而16位表示65536个值,以实现更高的分辨率。
Arduino Mega系列的控制器是Atmel AVR ATmega1280或ATmega2560。同样相同的只是存储器大小不同。这些控制器具有6个计时器。定时器0,定时器1和定时器2与ATmega168 / 328相同。定时器3,定时器4和定时器5均为16位定时器,类似于定时器1。
所有计时器均取决于Arduino系统的系统时钟。通常系统时钟为16MHz,但Arduino Pro 3,3V为8Mhz。因此,编写自己的计时器函数时要小心。
定时器硬件可以配置一些特殊的定时器寄存器。在Arduino固件中,所有计时器均配置为1kHz频率,并且中断均已启用

定时器0:

定时器0是一个8位定时器。
在Arduino世界中,timer0用于计时器功能,例如delay( ) 364,millis( )861和micros( )380。如果更改timer0寄存器,则可能会影响Arduino定时器功能。因此,您应该知道自己在做什么。

计时器1:

Timer1是一个16位定时器。
在Arduino世界中,Servo库 642在Arduino Uno上使用Timer1(在Arduino Mega上为timer5)。

定时器2:

定时器2是8位定时器,类似于定时器0。
在Arduino工作中,tone( ) 493函数使用timer2

Timer3,Timer4,Timer5:

计时器3、4、5仅在Arduino Mega板上可用。这些定时器都是16位定时器。

计时器寄存器

您可以通过计时器寄存器更改计时器行为。最重要的定时器寄存器是:
TCCRx-定时器/计数器控制寄存器。可以在此处配置预分频器

  • TCNTx-定时器/计数器寄存器。实际计时器值存储在此处。

  • OCRx-输出比较寄存器

  • ICRx-输入捕捉寄存器(仅适用于16位定时器)

  • TIMSKx-定时器/计数器中断屏蔽寄存器。启用/禁用定时器中断。

  • TIFRx-定时器/计数器中断标志寄存器。指示未决的定时器中断。

时钟选择和定时器频率

可以为每个定时器独立选择不同的时钟源。要计算计时器频率(例如使用Timer1的2Hz),您需要:

  1. Arduino的CPU频率16Mhz
  2. 最大计时器计数器值(8位为256,16位为65536)
  3. 将CPU频率除以所选的预分频器(16000000/256 = 62500)
  4. 将结果除以所需的频率(62500 / 2Hz = 31250)
  5. 如果失败,请对照最大计时器计数器值(31250 <65536成功)验证结果,然后选择更大的预分频器

计时器模式

定时器可以配置为不同的模式。

  • PWM模式。脉宽调制模式。OCxy输出用于生成PWM信号
  • CTC模式。比较匹配时清除计时器。当定时器计数器到达比较匹配寄存器时,定时器将被清除

什么是中断?

控制器上运行的程序通常按指令顺序运行。中断是一个外部事件,它会中断正在运行的程序并运行特殊的中断服务程序(ISR )。ISR 完成后,正在运行的程序将继续执行下一条指令。指令是指单条机器指令,而不是C或C ++ 代码行。
在未决中断能够调用ISR 之前,必须满足以下条件:

  • 通常必须启用中断
  • 必须启用相应的中断屏蔽

通常可以使用函数interrupts( ) 154 / noInterrupts( ) 40启用/禁用中断。默认情况下,在Arduino固件中启用中断。通过设置/清除中断屏蔽寄存器(TIMSKx)中的位,可以启用/禁用中断屏蔽。
发生中断时,将设置中断标志寄存器(TIFRx)中的标志。进入ISR 或手动清除中断标志寄存器中的位时,该中断将自动清除。

Arduino函数attachInterrupt( )191和detachInterrupt( )37仅可用于外部中断引脚。这些是不同的中断源,这里不再讨论。

定时器中断

定时器可以产生不同类型的中断。寄存器和位的定义可以在处理器数据表(Atmega328 185或Atmega2560 175)和I / O定义头文件中找到(对于Arduino为iomx8.h,对于Arduino Mega为iomxx0_1.h在硬件/工具/ avr / include / avr文件夹)。后缀x代表定时器编号(0..5),后缀y代表输出编号(A,B,C),例如TIMSK1(定时器1中断屏蔽寄存器)或OCR2A(定时器2输出比较寄存器A)。

计时器溢出:

计时器溢出表示计时器已达到极限值。当发生定时器溢出中断时,中断标志寄存器TIFRx中的定时器溢出位TOVx将置1。当中断屏蔽寄存器TIMSKx中的定时器溢出中断使能位TOIEx置1时,将调用定时器溢出中断服务程序ISR (TIMERx_OVF_vect)。

输出比较匹配:

当发生输出比较匹配中断时,OCFxy标志将在中断标志寄存器TIFRx中置1。当中断屏蔽寄存器TIMSKx中的输出比较中断使能位OCIExy置位时,将调用输出比较匹配中断服务ISR (TIMERx_COMPy_vect)例程。

定时器输入捕捉:

当定时器输入捕捉中断发生时,输入捕捉标志位ICFx将在中断标志寄存器TIFRx中置1。当中断屏蔽寄存器TIMSKx中的输入捕捉中断使能位ICIEx置1时,将调用定时器输入捕捉中断服务程序ISR (TIMERx_CAPT_vect)。

PWM和计时器

计时器和具有PWM功能的输出之间存在固定关系。当您查阅数据手册或处理器的引脚排列时,这些具有PWM功能的引脚的名称如OCRxA,OCRxB或OCRxC(其中x表示定时器编号0…5)。PWM功能通常与其他引脚功能共享。
Arduino具有3个Timers和6个PWM输出引脚。计时器和PWM输出之间的关系是:

  • 引脚5和6:由计时器0 控制
  • 引脚9和10:由计时器1 控制。
  • 引脚11和3:由计时器2 控制。

在Arduino Mega上,我们有6个计时器和15个PWM输出:

  • 引脚4和13 :由定时器0控制
  • 引脚11和12:由定时器1控制
  • 引脚9 和10:由定时器2 控制
  • 引脚2、3和5:由定时器3控制
  • 引脚6、7和8:由计时器4控制
  • 引脚46、45和44 :由计时器5控制

有用的第三方库存在一些第三方库,它们使用计时器:

  • Ken Shirrifs IR库。使用定时器2。发送和接收任何种类的IR远程信号,例如RC5,RC6,Sony
  • Timer1和Timer3库 。使用Timer1或tiner3。编写自己的计时器中断服务例程的简单方法。

我已经将这些库移植到了Arduino Mega的不同计时器上。所有移植的库都可以在附件中找到。

陷阱
当对Arduino进行编程并使用使用计时器的函数或库时,可能会遇到一些陷阱。

  • 伺服库使用Timer1。当您在Arduino上使用伺服库时,不能在引脚9、10上使用PWM。对于Arduino Mega来说要困难一些。所需的计时器取决于伺服器的数量。每个计时器可处理12个伺服器。对于前12个伺服器,将使用计时器5(在引脚44,45,46上释放PWM)。对于24个Servos,将使用计时器5和1(在引脚11,12,44,45,46上松开PWM)。对于36个伺服器,将使用计时器5、1和3(在引脚2,3,5上松开PWM, 11,12,44,45,46)。对于48个伺服器,将使用所有16位定时器5、1、3和4(失去所有PWM引脚)。
  • 引脚11具有共享功能PWM和MOSI。SPI接口需要MOSI。您不能在Arduino上同时在引脚11和SPI接口上使用PWM。在Arduino Mega上,SPI引脚位于不同的引脚上。
  • tone( ) 函数至少使用timer2 。当您使用Arduino的tone( ) 函数和Arduino Mega上的9,10引脚时,不能在引脚3,11上使用PWM。

例子

带比较匹配中断的指示灯闪烁

第一个示例使用CTC模式下的Timer1和比较匹配中断来切换LED。计时器配置为2Hz的频率。LED在中断服务程序中切换。


参考网址:http://www.letmakerobots.com/node/28278

/* Arduino 101: timer and interrupts1: `Timer1` compare match interrupt example more infos: http://www.letmakerobots.com/node/28278created by RobotFreak
*/
#define ledPin 13
void setup()
{pinMode(ledPin, OUTPUT);// initialize `Timer1` noInterrupts();           // disable all interruptsTCCR1A = 0;TCCR1B = 0;TCNT1  = 0;OCR1A = 31250;            // compare match register 16MHz/256/2HzTCCR1B |= (1 << WGM12);   // CTC modeTCCR1B |= (1 << CS12);    // 256 prescaler TIMSK1 |= (1 << OCIE1A);  // enable timer compare interruptinterrupts();             // enable all interrupts
}ISR (Timer1_COMPA_vect)          // timer compare interrupt service routine
{digitalWrite(ledPin, digitalRead(ledPin) ^ 1);   // toggle LED pin
}void loop()
{// your program here…
}

Blinking LED with timer overflow interrupt

same example like before but now we use the timer overflow interrupt. In this case Timer1 is running in normal mode.
The timer must be preloaded every time in the interrupt service routine.

/* * Arduino 101: timer and interrupts* 2: `Timer1` overflow interrupt example * more infos: http://www.letmakerobots.com/node/28278* created by RobotFreak */#define ledPin 13
void setup()
{pinMode(ledPin, OUTPUT);// initialize `Timer1` noInterrupts();           // disable all interruptsTCCR1A = 0;TCCR1B = 0;TCNT1 = 34286;            // preload timer 65536-16MHz/256/2HzTCCR1B |= (1 << CS12);    // 256 prescaler TIMSK1 |= (1 << TOIE1);   // enable timer overflow interruptinterrupts();             // enable all interrupts
}`ISR `(`Timer1`_OVF_vect)        // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{TCNT1 = 34286;            // preload timerdigitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}void loop()
{// your program here...
}

下面的例子是我的一Ardubot项目的一部分 。它使用timer2 和比较匹配中断来读取编码器输入。默认情况下,timer2 初始化为1kHz(1ms周期)的频率。在中断服务程序中,读取所有编码器引脚的状态,并使用状态机消除错误的读取。使用定时器中断比使用4个输入更改中断要容易得多。

正交编码器的信号是2位格雷码 。每个状态仅改变一位。状态机非常适合检查信号并计算编码器滴答声。计时器必须足够快,才能识别每个状态变化。对于Pololu车轮编码器 本文所用,1ms的定时器是速度不够快。

The following example has been modified to work with Arduino V1.x/*
/* * Arduino 101: timer and interrupts* 3: `timer2 ` compare interrupt example. Quadrature Encoder* more infos: http://www.letmakerobots.com/node/28278* created by RobotFreak ** Credits:* based on code from Peter Dannegger* http://www.mikrocontroller.net/articles/Drehgeber*/
#if ARDUINO >= 100#include “Arduino.h”
#else#include “WConstants.h”
#endif// Encoder Pins#define encLtA 2
#define encLtB 3
#define encRtA 11
#define encRtB 12
#define ledPin 13#define LT_PHASE_A     digitalRead(encLtA)
#define LT_PHASE_B      digitalRead(encLtB)
#define RT_PHASE_A      digitalRead(encRtA)
#define RT_PHASE_B      digitalRead(encRtB)static volatile int8_t encDeltaLt, encDeltaRt;
static int8_t lastLt, lastRt;
int encLt, encRt;`ISR `( `timer2 `_COMPA_vect )
{int8_t val, diff;digitalWrite(ledPin, HIGH);   // toggle LED pinval = 0;if( LT_PHASE_A )val = 3;if( LT_PHASE_B )val ^= 1;                   // convert gray to binarydiff = lastLt - val;              // difference last - newif( diff & 1 ){             // bit 0 = value (1)lastLt = val;             // store new as next lastencDeltaLt += (diff & 2) - 1;        // bit 1 = direction (+/-)}val = 0;if( RT_PHASE_A )val = 3;if( RT_PHASE_B )val ^= 1;               // convert gray to binarydiff = lastRt - val;              // difference last - newif( diff & 1 ){             // bit 0 = value (1)lastRt = val;             // store new as next lastencDeltaRt += (diff & 2) - 1;        // bit 1 = direction (+/-)}digitalWrite(ledPin, LOW);   // toggle LED pin
}void QuadratureEncoderInit(void)
{int8_t val;cli();TIMSK2 |= (1<<OCIE2A);sei();pinMode(encLtA, INPUT);pinMode(encRtA, INPUT);pinMode(encLtB, INPUT);pinMode(encRtB, INPUT);val=0;if (LT_PHASE_A)val = 3;if (LT_PHASE_B)val ^= 1;lastLt = val;encDeltaLt = 0;val=0;if (RT_PHASE_A)val = 3;if (RT_PHASE_B)val ^= 1;lastRt = val;encDeltaRt = 0;encLt = 0;encRt = 0;
}int8_t QuadratureEncoderReadLt( void )         // read single step encoders
{int8_t val;cli();val = encDeltaLt;encDeltaLt = 0;sei();return val;                   // counts since last call
}int8_t QuadratureEncoderReadRt( void )         // read single step encoders
{int8_t val;cli();val = encDeltaRt;encDeltaRt = 0;sei();return val;                   // counts since last call
}void setup()
{Serial.begin(38400);pinMode(ledPin, OUTPUT);QuadratureEncoderInit();
}void loop()
{encLt += QuadratureEncoderReadLt();encRt += QuadratureEncoderReadRt();Serial.print("Lt: “);Serial.print(encLt, DEC);Serial.print(” Rt: ");Serial.println(encRt, DEC);delay(1000);
}

Popular Links
2150 http://arduino.cc/playground/Code/Timer1
1699 http://arduino.cc/en/Reference/Millis
1204 http://arduino.cc/en/Reference/Servo
1049 http://arduino.cc/en/Reference/Tone
975 //www.robotshop.com/community/forum/uploads/default/original/2X/4/460915d584caebf2be9…
763 http://arduino.cc/en/Reference/Micros
760 http://arduino.cc/en/Reference/Delay
724 //www.robotshop.com/community/forum/uploads/default/original/2X/5/53d05d20393aaf1f688…
466 http://arduino.cc/en/Reference/Volatile
374 http://arduino.cc/en/Reference/AttachInterrupt
373 http://www.atmel.com/dyn/resources/prod_documents/doc8271.pdf
346 http://www.atmel.com/dyn/resources/prod_documents/doc2549.pdf
308 http://arduino.cc/en/Reference/Interrupts
279 http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
261 http://arduino.cc/en/Reference/DelayMicroseconds
200 http://arduino.cc/en/Reference/AnalogWrite
110 http://www.pololu.com/catalog/product/1217
82 http://ArduinoInfo.Info
82 /letsmakerobots/node/11987
79 http://arduino.cc/en/Reference/NoInterrupts
67 http://arduino.cc/forum/index.php?topic=130423.0
66 http://arduino.cc/en/Reference/DetachInterrupt
60 http://en.wikipedia.org/wiki/Gray_code
53 http://arduino.cc/en/Reference/NoTone
16 https://code.google.com/p/arduino/source/browse/trunk/libraries/Servo/Servo.cpp
11 volatile - Arduino Reference arduino.cc
7 GitHub - adafruit/Adafruit_NeoPixel: Neo Pixels! github.com
5 https://www.arduino.cc/reference/en/language/variables/variable-scope–qualifiers/vol…
There are 33 replies with an estimated read time of 19 minutes.

arduino 计时器和中断相关推荐

  1. arduino计时器程序

    这是个arduino计时器程序,这个程序可以调整计时器进行倒计时,可以设置倒计时时间. 一共两个按钮,两个电位器,三个led灯. 两个按钮其中一个控制计时开始和计时结束,另一个按钮循环移位时分秒设置, ...

  2. 【Arduino计时器】Arduino计时器使用TM1637显示时间

    Arduino计时器使用TM1637显示时间 本文介绍如何使用Arduino制作计时器,并使用TM1637显示时间.计时器使用2个GPIO接口作为启动计时和停止计时的按键,并要求计时精度达到0.01秒 ...

  3. Arduino笔记-定时器中断(MsTimer2库使用)

    定时器中断,在某一特定的时候, 不管在干嘛,都要去执行那个定时器中断,指向的代码段. 这里以Arduino UNO为例: 运行截图如下: 每隔1s,亮LED_BUILTIN的灯: 这里要下载MsTim ...

  4. 【51单片机】计时器/计数器中断

    51单片机中有2个 定时器/计数器 中断,之所以叫定时器/计数器,是因为它既可以当定时器,也可以当计数器,其实本质上都是计数器,如果给一个稳定的时钟源,那么它就是一个定时器的.(下面我说的计数器或定时 ...

  5. arduino——编码器示例(中断控制)

    使用中断控制 语法 attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); 参数 pin: 中断引脚号 ISR: 中断服务程序名 mode:中断 ...

  6. Arduino笔记-外部中断实验(震动传感器实时亮灯)

    外部中断:达到实时响应处理事件的效果. 目前Ardinuo UNO引脚只有2个,一个是2号口,一个是3号口 在Ardinuo中中断函数,返回值为空,不能有参数 程序运行截图如下: 当感应到震动后: 这 ...

  7. arduino 多个超声波模块HC-SR04 Newping.h库的使用——摆脱万恶的阻塞等待

    目录 前言(一点废话) 问题的发现 Newping.h库 简介 安装 例程1:定时器示例TimerExample 例程2:超声波模块的读取NewPingExample 例程3:中断读取超声波NewPi ...

  8. Arduino ESP32 中断计时器

    学习目标: 在实验中,当检测到运动(触发中断)时,ESP32启动计时器,并在预定义的秒数内打开LED.当计时器完成倒计时时,LED会自动关闭. 在Arduino中设置中断,可用attachInterr ...

  9. ESP8266 中断(Interrupts)和计时器(Timers)功能介绍

    ESP8266 中断(Interrupts)和计时器(Timers)功能介绍 在本指南中,您将学习如何使用Arduino IDE与ESP8266 NodeMCU使用中断和计时器.中断允许您检测GPIO ...

最新文章

  1. 如何建立顺畅的项目流程
  2. 流量分析_安恒八月月赛
  3. aws iam 架构图_使用IAM保护您的AWS基础架构
  4. 浅析设计模式(三)——抽象工厂模式
  5. Django完整的开发一个博客系统
  6. minio 文件预览_Minio使用说明
  7. windows server 2008 大量拷贝后释放内存
  8. RTK_LIB 源码、可执行文件、rtkget、观测文件、星历文件(精密星历、广播星历)、精密钟差文件介绍
  9. [编辑器]_从 VI 编辑器谈 FreeBSD 的前世今生以及编辑器本质
  10. ubuntu重装显卡驱动
  11. Android茶叶进销存源码分享
  12. 小学计算机课flash的教案,信息技术flash教案
  13. Pandas玩转数据透视表,用它就够了!
  14. MSI Center局域网管理器开启导致电脑网络质量变差、网速低
  15. “21天好习惯“ 第五期 — 5
  16. vue3.0 前进刷新后退缓存
  17. KCL v0.4.4 发布 - 自定义 YAML Manifests 输出以及 Python SDK
  18. [ARM嵌入式系统开发]第一章之嵌入式系统的软硬件
  19. 续写千倍币神话,PlusFo到底是何方神圣?
  20. 卡方 python_Python卡方拟合优度检验得到最优分布

热门文章

  1. TensorFlow Lite编译Android so库
  2. jenkins从节点问题-windows重启导致从节点失联
  3. 华为联运服务登录支付签名
  4. 简单粗暴的黑苹果安装教程
  5. 【离散数学】集合与关系
  6. linux系统c语言重命名文件,C语言文件操作函数
  7. 可私有化部署的物联网云平台----性能稳定可靠 ,低成本
  8. 最后一天了,四个关键字回顾程序员小跃的2020
  9. uniapp集成colorUI uView2.0 Vuex
  10. 【STM32CubeIDE和ITM SWV实现printf调试信息的打印】