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