打造專業級 UI | ESP32 LVGL 安裝與專案結構完整教學


ESP32 LVGL 在現代嵌入在嵌入式開發領域,ESP32 是一顆高性價比又多功能的 Wi-Fi + 藍牙 SoC,但要打造一個「看起來專業、操作直覺、效能良好」的 UI,單靠基本的顯示驅動還不夠。這時候,就該認識 LVGL(Light and Versatile Graphics Library)
它是一套專為嵌入式系統打造的輕量級 UI 函式庫,支援動畫、佈局、自訂樣式與觸控等功能,而且效能優秀,資源需求低,非常適合 ESP32。本篇文章會帶你從 0 開始,學會如何在 ESP-IDF 中安裝 LVGL、建立一個乾淨的專案架構,並成功顯示出第一個 LVGL 元件。

ESP32 LVGL

什麼是 LVGL?

LVGL(Light and Versatile Graphics Library) 是一套開源、跨平台的圖形界面函式庫,專為低資源裝置設計。

特色包括:

  • 社群活躍、文件完善
  • 支援 多種解析度與觸控輸入
  • 提供豐富的 UI 元件(按鈕、文字、清單、滑桿等)
  • 支援 動畫、佈局、主題切換

ESP32 LVGL 原理快速理解

ESP32 上運行 LVGL 前,了解其基本架構與運作原理能讓你更順利整合顯示與觸控設備。

LVGL 自身是一個「純 UI 引擎」,它不會直接與你的 LCD 或觸控 IC 通訊,而是透過你提供的驅動程式 callback來進行畫面輸出與輸入處理。

+------------------+
|      Your App    | ← 你的邏輯與 UI 流程
+------------------+
         ↓
+------------------+
|       LVGL       | ← UI 元件、動畫、樣式、佈局、事件處理等
+------------------+
         ↓
+------------------+
|  Display Driver  | ← 將 LVGL 繪製的像素輸出到 LCD(需實作)
|   Input Driver   | ← 處理觸控 / 按鈕等輸入(需實作)
+------------------+
         ↓
+------------------+
|   ESP32 + LCD    | ← 實體螢幕或觸控設備
+------------------+

LVGL 的運作流程核心

  • 初始化
    呼叫 lv_init() 啟動 LVGL
  • 註冊顯示驅動
    提供畫面 buffer(記憶體)
    提供 flush_cb() → 寫像素到螢幕的函式
  • 註冊輸入驅動
    提供讀取觸控或按鈕的 callback
  • UI 更新循環
    定時執行 lv_timer_handler() → 處理動畫、事件、重繪等
    通常每 5~10ms 呼叫一次

這些就是 ESP32 LVGL 的基本原理與工作機制,理解之後你會更容易在日後整合 LCD、觸控板,甚至加入圖示動畫與多頁面切換!

開發環境

在開始編程之前,請確保已完成以下準備工作:

專案結構

建立一個乾淨的 ESP-IDF LVGL 專案如下:

esp32_lvgl_project/
├── CMakeLists.txt
├── components/
│   └── lvgl/               ← LVGL
├── main/
│   ├── CMakeLists.txt
│   └── main.c              ← Main
├── sdkconfig

取得 LVGL 並整合到 ESP-IDF 專案

VGL 雖然不是 ESP-IDF 內建元件,但它支援用 components/ 的方式簡單整合。

mkdir -p components
cd components
git clone https://github.com/lvgl/lvgl.git

接著 ESP-IDF 會自動偵測 components/lvgl/ 並編譯。

複製 lv_conf_template.hlv_conf.h

因為 LVGL 預設只提供 lv_conf_template.h,你需要自己手動:

cp components/lvgl/lv_conf_template.h components/lvgl/lv_conf.h

打開 lv_conf.h,會看到最上面有這段:

#if 0 /* Set this to "1" to enable content */
要把它改成:
#if 1 /* Set this to "1" to enable content */

這樣整個設定檔才會被啟用!不然 LVGL 會完全用內建預設值(通常不適合直接用在 ESP32)。

程式碼

以下是基本的LVGL初始化代碼 (main/main.c):

#include "lvgl.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

void app_main(void)
{
    lv_init();  // Initialize LVGL

    // Screen driver initialization is skipped here for simplicity.
    // In practice, you should register the display driver and set up buffers.

    lv_obj_t *label = lv_label_create(lv_scr_act());
    lv_label_set_text(label, "Hello ESP32 + LVGL!");
    lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);

    while (1) {
        lv_timer_handler();              // Handle LVGL tasks (UI updates)
        vTaskDelay(pdMS_TO_TICKS(10));    // Call every 10 ms
    }
}

程式碼解說

  • lv_init():初始化 LVGL 核心。
  • lv_label_create():在主畫面上新增一個文字標籤元件。
  • lv_label_set_text():設定文字內容。
  • lv_obj_align():將元件置中。
  • lv_timer_handler():LVGL 的核心「畫面更新器」,必須定時呼叫。

編譯和燒錄

完成程式碼後,您可以使用 ESP-IDF 提供的命令進行編譯、燒錄和監控。

在 VS Code 的左下角 ESP-IDF 工具列:

  • 點選 Build project
  • 點選 Flash device
  • 點選 Monitor device

成功運行後,串口監視器將顯示如下輸出:
你會在序列埠看到 LVGL 初始化成功的 log,雖然還沒有畫面(因為還沒連接 LCD 驅動),但整個系統已經能正常編譯並執行 LVGL 的邏輯。

結論

從安裝 LVGL、理解其運作原理,到實際建立一個清晰的 ESP-IDF 專案架構,我們一步步走過了將 LVGL 整合進 ESP32 專案的完整流程。這不僅是一次技術上的整合練習,更是學會如何打造出具備專業外觀與良好體驗的嵌入式圖形界面。透過這篇文章,相信你已經掌握了 LVGL 最基本的使用方式與專案實作技巧,也為後續進一步整合觸控螢幕、動畫、事件處理等功能打下了紮實基礎。嵌入式開發不再只是文字輸出或 GPIO 控制,透過 LVGL,我們能讓硬體產品有更好的互動介面、更豐富的使用體驗。希望這篇教學能成為你開啟 UI 設計之路的起點,也歡迎你持續探索更多 LVGL 的潛力,讓你的 ESP32 專案真正「看起來就很專業」。