目录
3.2 FALLING 下降沿沿触发中断的demo.(可测试中断功能)
对前两小节介绍不感兴趣的可以直接从看2.2开始看
1.为什么要使用外部中断?()
1.1系统延时导致程序监测不灵敏
我们Arduino单片机是单线程,轮询的方式运行的,即我们的程序是在一个循环中持续运行,在实际使用的过程中,我们的项目难免会出现一定时间的延时.这个延时会干扰我们轮询判断的速度.
假如说我们做一个普通的按键读取,他读取这个按键状态如果是低电平,处理相应的函数.但是我们的主程序每次循环都有一定时间的延时,在这个延时期间如果按键连续按了3次,我们的程序是无法获取到的按键变化的.
1.2节省CPU资源
使用外部中断,可以减少不必要的CPU周期消耗。如果系统不断轮询某些外部设备,CPU需要频繁检查设备状态,而使用中断时,CPU可以在没有事件时空闲工作,当事件发生时自动中断当前任务,进行处理,减少了CPU的空闲检查工作。
1.3适用于嵌入式系统和硬件接口
在嵌入式系统中,外部中断是常用的机制。许多硬件接口(如串口、定时器、外部传感器)通过外部中断来通知处理器进行数据传输或状态变化,避免了处理器主动检查每个接口的需要,从来提升运行效率.
2.中断的概念
单片机在执行程序时遇见紧急且需要迫切记录的任务,能够暂时中止当前正在运行的任务,去处理更为紧急的任务,然后再返回继续执行原来的任务。中断通常由硬件或软件事件触发,是一种异步的事件响应机制。
2.1中断的执行流程
1.中断请求(引脚上升沿下降沿或者其他)
2.保存当前执行状态
3. 跳转到中断服务程序(ISR)
4.执行中断服务程序(ISR)
5.中断返回与恢复执行(回到原本的执行逻辑)
2.2Arduino中断编号和对应引脚
Arduino中的调用函数是采用的中断编号,也可用函数来映射中断编号,下文有相关讲解,将对应引脚配置成相关的 输入上拉模式来检测是否触发中断.
3. 外部中断函数
3.1 attachInterrupt
attachInterrupt(num,Function,Mode);
//开启指定引脚中断
参数1(num
):中断编号 Arduino UNO的编号是0或者1 为了方便理解我们可以用digitalPinToInterrupt(pin)来映射对应引脚(本来中断编号0就是引脚2,这里我们可以直接填写引脚2,方便理解)
attachInterrupt(0,Function,Mode);等效与
attachInterrupt(digitalPinToInterrupt(2), Function, Mode);
参数2(Function
):中断回调函数,触发中断后会进入这个函数
参数3(Mode
):触发中断的模式.
Mode | 说明 |
RISING | 上升沿触发:由低电平到高电平变化进入中断(需要配置上拉输入,因为不支持下拉输入) |
FALLING | 下降沿触发:由高电平到低电平进入中断(需要配置上拉输入) |
LOW | 保持低电平触发中断 |
CHANGE | 电平发生变化触发(上升沿和下降沿都触发) |
在平时使用的过程中,上升沿和下降沿两种触发方式较为常用,LOW模式一般不去使用,只要检测到低电平直接进入中断程序.
下面三种函数基本不用,了解即可,attachInterrupt函数默认打开的中断.
detachInterrupt(digitalPinToInterrupt(pin));
//取消指定引脚的中断
interrupts();
//开中断
noInterrupts();
//关中断
3.1.1 上升沿触发和下降沿触发
3.2 FALLING 下降沿沿触发中断的demo.(可测试中断功能)
bool flag =0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200); //串口初始化,方便查看串口打印
attachInterrupt(digitalPinToInterrupt(2),interrupt_callback,FALLING);//中断号为0 对应D2引脚 interrupt_callback中断服务函数,进入中断后执行该函数内容 FALLING 下降沿触发
pinMode(2,INPUT_PULLUP); //外部中断为读取外部引脚变化,所以需要配置引脚输入模式,这里是下降沿,高电平变为低电平,默认拉高,所以引脚模式是INPUT_PULLUP上拉输入
pinMode(13,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
delay(10000);//阻塞延迟10s,
}
void interrupt_callback(){//中断服务函数
Serial.println("按键下降沿触发中断");//这是为了测试中断瞬间触发.正常情况下不要在中断服务函数中执行其他命令,一般为标志位赋值.
}
3.4 RISING demo
bool flag =0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200); //串口初始化,方便查看串口打印
attachInterrupt(digitalPinToInterrupt(2),interrupt_callback,RISING);//中断号为0 对应D2引脚 interrupt_callback中断服务函数,进入中断后执行该函数内容 RISING下降沿触发
pinMode(2,INPUT_PULLUP); //外部中断为读取外部引脚变化,所以需要配置引脚输入模式,这里是下降沿,高电平变为低电平,默认拉高,所以引脚模式是INPUT_PULLUP上拉输入
pinMode(13,OUTPUT);
}
void loop() {
delay(10000);//阻塞延迟10s
}
void interrupt_callback(){//中断服务函数
flag=1;
Serial.println("按键上升沿沿触发中断");//这是为了测试中断瞬间触发.正常情况下不要在中断服务函数中执行其他命令,一般为标志位赋值.
}
3.3极简版中断,方便基础弱的同志直接调用
volatile bool flag =0; //在中断服务函数中使用的变量需要用volatile
void setup() {
// put your setup code here, to run once:
Serial.begin(115200); //串口初始化,方便查看串口打印
attachInterrupt(digitalPinToInterrupt(2),interrupt_callback,RISING);//中断号为0 对应D2引脚 interrupt_callback中断服务函数,进入中断后执行该函数内容 FALLING 下降沿触发
pinMode(2,INPUT_PULLUP); //外部中断为读取外部引脚变化,所以需要配置引脚输入模式,这里是下降沿,高电平变为低电平,默认拉高,所以引脚模式是INPUT_PULLUP上拉输入
pinMode(13,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
if(flag==1)
{
flag=0;
}
}
void interrupt_callback(){//中断服务函数
flag=1;
}