Arduino 中断介绍
在Arduino编程中,中断是一种强大的机制,允许微控制器在执行主程序的同时,对外部事件做出快速响应。中断可以暂停当前正在执行的代码,转而执行一个特殊的函数(称为中断服务程序,ISR),然后再返回到原来的代码继续执行。
中断通常用于处理时间敏感的任务,例如读取传感器数据、检测按钮按下或处理外部信号。通过使用中断,Arduino可以更高效地处理这些事件,而不需要不断地轮询输入状态。
中断的基本概念
什么是中断?
中断是一种硬件或软件触发的信号,用于通知微控制器某个事件已经发生。当中断发生时,微控制器会暂停当前的任务,保存当前状态,并跳转到预先定义的中断服务程序(ISR)中执行。执行完ISR后,微控制器会恢复之前的状态,并继续执行主程序。
中断的类型
Arduino支持两种类型的中断:
硬件中断:由外部硬件信号触发,例如按钮按下或传感器信号变化。
软件中断:由程序内部触发,例如定时器溢出或特定条件满足。
中断的优点
实时响应:中断可以立即响应外部事件,而不需要等待主程序轮询。
高效性:通过中断处理事件,可以减少CPU的轮询开销。
简化代码:中断可以将事件处理逻辑与主程序分离,使代码更清晰。
Arduino 中断的使用
中断引脚
Arduino的不同型号支持不同数量的中断引脚。例如,Arduino Uno有两个外部中断引脚:D2和D3。这些引脚可以配置为在信号上升沿、下降沿或电平变化时触发中断。
配置中断
在Arduino中,使用attachInterrupt()函数来配置中断。该函数的语法如下:
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode);
pin:中断引脚号。
ISR:中断服务程序的函数名。
mode:中断触发模式,可以是以下值之一:
LOW:低电平时触发。
CHANGE:电平变化时触发。
RISING:上升沿触发。
FALLING:下降沿触发。
示例:按钮中断
以下是一个简单的示例,展示如何使用中断检测按钮按下:
const int buttonPin = 2; // 按钮连接到D2引脚volatile bool buttonPressed = false; // 用于存储按钮状态的变量void setup() { pinMode(buttonPin, INPUT); attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, FALLING); Serial.begin(9600);}void loop() { if (buttonPressed) { Serial.println("Button pressed!"); buttonPressed = false; // 重置按钮状态 }}void buttonISR() { buttonPressed = true; // 在中断中设置按钮状态}
在这个示例中,当按钮按下时,buttonISR()函数会被调用,并将buttonPressed变量设置为true。主程序在loop()中检测到这个变化,并打印一条消息。
备注注意:在中断服务程序(ISR)中,应尽量避免使用delay()或执行耗时操作,因为这会影响主程序的执行。
实际应用场景
案例1:旋转编码器
旋转编码器是一种常见的输入设备,用于检测旋转方向和速度。通过使用中断,可以实时检测编码器的信号变化,并计算旋转方向和步数。
const int pinA = 2; // 编码器A相连接到D2const int pinB = 3; // 编码器B相连接到D3volatile int encoderPos = 0; // 编码器位置void setup() { pinMode(pinA, INPUT); pinMode(pinB, INPUT); attachInterrupt(digitalPinToInterrupt(pinA), encoderISR, CHANGE); Serial.begin(9600);}void loop() { Serial.println(encoderPos); // 打印编码器位置}void encoderISR() { int stateA = digitalRead(pinA); int stateB = digitalRead(pinB); if (stateA == stateB) { encoderPos++; // 顺时针旋转 } else { encoderPos--; // 逆时针旋转 }}
案例2:超声波传感器
超声波传感器通常用于测量距离。通过使用中断,可以在接收到回波信号时立即计算距离,而不需要等待主程序轮询。
const int trigPin = 9; // 超声波传感器触发引脚const int echoPin = 2; // 超声波传感器回波引脚volatile long duration = 0; // 存储回波时间volatile bool echoReceived = false; // 回波接收标志void setup() { pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); attachInterrupt(digitalPinToInterrupt(echoPin), echoISR, CHANGE); Serial.begin(9600);}void loop() { if (echoReceived) { long distance = duration * 0.034 / 2; // 计算距离 Serial.print("Distance: "); Serial.println(distance); echoReceived = false; // 重置标志 } digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW);}void echoISR() { static unsigned long startTime = 0; if (digitalRead(echoPin) == HIGH) { startTime = micros(); // 记录回波开始时间 } else { duration = micros() - startTime; // 计算回波持续时间 echoReceived = true; // 设置回波接收标志 }}
总结
中断是Arduino编程中一个强大的工具,可以帮助你实时响应外部事件,提高程序的效率和响应速度。通过合理使用中断,你可以简化代码结构,并处理时间敏感的任务。
提示提示:在使用中断时,务必注意中断服务程序的执行时间,避免影响主程序的正常运行。
附加资源与练习
练习1:修改按钮中断示例,使其在按钮按下时点亮LED灯。
练习2:使用中断实现一个简单的计数器,每按一次按钮,计数器加1,并在串口监视器中显示计数值。
参考资源:
Arduino官方文档:中断
Arduino中断教程
通过以上内容,你应该对Arduino中断有了初步的了解。继续实践和探索,你将能够更好地掌握这一强大的功能!