2. 按键控制LED

任务目标

使用ESP32开发板,通过一个外部按键控制板载LED的亮灭状态。每次按下按键,LED状态翻转一次(亮→灭或灭→亮)。本案例聚焦GPIO数字输入模式的配置与状态读取方法。

所需硬件与接线

  • ESP32开发板(板载LED通常连接GPIO2)
  • 轻触按键一个
  • 面包板及杜邦线若干

接线方式:按键一端连接GPIO18,另一端连接GND。GPIO18内部启用上拉电阻,按键按下时读到低电平,释放时读到高电平。板载LED使用GPIO2(大多数ESP32开发板默认),若你的开发板LED引脚不同,请对应修改代码中的LED_PIN。

完整代码

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

#define LED_PIN      GPIO_NUM_2
#define BUTTON_PIN   GPIO_NUM_18

// 消抖延时(毫秒)
#define DEBOUNCE_MS  50

void app_main(void)
{
    // 配置LED引脚为推挽输出
    gpio_config_t led_conf = {
        .pin_bit_mask = (1ULL << LED_PIN),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
    };
    gpio_config(&led_conf);

    // 配置按键引脚为输入,启用内部上拉
    gpio_config_t btn_conf = {
        .pin_bit_mask = (1ULL << BUTTON_PIN),
        .mode = GPIO_MODE_INPUT,
        .pull_up_en = GPIO_PULLUP_ENABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
    };
    gpio_config(&btn_conf);

    bool led_state = false;
    int last_level = 1;  // 上拉默认高电平
    TickType_t last_change_time = 0;

    while (1) {
        int level = gpio_get_level(BUTTON_PIN);

        // 检测下降沿(按下瞬间)
        if (level == 0 && last_level == 1) {
            // 简单消抖:确认电平稳定后再翻转
            vTaskDelay(pdMS_TO_TICKS(DEBOUNCE_MS));
            if (gpio_get_level(BUTTON_PIN) == 0) {
                led_state = !led_state;
                gpio_set_level(LED_PIN, led_state ? 1 : 0);
            }
        }

        last_level = level;
        vTaskDelay(pdMS_TO_TICKS(10));  // 轮询间隔10ms
    }
}

编译与烧录

本案例基于ESP-IDF开发框架。在项目目录下执行以下命令:

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

请将/dev/ttyUSB0替换为你实际的串口设备名(Windows下为COMx)。

验证方法

  1. 烧录成功后,观察板载LED初始状态为熄灭。
  2. 按下按键并松开,LED应点亮。
  3. 再次按下并松开,LED应熄灭。
  4. 快速连续按动按键,每次按下LED状态都应翻转一次,且不会出现一次按下多次翻转的情况(消抖生效)。

若LED状态与预期不符,请检查LED引脚号是否正确,以及按键是否连接在GPIO18与GND之间。可通过串口监视器观察程序是否正常启动(无报错输出)。

关键说明

本案例采用轮询方式读取GPIO电平,通过检测电平下降沿(从高到低)识别按键按下动作。内部上拉电阻确保按键未按下时引脚为高电平,按下时接地为低电平。消抖延时50ms用于滤除机械按键的抖动噪声。若需更高效的实现,可改用GPIO中断方式,但轮询方式更直观地展示了GPIO输入状态读取的基本流程。