3. 按键中断处理

任务目标

本案例使用ESP32-S3开发板,将GPIO0配置为按键输入并启用下降沿中断,GPIO2配置为LED输出。当按键按下时触发中断服务函数,在中断中通过软件标志通知主循环翻转LED状态,以此掌握ESP-IDF中断处理机制与GPIO中断配置方法。

硬件连接

  • 按键一端接GPIO0,另一端接GND(按下为低电平)
  • LED正极经220Ω电阻接GPIO2,负极接GND
  • 开发板内部上拉电阻使能,按键未按下时GPIO0为高电平

完整代码

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"

#define BUTTON_GPIO     GPIO_NUM_0
#define LED_GPIO        GPIO_NUM_2
#define ESP_INTR_FLAG_DEFAULT 0

static const char *TAG = "button_intr";
static volatile bool led_state = false;
static volatile bool button_pressed = false;

// 中断服务函数 - 只做标志置位,不执行耗时操作
static void IRAM_ATTR button_isr_handler(void *arg)
{
    button_pressed = true;
}

void app_main(void)
{
    // 配置LED引脚
    gpio_reset_pin(LED_GPIO);
    gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_level(LED_GPIO, 0);

    // 配置按键引脚
    gpio_reset_pin(BUTTON_GPIO);
    gpio_set_direction(BUTTON_GPIO, GPIO_MODE_INPUT);
    gpio_set_pull_mode(BUTTON_GPIO, GPIO_PULLUP_ONLY);  // 内部上拉

    // 安装GPIO中断服务
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    gpio_isr_handler_add(BUTTON_GPIO, button_isr_handler, NULL);
    gpio_set_intr_type(BUTTON_GPIO, GPIO_INTR_NEGEDGE);  // 下降沿触发

    ESP_LOGI(TAG, "按键中断已配置,按下GPIO0翻转LED");

    while (1) {
        if (button_pressed) {
            button_pressed = false;   // 清除标志
            led_state = !led_state;   // 翻转状态
            gpio_set_level(LED_GPIO, led_state ? 1 : 0);
            ESP_LOGI(TAG, "LED状态: %s", led_state ? "ON" : "OFF");
        }
        vTaskDelay(pdMS_TO_TICKS(10));  // 10ms轮询标志
    }
}

编译与烧录

idf.py set-target esp32s3
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor

验证方法

  1. 烧录后打开串口监视器,日志显示“按键中断已配置”
  2. 按下按键(GPIO0接地),松开后观察LED状态翻转
  3. 串口输出“LED状态: ON/OFF”交替出现,每次按键对应一次翻转
  4. 连续快速按键多次,LED状态应跟随每次按键翻转,无漏检

通过标准:每次按下并松开按键,LED状态翻转一次且串口日志同步更新,说明中断触发与标志处理逻辑正确。

关键说明

  • 中断服务函数必须加IRAM_ATTR属性,确保代码运行在内部RAM中
  • ISR内只置标志位,实际处理(翻转LED)放在主循环中执行,避免在中断上下文做耗时操作
  • 使用gpio_install_isr_service统一管理GPIO中断,支持多个GPIO共用中断服务
  • 若按键存在机械抖动,可在硬件上加RC滤波或软件延时消抖;本案例为演示中断机制,未做消抖处理