Arduino 中断的使用

中断的定义

程序运行过程中时常需要监控一些事件的发生,如对某一传感器的检测结果做出反应。使用轮询的方式进行检测时效率较低,等待时间较长,而使用中断方式进行检测时则可以达到实时检测的效果。

当中断被触发时,控制器会暂停当前正在运行的主程序,而跳去运行中断程序,当中断程序运行完后,会再回到之前主程序暂停的位置,继续运行主程序。如此便可以达到实时响应处理事件的效果。

外部中断是由外部设备发起请求的中断。要想使用外部中断,就需要了解中断引脚的位置,根据外部设备选择中断模式,以及编写一个中断被触发后需要执行的中断函数。

中断引脚

ARDUINO中的外部中断通常是由Pin口电平改变触发的。每种型号的ARDUINO板都有数个PIn口可以用来注册中断

常见开发板外部引脚图:常见开发板引脚图

中断模式

为了设置中断模式,还需要了解设备触发外部中断的输入 信号类型。中断模式也就是中断触发的方式。在大多数ARDUINO上支持以下几个中断触发方式

LOW 低电平触发

CHANGE 电平变化触发

RISING 上升沿触发,即高电平变低电平

FALLING 下降沿触发,即低电平变高电平

中断函数

除了设置中断模式外,还需要编写一个响应中断的处理程序——中断函数,当中断被触发后,便可以让Arduino运行该中断函数。中断函数就是当中断被触发后要去执行的函数,该函数不能带有任何参数,且返回类型为空

这些准备工作完成后,还需要在setup()中使用attachInterrrupt()函数对中断引脚进行初始化配置,以开启arduino的外部中断功能,其用法如下:

attachInterrupt(interrupt, function,mode)

功能:对中断引脚进行初始化配置

参数:

interrupt,中断编号,注意,这里的中断编号并不是引脚编号

function,中断函数名,当中断被触发后即会运行此函数所代表的中断函数。

mode,中断模式

detachInterrupt(interrupt)

功能:禁用外部中断

参数:

interrrupt,需要禁用的中断编号

实验代码


#define LED  A2
#define KEY 2

volatile byte  state;
volatile unsigned long last_time;
void setup() {

  Serial.begin(115200);

  // put your setup code here, to run once:
  pinMode(LED, OUTPUT);
  pinMode(KEY, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(KEY), keyInterrupt, RISING);
  state = LOW;
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(LED, state);
}

void keyInterrupt() {
  if ((millis() - last_time) > 500) {
    Serial.println("检测到中断");
    if (state == LOW) {
      state = HIGH;
    } else {
      state = LOW;
    }
    last_time = millis();

  }

}

尝试自己模拟运行下吧:https://wokwi.com/projects/347197223040189011

可能会遇到的问题

当实际操作的时候你会发现你的中断函数被触发很多次,这个当然不是我们想要看到的。这是由于我们按键是机械结构所造成的抖动,而需求就是消除这个抖动。

if ((millis() - last_time) > 500) {
    Serial.println("检测到中断");
    if (state == LOW) {
      state = HIGH;
    } else {
      state = LOW;
    }
    last_time = millis();

  }

此方法是加入时间函数利用时间差进行处理抖动效果。

当然还有另外的一种方案笔者没有尝试过,利用在按钮两端并联一颗电容利用它的特性过滤按钮的抖动,感兴趣的可以自己测试。

定时器库的使用

引入库: TimerOne
代码中使用:#include "TimerOne.h"

#include "TimerOne.h"

#define LED 7

volatile byte state = LOW;

void setup() {
  Serial.begin(115200);
  // put your setup code here, to run once:
  pinMode(LED, OUTPUT);

  digitalWrite(LED, state);

  Timer1.initialize( 500000  ); // 初始化,   interval 以 micro sec 为单位
  Timer1.attachInterrupt( timer_task ); // attach the service routine here
}

void loop() {
  digitalWrite(LED, state);
}

void timer_task() {
  Serial.println("timer_task 执行了");
  state = ~state;
}

运行范例:https://wokwi.com/projects/347208147574719058

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容