中断原理与Arduino

文章目录

    • 前言
    • CPU中断
    • Arduino中断
    •  触发原理
    • 在setup函数中配置中断
    • 附录

前言

无论是在现代PC中,还是在嵌入式系统中(如Arduino,51单片机,还是stm32),中断都是重要的概念,此文我将介绍中断的原理与其在Arduino中的应用

CPU中断

中断是指计算机在执行当前程序的过程中,当出现某些紧急或需要立即处理的事件时,暂时停止正在执行的程序,转而去处理这些事件,待处理完成后再返回原来的程序继续执行的过程。

中断中断可以分为内中断和外中断

内中断:中断信号来源于CPU内部

例1:当CPU处在用户态时执行特权指令

例2:执行除法时发现除数为0

例3:应用程序想要请求操作系统内核的服务,会执行陷入指令

以上三个例子会引发中断信号,CPU会立即处理该中断

外中断:中断信号来源于CPU外部

例1:时钟中断-------由CPU时钟部件引发的

例2:I/O中断------由输入输出设备引发的中断信号

Arduino中断

触发原理

Arduino中断有两种种方式,时钟中断和外部中断,此文我只介绍外部中断,因为时钟中断并不常见。

常见的Arduino板是UNO板,它有外部中断引脚,2和3,分别产生的中断信号是0和1

只有使用正确的引脚才能触发中断 

常见的中断触发模式如下:

在setup函数中配置中断:

void setup()
{
    attachTnterrupt(中断编号,中断函数,中断触发模式) 
}

例如:attachInterrupt(0,onChange,Change)

          中断编号0对应的是2号引脚,Change是电平改变时触发,当触发中断时会调用onCHange函数

如果觉得要查引脚号对应的中断号麻烦的话,可以用digitalPinToInterrupt(引脚号)函数 ,例如:

 attachInterrupt(digitalPinToInterrupt(2),onChange,Change)

项目实例

下面用所学知识做一个项目,用按钮控制LED的亮灭,代码如下:

const int ledPin = 8;//定义led引脚,const使ledPin的值无法修改,防止程序被意外修改
const int buttonPin = 2;//定义按钮引脚为2
volatile bool ledState = LOW;
/*volatile用于修饰可能被意外修改的值,保证主程序和中断服务函数能正确访问和修改变量*/

void led_change(){
  ledState=!ledState; //对ledState的状态取反
  digitalWrite(ledPin,ledState);
}

void setup() {
  pinMode(ledPin,OUTPUT);
  pinMode(buttonPin,INPUT); 
  attachInterrupt(digitalPinToInterrupt(buttonPin),led_change,FALLING);//设置中断函数
}

void loop() { 
  //此处可以正常运行其他程序,只有当中断触发时,Arduino才会执行中断程序
}

但这个代码是不完善的,因为普通按钮会发生抖动, 因而需要加入消抖逻辑:

millis()是arduino中的一个非常实用的函数,用于返回Arduino板通电以来经过的时间(unsigned int类型),单位是毫秒,例如:

unsigned long startTime = millis();  //用于记录arduino板当前时间
unsigned long elapseTime = millis() - startTime;  //用于计算从记录的时间到现在所经过的时间

 改进后的代码如下:

const int ledPin = 8;
const int buttonPin = 2;
volatile bool ledState = LOW;
unsigned long lastDebounceTime = 0; //记录上次按下的时间
unsigned long debounceDelay = 50; //在触发中断的50毫秒内不再触发中断

void led_change() {
  if (millis() - lastDebounceTime > debounceDelay) {
    ledState =!ledState;
    digitalWrite(ledPin, ledState);
    lastDebounceTime = millis();
  }
}

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT); 
  attachInterrupt(digitalPinToInterrupt(buttonPin), led_change, CHANGE);
}

void loop() {
  
}

附录 :

(1)detachInterrupt()

取消中断函数。

函数原型:

void detachInterrupt(uint8_t interruptNum)

 例子:

detachInterrupt(digitalPinToInterrupt(2));//取消2号引脚的中断

(2)interrupts()

重新启用中断。中断允许一些重要任务在后台运行,默认状态是启用的。禁用中断后一些函数可能无法工作,并且传入信息可能会被忽略。

函数原型:

#define interrupts() sei()

参数:无 

(3)noInterrupts()

 禁止中断。

 函数原型:

#define noInterrupts() cli()

参数:无

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值