2. 按钮控制LED

任务目标

在ESP32上使用LVGL创建一个按钮控件,每次点击按钮时切换板载LED(GPIO2)的开关状态,并在按钮上实时显示当前LED状态(“LED: ON” / “LED: OFF”)。

环境与依赖

  • 硬件:ESP32开发板(板载LED接GPIO2)
  • 框架:ESP-IDF v5.x + LVGL v8.3(已配置好显示驱动与触摸/编码器输入)
  • LVGL配置:确保 CONFIG_LVGL_USE_SYSMON 未开启,lv_tick_inc() 已在定时器中调用

核心实现

本案例通过LVGL按钮的事件回调函数,在每次点击时翻转LED电平,并同步更新按钮上的文本标签。代码采用最小实现,不涉及额外UI元素。

// main.c 核心代码(仅展示LVGL相关部分)
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "lvgl.h"

#define LED_GPIO  2

static lv_obj_t *btn;
static lv_obj_t *btn_label;
static bool led_state = false;

// 按钮点击事件回调
static void btn_event_cb(lv_event_t *e) {
    // 翻转LED状态
    led_state = !led_state;
    gpio_set_level(LED_GPIO, led_state ? 1 : 0);

    // 更新按钮文本
    lv_label_set_text(btn_label, led_state ? "LED: ON" : "LED: OFF");
}

// 创建UI(在lvgl初始化完成后调用)
static void ui_create(void) {
    // 创建按钮
    btn = lv_btn_create(lv_scr_act());
    lv_obj_set_size(btn, 160, 60);
    lv_obj_center(btn);

    // 添加标签
    btn_label = lv_label_create(btn);
    lv_label_set_text(btn_label, "LED: OFF");
    lv_obj_center(btn_label);

    // 绑定点击事件
    lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_CLICKED, NULL);
}

// 主任务(在app_main中创建)
void lvgl_demo_task(void *arg) {
    // 初始化GPIO
    gpio_reset_pin(LED_GPIO);
    gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_level(LED_GPIO, 0);

    // 创建UI
    ui_create();

    // LVGL主循环
    while (1) {
        lv_task_handler();
        vTaskDelay(pdMS_TO_TICKS(10));
    }
}

void app_main(void) {
    // 假设lvgl_init()已完成显示驱动、输入驱动和lv_init()的初始化
    xTaskCreate(lvgl_demo_task, "lvgl_demo", 4096, NULL, 5, NULL);
}

运行与验证

  1. 将上述代码合并到你的ESP-IDF工程中,确保LVGL已正确初始化(包括显示驱动和输入设备驱动)。
  2. 编译并烧录:idf.py build flash monitor
  3. 观察屏幕:应显示一个居中按钮,初始文本为“LED: OFF”。
  4. 点击按钮(通过触摸屏或编码器按键),观察板载LED是否亮起,按钮文本变为“LED: ON”。
  5. 再次点击,LED熄灭,文本恢复为“LED: OFF”。

通过条件:每次点击按钮,LED状态和按钮文本同步切换,无卡顿或误触发。

关键说明

  • 事件使用 LV_EVENT_CLICKED,仅在按钮释放且仍在按钮区域内时触发,避免长按误操作。
  • GPIO2在部分开发板上可能连接板载LED(低电平点亮),若你的硬件极性相反,将 gpio_set_level 中的逻辑反转即可。
  • 若使用编码器按键作为输入,需确保LVGL的输入设备已正确注册,否则按钮无法获得焦点和点击事件。