Arduino 函数与中断
在Arduino编程中,函数和中断是两个非常重要的概念。函数用于封装代码逻辑,使程序更模块化和易于维护;而中断则是一种特殊的机制,允许程序在特定事件发生时立即响应,而不需要持续轮询。本文将详细介绍Arduino中的函数与中断,并通过实际案例帮助你理解它们的应用。
什么是函数?
函数是Arduino程序中的基本构建块之一。它是一个独立的代码块,可以接收输入参数、执行特定任务并返回结果。通过使用函数,你可以将复杂的程序分解为更小、更易管理的部分。
函数的定义与调用
在Arduino中,函数的定义通常包括返回类型、函数名、参数列表和函数体。以下是一个简单的函数示例:
int add(int a, int b) {
return a + b;
}
这个函数名为 add
,接收两个整数参数 a
和 b
,并返回它们的和。你可以在程序的其他地方调用这个函数:
void setup() {
Serial.begin(9600);
int result = add(3, 5);
Serial.println(result); // 输出:8
}
void loop() {
// 主循环代码
}
函数不仅可以返回基本数据类型(如 int
、float
),还可以返回更复杂的数据类型(如数组或结构体)。
什么是中断?
中断是一种硬件机制,允许微控制器在特定事件发生时立即暂停当前任务,转而执行一个特殊的函数(称为中断服务程序,ISR)。中断通常用于处理实时事件,例如按键按下、传感器数据到达或定时器溢出。
中断的类型
Arduino支持两种类型的中断:
- 外部中断:由外部引脚的电平变化触发。
- 定时器中断:由内部定时器触发。
使用外部中断
以下是一个使用外部中断的示例。假设你希望在一个按钮按下时立即点亮LED:
const int buttonPin = 2; // 按钮连接到引脚2
const int ledPin = 13; // LED连接到引脚13
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), buttonPressed, FALLING);
}
void loop() {
// 主循环代码
}
void buttonPressed() {
digitalWrite(ledPin, !digitalRead(ledPin)); // 切换LED状态
}
在这个示例中,attachInterrupt
函数用于将 buttonPressed
函数注册为中断服务程序。当按钮按下时(引脚2的电平从高变低),Arduino会立即调用 buttonPressed
函数。
中断服务程序应尽可能简短,避免使用延迟函数(如 delay()
)或复杂的计算,以免影响程序的实时性。
使用定时器中断
定时器中断可以用于周期性任务,例如每秒钟读取一次传感器数据。以下是一个简单的定时器中断示例:
#include <TimerOne.h>
void setup() {
Serial.begin(9600);
Timer1.initialize(1000000); // 设置定时器周期为1秒
Timer1.attachInterrupt(timerISR); // 注册中断服务程序
}
void loop() {
// 主循环代码
}
void timerISR() {
Serial.println("1 second passed!"); // 每秒输出一次
}
在这个示例中,Timer1
库用于设置一个1秒的定时器,并在每次定时器溢出时调用 timerISR
函数。
实际应用案例
案例1:按键去抖
在按键操作中,机械开关可能会产生抖动,导致多次触发中断。通过结合函数和中断,可以实现按键去抖:
const int buttonPin = 2;
const int ledPin = 13;
volatile bool buttonState = false;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), buttonPressed, FALLING);
}
void loop() {
if (buttonState) {
digitalWrite(ledPin, HIGH);
delay(500); // 点亮LED 0.5秒
digitalWrite(ledPin, LOW);
buttonState = false;
}
}
void buttonPressed() {
static unsigned long lastInterruptTime = 0;
unsigned long interruptTime = millis();
if (interruptTime - lastInterruptTime > 200) { // 去抖时间200ms
buttonState = true;
}
lastInterruptTime = interruptTime;
}
案例2:实时数据采集
假设你需要实时采集传感器的数据,并在特定条件下触发警报:
const int sensorPin = A0;
const int alarmPin = 9;
volatile bool alarmTriggered = false;
void setup() {
pinMode(alarmPin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(sensorPin), checkSensor, RISING);
}
void loop() {
if (alarmTriggered) {
tone(alarmPin, 1000); // 触发警报
delay(1000);
noTone(alarmPin);
alarmTriggered = false;
}
}
void checkSensor() {
int sensorValue = analogRead(sensorPin);
if (sensorValue > 500) {
alarmTriggered = true;
}
}
总结
函数和中断是Arduino编程中不可或缺的工具。函数使代码更模块化和可维护,而中断则提供了处理实时事件的能力。通过结合两者,你可以编写出高效、响应迅速的程序。
如果你想进一步学习,可以参考以下资源:
- Arduino官方文档
- 《Arduino编程从入门到精通》
尝试完成以下练习,巩固你的知识:
- 编写一个函数,计算两个数的平均值,并在串口监视器中输出结果。
- 使用中断实现一个简单的计数器,每次按下按钮时计数加1,并在LED上显示计数值(使用二进制编码)。