目录
Arduino外部中断是一种功能,允许微控制器在检测到指定引脚上的信号变化时暂时停止当前执行的任务,而去执行一段特定的代码(中断服务程序ISR),之后再返回到原来的任务。这种方式非常适合需要对实时或紧急事件做出快速响应的应用场景,比如按键检测、传感器信号监测等。ESP32 上的 GPIO 外设支持中断。
1、attachInterrupt
该函数用于将中断连接到定义的引脚。
attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode);
- pin定义 GPIO 引脚编号。
- handler设置处理程序函数。
- mode设置中断模式。
以下是支持的中断模式:
- DISABLED:表示中断功能被禁用。在这种模式下,即使有相应的事件发生,也不会触发中断服务程序执行。
- RISING:上升沿触发中断。
- FALLING:下降沿触发中断。
- CHANGE:任意电平变化中断。无论引脚电平是从低到高,还是从高到低变化,都会触发中断。
- ONLOW:低电平中断。当引脚电平为低时,中断被触发。这种模式不是所有Arduino板都支持,但在一些特定平台或库中可能出现。
- ONHIGH:高电平中断。与ONLOW相反,当引脚电平为高时,中断被触发。同样,此模式并非所有环境都支持。
- ONLOW_WE / ONHIGH_WE:这些模式可能是特定平台或库中的特有模式,其中“_WE”可能代表“With Debounce”(带消抖),意味着在低电平或高电平状态下,经过消抖处理后才触发中断,以防止因接触不良或快速波动导致的错误中断触发。不过,这种解释依赖于具体上下文,因为“WE”也可能有其他含义,在标准Arduino中断模式中并不常见。
请注意,除了前四种(DISABLED, RISING, FALLING, CHANGE)是Arduino中比较通用的中断模式外,后面的几种(ONLOW, ONHIGH, ONLOW_WE, ONHIGH_WE)可能不是所有Arduino板或标准库直接支持的。这些特殊模式可能出现在特定的库、自定义固件或更高级的微控制器上,因此在使用时需要查阅具体平台或库的文档确认。(ESP32都支持)
2、attachInterruptArg
该函数用于使用参数将中断附加到定义的引脚。
attachInterruptArg(uint8_t pin, voidFuncPtrArg handler, void * arg, int mode);
- pin定义 GPIO 引脚编号。
- handler设置处理程序函数。
- arg指向中断参数的指针。
- mode设置中断模式。
3、detachInterrupt
要从特定引脚上分离中断,请使用提供要分离的 GPIO 的功能。
- pin定义 GPIO 引脚编号。
detachInterrupt(uint8_t pin);
4、示例代码
#define LED 12
#define BUTTON 2
uint8_t stateLED = 0;
void setup() {
pinMode(LED, OUTPUT);
pinMode(BUTTON,INPUT_PULLUP);
}
void loop() {
if(!digitalRead(BUTTON)){
stateLED = stateLED^1;
digitalWrite(LED,stateLED);
}
}
#include <Arduino.h>
struct Button {
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
};
Button button1 = {23, 0, false};
Button button2 = {18, 0, false};
void ARDUINO_ISR_ATTR isr(void *arg) {
Button *s = static_cast<Button *>(arg);
s->numberKeyPresses += 1;
s->pressed = true;
}
void ARDUINO_ISR_ATTR isr() {
button2.numberKeyPresses += 1;
button2.pressed = true;
}
void setup() {
Serial.begin(115200);
pinMode(button1.PIN, INPUT_PULLUP);
attachInterruptArg(button1.PIN, isr, &button1, FALLING);
pinMode(button2.PIN, INPUT_PULLUP);
attachInterrupt(button2.PIN, isr, FALLING);
}
void loop() {
if (button1.pressed) {
Serial.printf("Button 1 has been pressed %lu times\n", button1.numberKeyPresses);
button1.pressed = false;
}
if (button2.pressed) {
Serial.printf("Button 2 has been pressed %lu times\n", button2.numberKeyPresses);
button2.pressed = false;
}
static uint32_t lastMillis = 0;
if (millis() - lastMillis > 10000) {
lastMillis = millis();
detachInterrupt(button1.PIN);
}
}