arduino的硬件中断和定时器中断

sean 编辑于2021-06-09 16:35Arduino

中断是一种相对于轮询来说更高效的一种调度方式:

arduino uno只有两个引脚支持硬件中断,(D2, 0),(D3, 1),D2对应0中断号,D3对应1中断号。

其他板的中断引脚多一些,

void setup()
{
 pinMode(12, OUTPUT);
//初始化D2针脚,没有信号时默认高电平
 pinMode(2, INPUT_PULLUP);
//这里0,号为中断号连接D2引脚,1号连接D3引脚。
//FALLING,说明当D2从高电平降为低电平变化时则触发,mycallbackfunc则会被调用,这里这个mycallbackfunc则称为ISR中断服务程序。 
attachInterrupt(0, mycallbackfunc, FALLING);
}
 void loop(){}
void mycallbackfunc(){
digitalWrite(12, HIGH);
}

attachInterrupt()为中断关联函数,这里参数0,号为中断号连接D2引脚,1号连接D3引脚。FALLING,说明当D2从高电平降为低电平变化时则触发,mycallbackfunc则会被调用,这里这个mycallbackfunc则称为ISR中断服务程序。

如果要禁用0号中断号的所有中断可以使用detachInterrupt(0)这个函数。

 

 关于中断模式不仅仅有FALLING(下降沿),还有RISING(上升沿):

中断模式

模式解释

FALLING

当引脚电平从高电平降为低电平时,触发中断
RISING 当引脚电平从低电平升为高电平时,触发中断
CHANGE 当引脚电平发生变化时,触发中断
HIGH 当引脚处于高电平时,触发中断,并持续运行ISR
LOW 当引脚处于低电平时,触发中断,并持续运行ISR

 

  • ISR(中断服务程序)运行的时候,loop()函数不会运行,直到ISR运行完成。
  • ISR运行时,中断是被关闭的,目的是防止ISR之间互相干扰,如果中断中使用的delay()或者millis()函数,将不会生效,因为delay()函数使用了中断和定时器。
  • 而millis()在会记录程序执行毫秒数由于使用到了中断,在ISR中,millis()是不会产生变化的。
  • 如果要用类似功能可以用delayMicroseconds(),它没有用到中断。
  • Serial通讯也用到中断,所以在ISR中也不能稳定可靠运行。
  • ISR中,无法传递参数,所以要用到全局变量。但在声明全局变量的时候,最好使用volatile,来防止编译器把该变量缓存到寄存器中,如果缓存过程被中断,则会而导致的变量更新失败。

ISR注意事项:

  1. 程序短而快
  2. ISR传参要用volatile来声明变量
  3. 不要使用millis(),因为它的返回值不会在ISR中变化的。
  4. 不使用delay() ,不可以被使用,但可以用delayMicroseconds()。
  5. 尽量避免使用串口通讯,因为通讯不可靠。
  6. 如果想在某些程序中,不想被中断打扰可以通过interrupts()和noInterrupts()来打开和关闭中断。关闭中断场景:使用串口通讯时,或者是使用delayMicroseconds生成精确计时的脉冲的情况下。

定时器中断

关于定时器中断,是由定时事件触发调用ISR的过程。

这里会用到TimerOne的库,Timer1是 ATmega168/328上的16位精度(0~65535)的硬件计时器的库

Arduino具有3个Timers和6个PWM输出引脚。计时器和PWM输出之间的关系是:

  • 引脚5和6:由计时器0 控制
  • 引脚9和10:由计时器1 控制。
  • 引脚11和3:由计时器2 控制。
#include <TimerOne.h>

int outputPin = 12;
volatile int output = Low;

void setup(){
pinMode(12, OUTPUT);
Timer1.initialize(500);  //1~8388480us(8.4s) 
Timer1.attachInterrupt(myoutput);
}

void loop(){}

void myoutput(){
digitalWrite(outputPin, output);
output = ! output;
}

这个程序如果用delay()来替代,则不会精确产生波形,实际输出高电平的时间在延迟中会被忽略。

利用TimerOne库,可以在9,10引脚使用定时器产生pwm,相对于analogWrite()的优点:

  TimerOne analogWrite
占空比精度 (0~1023) (0~255)
频率固定 频率不固定,可以定制 500Hz

TimerOne生成pwm的范例:

#include <TimerOne.h>

void setup(){
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
Timer1.initialize(1000);//周期1000us,频率为1khz的pwm,如果设置的是10us的周期,频率为100khz的pwm 
Timer1.pwm(9, 512); //占空比50%的pwm
Timer1.pwm(10, 255); //占空比25%的pwm
}

关于本站

肥龙软件分享的软件是本站作者开发的免费,无广告,安全可靠,绝不附带任何无关软件,绝不困绑任何插件的实用软件。如果您感觉好用,可以捐赠我们,这样我们可以有更积极的动力去改进升级软件,维持服务器运转,感谢您的捐助,谢谢!

致谢 赞赏/捐助名单

2024-8-13 **军 ¥16.8

更新时间:2024.8.31

联系作者(邮箱)
分类