简介
本章节我们将学习Arduino中的中断相关的API函数. 那么在我们正式可以学习API之前呢,让我来简单的介绍一下中断相关的概念.
中断
中断是单片机中实现实时操作的关键机制。没有中断的系统往往依赖程序在主循环中不断运行,无法及时响应外部事件。我们用一个电梯的例子来说明:想象一部扶手电梯在正常运行时,如果发生紧急情况,比如一个小孩被卡住,而电梯没有中断机制,那么唯一能做的就是切断电源来停下电梯。然而,切断电源可能耗费一定的时间,小孩的处境会变得非常危险。
引入中断后,情况就完全不同了。如果有小孩遇到危险,按下电梯的急停按钮,电梯立即停止,但仍保持通电状态,系统可以在处理完紧急情况后将电梯恢复到之前的状态。这就是中断的本质:当发生紧急事件时,暂停当前的工作,优先处理紧急事件,之后再回到之前的任务。
中断优先级
单片机通常提供多种中断资源,例如系统中断、定时器中断、串口中断和外部中断等。不同的中断可以根据应用场景进行配置。
那么,当多个中断同时发生时该如何处理呢?这时就涉及到中断优先级。假如你在写代码,突然有几个人同时来给你捏肩膀,那么你肯定会选择优先接受最舒服的一个。同样道理,优先级高的中断会优先被处理,低优先级的中断则会被延后。
中断嵌套
另一个常见的情况是中断嵌套。假如低优先级的中断A正在执行,突然有一个高优先级的中断B发生。由于中断B的优先级较高,单片机会暂停中断A的处理,先执行中断B,待中断B处理完成后再返回处理中断A。
比方说你正在吃美女A送来的水果,此时美女B送来了你更喜欢的水果。你会停下吃A的水果,优先享用B的水果,等B的水果吃完了再去继续吃A的。
中断的注意事项
中断函数一般不要包含复杂逻辑或耗时的操作,比如延时操作。这样可能导致一个中断还未处理完,新的中断又到来,影响系统的实时性。
经过这样简化,中断机制变得更容易理解。它的核心就在于实时处理紧急事件,优先处理高优先级任务,并及时返回原先的工作。
Arduino 中断相关API函数
根据Arduino的官方API文档(https://www.arduino.cc/reference/en/)得知,Arduino的中断相关函数一共有以下五个.
让我们来逐一介绍和使用上面的API. 在interrupts下面一共有两个API
1- interrupts()
2- noInterrupts()
这两个API分别用于开启中断和关闭中断, 例如我们在操作某些时序相关的传感器的时候,并不希望和需要去他的应用进入中断函数来打断当前的时序,那么我们便可以在开始传感器操作之前调用noInterrupts() 方法来关闭中断. 然后在完成时序操作后再调用interrupts()开启中断.
对于外部中断,这里一共有三个方法, 分别是
1- attachInterrupt()
2- detachInterrupt()
3- digitalPinToInterrupt()
第一个API attachInterrupt() 主要用于绑定某一个IO的引脚到外部中断上. 同时设置对应的中断方法以及触发中断的方式. 但是需要注意的是,并不是所有的PIN都可以被绑定作为外部中断的触发PIN. Adruino uno r4 wifi 支持的触发Pin 如下所示
用法的话则按照Arduino推荐的调用方式进行使用即可. 按下图所示
在我们继续之前,让我们看一下推荐调用方式中设计到的另一个API digitalPinToInterrupt()
digitalPunToInterrupt() 这个API主要用于确定当前的PIN是否可以被绑定作为中断的引脚. 比如说在Arduino uno r4 wifi中支持的PIN 为 2 和 3 , 那么将这两个PIN作为参数传入的时候, 这个方法将会返回1, 即当前的PIN支持绑定外部中断, 如果当前的PIN并不支持外部中断的话则返还0.
那么我们继续看上面的attachInterrupt() API 的第二个参数, ISR, 即Interrupt service routine 可以理解为call back function (回掉函数), 即中断处罚之后触发的函数(用户可以自定义).
第三个参数则为外部中断的触发方式, 那么它支持的触发方式一共有四种(五种), 分别是:
1- 低电平触发
2-IO状态切换的时候触发
3-上升沿触发
4-下降沿触发
同时在Due, Zero 和MKR1000开发版上还支持高电平触发.
而最后的一个API则是 detachInterrupt() 这个API主要是用于,当某一个PIN被绑定成了外部中断的PIN的话,解绑它. 那么至此我们便看完了Arduino的所有API. 接下来我们看下代码部分.
代码Demo演示
const byte ledPin = 13; const byte interruptPin = 2; volatile byte state = LOW; void setup() { //配置PIN pinMode(ledPin, OUTPUT); pinMode(interruptPin, INPUT_PULLUP); //绑定中断PIN和中断服务以及中断的触发方式 attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE); } //主循环 void loop() { digitalWrite(ledPin, state); } //回掉函数 void blink() { state = !state; }
在上述代码中我们初始化了LED灯的PIN, 和中断的PIN,并且为中断的PIN绑定了中断服务, 且在主循环中一直调用digitalWrite向LED灯的PIN写低(关闭LED) 同时定义了一个回掉函数,那么当中断PIN发生状态切换的时候,那么当前LED灯的状态将触发中断服务,同时反转LED灯的状态.
总结
在本章节我们学习了如何使用Arduino的中断函数及其相关的API, 相信通过近期这几个帖子大家也能意识到如果不考虑底层实现, 仅仅使用Arduino来快速开发或者验证产品是十分快速方便的, 让我们继续期待下面的教程吧