循环错过的一次按键
本课属于 Coddy Arduino 学习旅程的“无需 delay 的计时”单元。第 12 课,共 18 课。
草图有时会忙于执行耗时的任务,或等待较长时间的 delay()。如果循环只在任务之间读取按钮,就会漏掉在任务执行期间按下又松开的操作。
中断可以解决这个问题:引脚状态发生变化时,开发板会暂停当前操作,运行你指定的函数,然后继续执行。即使在 delay() 期间,芯片也会自行监视引脚。
void onPress() {
digitalWrite(ledPin, HIGH);
}
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), onPress, FALLING);
}attachInterrupt()需要三个参数:引脚对应的中断(digitalPinToInterrupt(buttonPin)会找到它)、要运行的函数,以及触发时机。FALLING表示引脚从 HIGH变为 LOW的时刻:启用上拉时,也就是按钮按下的时刻。
这个函数称为中断服务例程,简称 ISR。让它尽可能简短:不要使用 delay(),也不要使用 Serial。
挑战
简单这个警报器每隔 2 秒才检查一次按钮,所以快速按下时会漏掉。让按下按钮后 LED 立即亮起:
- 编写一个 ISR,
onPress(),让 LED 亮起 - 在
setup()中,将它连接到按钮引脚,并使用FALLING
将耗时的任务保留在 loop() 中。按下按钮后,LED 会像警报器一样保持亮起。按“运行”,点击按钮,然后按“检查”。
亲手试试
const int ledPin = 13;
const int buttonPin = 2;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(9600);
// 在这里绑定中断
}
void loop() {
// 耗时任务:保持原样
Serial.println("working");
delay(2000);
// 这里只会每隔 2 秒检查一次按钮,
// 所以短暂按下按钮可能会被漏掉
if (digitalRead(buttonPin) == LOW) {
digitalWrite(ledPin, HIGH);
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
无需 delay 的计时中的所有课
自己练习: Arduino 在线编辑器