跳到主要内容

Arduino 函数与中断

在Arduino编程中,函数和中断是两个非常重要的概念。函数用于封装代码逻辑,使程序更模块化和易于维护;而中断则是一种特殊的机制,允许程序在特定事件发生时立即响应,而不需要持续轮询。本文将详细介绍Arduino中的函数与中断,并通过实际案例帮助你理解它们的应用。

什么是函数?

函数是Arduino程序中的基本构建块之一。它是一个独立的代码块,可以接收输入参数、执行特定任务并返回结果。通过使用函数,你可以将复杂的程序分解为更小、更易管理的部分。

函数的定义与调用

在Arduino中,函数的定义通常包括返回类型、函数名、参数列表和函数体。以下是一个简单的函数示例:

cpp
int add(int a, int b) {
return a + b;
}

这个函数名为 add,接收两个整数参数 ab,并返回它们的和。你可以在程序的其他地方调用这个函数:

cpp
void setup() {
Serial.begin(9600);
int result = add(3, 5);
Serial.println(result); // 输出:8
}

void loop() {
// 主循环代码
}
提示

函数不仅可以返回基本数据类型(如 intfloat),还可以返回更复杂的数据类型(如数组或结构体)。

什么是中断?

中断是一种硬件机制,允许微控制器在特定事件发生时立即暂停当前任务,转而执行一个特殊的函数(称为中断服务程序,ISR)。中断通常用于处理实时事件,例如按键按下、传感器数据到达或定时器溢出。

中断的类型

Arduino支持两种类型的中断:

  1. 外部中断:由外部引脚的电平变化触发。
  2. 定时器中断:由内部定时器触发。

使用外部中断

以下是一个使用外部中断的示例。假设你希望在一个按钮按下时立即点亮LED:

cpp
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())或复杂的计算,以免影响程序的实时性。

使用定时器中断

定时器中断可以用于周期性任务,例如每秒钟读取一次传感器数据。以下是一个简单的定时器中断示例:

cpp
#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:按键去抖

在按键操作中,机械开关可能会产生抖动,导致多次触发中断。通过结合函数和中断,可以实现按键去抖:

cpp
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:实时数据采集

假设你需要实时采集传感器的数据,并在特定条件下触发警报:

cpp
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编程中不可或缺的工具。函数使代码更模块化和可维护,而中断则提供了处理实时事件的能力。通过结合两者,你可以编写出高效、响应迅速的程序。

备注

如果你想进一步学习,可以参考以下资源:

尝试完成以下练习,巩固你的知识:

  1. 编写一个函数,计算两个数的平均值,并在串口监视器中输出结果。
  2. 使用中断实现一个简单的计数器,每次按下按钮时计数加1,并在LED上显示计数值(使用二进制编码)。