第四章——中断 Interrupt

1. 什么是中断

当单片机正在执行某程序时,如果突然出现意外情况,它就需要停止当前正在执行的程序,转而去处理意外情况,处理完后又接着执行原来的程序。这就是中断的作用。

下面是一个中断示意图:

中断示意图

在单片机中有硬件中断软件中断

  • 硬件中断:当外部事件发生时发生,例如外部中断引脚将其状态从 LOW 变为 HIGH 或 HIGH 变为 LOW。
  • 软件中断:根据软件的指令发生。例如定时器中断是软件中断。

下面我们介绍一下 Arduino 的硬件中断。

2. attachInterrupt()函数

在 Arduino 中使用中断非常简单,直接使用attachInterrupt()进行中断配置就可以了。

语法:

attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);

pin 参数:在这里还不能直接使用中断引脚,你必须使用digitalPinToInterrupt(),将对应的引脚映射到对应的中断序号上,在某些单片机芯片上,引脚号就是中断号,但是还是比较建议使用此函数进行映射。

ISR 参数:ISR(Interrupt Service Routine)是中断发生时需要调用的函数名,该函数必须无返回值,无参数。

mode 参数:mode 是指能够触发中断的模式,有以下三种模式可供选择:

下面是 Arduino 部分开发板支持的外部中断引脚分布:

Aduino BoardPins
Uno,Nano,other 328-based board2,3
Mega, Mega2560, MegaADK2,3,18,19,20,21
  • LOW,引脚为低电平触发中断
  • CHANGE,引脚电平改变时触发中断
  • FALLING,引脚电平出现上升沿时触发中断
  • RISING,引脚中断出现下降沿时触发中断

下面是一个在按钮中使用中断的例子,可以帮助大家理解中断的使用:

uint8_t led = 13;
uint8_t button = 2;
bool LEDStatus;

// 中断回调的任务函数
void buttonTask() {
  LEDStatus = !LEDStatus;
  if (LEDStatus)digitalWrite(led, HIGH);
  else digitalWrite(led, LOW);
}

void setup() {
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP);
  // 中断初始化
  attachInterrupt(digitalPinToInterrupt(button), buttonTask, FALLING);
}

void loop() {
}

你可以通过detachInterrupt(pin)结束单片机对某个中断引脚的监视。

上面的代码中加入结束中断后如下:

uint8_t led = 13;
uint8_t button = 2;
bool LEDStatus;
unsigned long lastTime;

// 中断回调的任务函数
void buttonTask() {
  LEDStatus = !LEDStatus;
  if (LEDStatus)digitalWrite(led, HIGH);
  else digitalWrite(led, LOW);
}

void setup() {
  pinMode(led, OUTPUT);
  pinMode(button, INPUT_PULLUP);
  // 中断初始化
  attachInterrupt(digitalPinToInterrupt(button), buttonTask, FALLING);
}

void loop() {
  // 20s后结束对中断引脚buttons的监视
  if (millis() - lastTime > 20000) {
    detachInterrupt(digitalPinToInterrupt(button));
  }
}