2. 按键控制LED
任务目标
使用ESP32开发板读取按键状态,实现每次按下按键时LED亮灭状态切换。通过本案例掌握GPIO数字输入配置、按键消抖处理以及基本的电平检测逻辑。
硬件准备
- ESP32开发板(如ESP32-DevKitC)
- 1个LED(推荐红色或蓝色)
- 1个轻触按键
- 1个220Ω限流电阻(LED用)
- 1个10kΩ下拉电阻(按键用)
- 面包板及杜邦线若干
电路连接
- LED阳极 → GPIO2(通过220Ω电阻)
- LED阴极 → GND
- 按键一端 → GPIO4
- 按键另一端 → 3.3V
- GPIO4 → 10kΩ电阻 → GND(下拉电阻,确保未按下时读到低电平)
完整代码
#include <stdio.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define LED_GPIO GPIO_NUM_2
#define BUTTON_GPIO GPIO_NUM_4
#define DEBOUNCE_MS 20
void app_main(void)
{
// 配置LED引脚为推挽输出
gpio_config_t led_conf = {
.pin_bit_mask = (1ULL << LED_GPIO),
.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_GPIO),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_ENABLE,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&btn_conf);
bool led_state = false;
int last_level = 0;
int stable_level = 0;
TickType_t last_change_time = 0;
gpio_set_level(LED_GPIO, 0);
while (1) {
int current_level = gpio_get_level(BUTTON_GPIO);
TickType_t now = xTaskGetTickCount();
// 消抖:仅在电平变化持续超过DEBOUNCE_MS后确认状态
if (current_level != stable_level) {
if (now - last_change_time > pdMS_TO_TICKS(DEBOUNCE_MS)) {
stable_level = current_level;
// 检测到按下沿(从低到高)
if (stable_level == 1 && last_level == 0) {
led_state = !led_state;
gpio_set_level(LED_GPIO, led_state ? 1 : 0);
}
last_level = stable_level;
}
} else {
last_change_time = now;
}
vTaskDelay(pdMS_TO_TICKS(5));
}
}
代码说明
代码采用软件消抖方式:按键状态变化后,等待20ms确认电平是否稳定,避免机械抖动导致误触发。仅在检测到按键从低电平变为高电平(按下动作)时翻转LED状态。GPIO4配置为输入并启用内部下拉电阻,因此未按下时读到低电平,按下时读到高电平。
编译与烧录
# 在项目目录下执行
idf.py set-target esp32
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
将/dev/ttyUSB0替换为实际串口设备名(Windows下为COMx)。
验证方法
- 烧录成功后,观察LED初始状态为熄灭。
- 按下按键并松开,LED应点亮。
- 再次按下并松开,LED应熄灭。
- 快速连续按动按键,每次按下LED状态都应可靠切换,无跳变或闪烁。
若LED状态切换不稳定或一次按下多次切换,可适当增大DEBOUNCE_MS值(如改为30或50)后重新编译烧录。