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)。
验证方法
- 烧录成功后,观察板载LED初始状态为熄灭。
- 按下按键并松开,LED应点亮。
- 再次按下并松开,LED应熄灭。
- 快速连续按动按键,每次按下LED状态都应翻转一次,且不会出现一次按下多次翻转的情况(消抖生效)。
若LED状态与预期不符,请检查LED引脚号是否正确,以及按键是否连接在GPIO18与GND之间。可通过串口监视器观察程序是否正常启动(无报错输出)。
关键说明
本案例采用轮询方式读取GPIO电平,通过检测电平下降沿(从高到低)识别按键按下动作。内部上拉电阻确保按键未按下时引脚为高电平,按下时接地为低电平。消抖延时50ms用于滤除机械按键的抖动噪声。若需更高效的实现,可改用GPIO中断方式,但轮询方式更直观地展示了GPIO输入状态读取的基本流程。