鏈接:https://docs.lvgl.io/master/
docs:LVGL
LVGL(Light and Versatile Graphics Library)是用于在資源受限的嵌入式
系統上創建圖形用戶界面(GUI)的開源解決方案。
它提供豐富的控件
和靈活的**事件
系統**來實現動態交互。
該庫能高效處理繪制/渲染到各類顯示屏的操作,并支持來自多種**輸入設備**的輸入
,所有功能都可通過中心化的配置進行定制。
概覽
章節
- 配置(lv_conf.h)
- 顯示屏(lv_display)
- 控件(lv_obj)
- 樣式(lv_style)
- 布局(lv_flex, lv_grid)
- 輸入設備(lv_indev)
- 事件系統(lv_event)
- 繪制/渲染(lv_draw)
第一章:配置(lv_conf.h)
歡迎開啟LVGL之旅~
在嵌入式系統圖形用戶界面(GUI),LVGL就像一套多功能工具箱,能夠從智能手表到工業面板的各種小屏幕上繪制精美的界面。
但與實體工具箱類似,并非所有項目都需要用到全部工具。假設我們正在開發一款配備基礎小屏幕
的簡易設備,僅需幾個按鈕和文本顯示。
此時我們希望設備盡可能高效運行,同時占用最少的內存和處理器資源。
這正是lv_conf.h
的用武之地!可將lv_conf.h
視為整個LVGL庫的"定制清單"或"設置菜單"。
通過這個特殊文件,我們可以精確指定
需要啟用的功能(如特定按鈕類型或高級繪圖效果)以及需要禁用的功能。
通過這種配置,最終程序將針對特定設備進行極致優化,節省寶貴內存并提升運行效率。
什么是lv_conf.h
?
lv_conf.h
是一個標準C頭文件(擴展名為.h
),包含大量LVGL配置參數。這些參數在C語言中通常稱為"宏
"或"定義",其作用類似于功能開關或數值設定器。
例如某個配置項可能如下:
#define LV_USE_BUTTON 1
這行代碼告知LVGL:"我們需要在項目中使用按鈕!"其中1
表示啟用,0
表示禁用。
配置文件的獲取與設置
初次獲取LVGL時并不會直接得到lv_conf.h
文件,而是會看到lvgl/lv_conf_template.h
文件。
這相當于包含所有可能選項的藍圖或默認清單。
要為項目配置LVGL,請按以下步驟操作:
-
復制模板文件:復制
lvgl/lv_conf_template.h
并重命名為lv_conf.h
- 重要提示:將
lv_conf.h
置于lvgl
文件夾同級目錄,形成如下項目結構:項目目錄/ ├── lvgl/ │ ├── src/ │ └── ... └── lv_conf.h └── main.c └── ...
- 重要提示:將
-
激活配置內容:打開新建的
lv_conf.h
文件,在文件頂部可見:#if 0 /* 將此值設為"1"以激活配置內容 */
將
0
改為1
以激活文件內所有設置項:#if 1 /* 將此值設為"1"以激活配置內容 */
至此,lv_conf.h
已準備就緒可供定制~
新手必備配置項
我們以構建簡易內存優化型GUI(含按鈕和文本)為目標,重點講解幾個關鍵配置項。
1. 屏幕色深(LV_COLOR_DEPTH
)
該參數決定每個像素顏色表示的位數。位數越多色彩越豐富
,但內存占用也越高。
16
:常見于嵌入式顯示設備(如RGB565格式),內存占用低于32位32
:適用于高質量顯示(如ARGB8888),內存需求較高
對于簡易設備,選擇16
位可有效節省內存:
// 位于lv_conf.h
/*====================顏色設置*====================*//** 色深選項:1 (I1), 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888) */
#define LV_COLOR_DEPTH 16 // 從默認的32或16修改為16以節省內存
2. LVGL內存分配(LV_MEM_SIZE
)
LVGL需要預分配內存來存儲內部變量、繪圖緩沖區和控件數據。
LV_MEM_SIZE
定義了為LVGL保留的內存容量。
模板文件中默認值通常為(64 * 1024U)
即64KB。對于小型設備,若功能簡單可縮減至32KB或更低:
// 位于lv_conf.h
#if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN/** 為lv_malloc()預留的可用內存大小(>= 2kB) */#define LV_MEM_SIZE (32 * 1024U) // 從64KB調整為32KB以節省內存
#endif
3. 控件啟用/禁用(LV_USE_WIDGET_NAME
)
LVGL提供多種預制組件(稱為"控件"),包括按鈕、滑塊、圖表、日歷等。
對于簡易設備,僅需啟用按鈕和基礎文本(標簽)控件即可顯著減小程序體積。
在lv_conf.h
中找到如下段落進行配置:
// 位于lv_conf.h
/*==================* 控件*================*/#define LV_USE_ANIMIMG 0 // 禁用
#define LV_USE_ARC 0 // 禁用#define LV_USE_BAR 0 // 禁用#define LV_USE_BUTTON 1 // 啟用!#define LV_USE_BUTTONMATRIX 0 // 禁用#define LV_USE_CALENDAR 0 // 禁用(模板中為1)
// ... 更多控件配置 ...#define LV_USE_LABEL 1 // 啟用!
將未使用的控件設為0
后,編譯器會完全忽略相關代碼,顯著減小最終程序體積。
4. 日志與調試(LV_USE_LOG
, LV_USE_PERF_MONITOR
, LV_USE_SYSMON
)
這些參數控制LVGL是否輸出調試日志或性能監控信息。
開發階段開啟有助于調試,但正式發布時應關閉以優化代碼體積和性能:
// 位于lv_conf.h
/*-------------* 日志系統*-----------*//** 啟用日志模塊 */
#define LV_USE_LOG 0 // 從1改為0以優化發布版本// ... 文件后續部分 ...
/** 1: 啟用系統監控組件 */
#define LV_USE_SYSMON 0 // 從1改為0以優化發布版本
#if LV_USE_SYSMON// ... 相關設置 .../** 1: 顯示CPU使用率和FPS計數 */#define LV_USE_PERF_MONITOR 0 // 從1改為0
#endif
?lv_conf.h
–條件編譯
當編譯LVGL項目(即將C代碼轉換為設備可執行程序)時,編譯器會讀取lv_conf.h
配置。
每個#define
指令相當于給編譯器的特殊指令。當某功能被啟用(如#define LV_USE_BUTTON 1
),編譯器會將LVGL庫中所有按鈕相關代碼包含進最終程序。
若功能被禁用(如#define LV_USE_CALENDAR 0
),編譯器則完全跳過日歷相關代碼,相當于這些代碼從未存在!
此過程稱為**條件編譯**,是精確適配硬件能力和項目需求的強大工具。
其工作原理可簡化為:
在LVGL源代碼中,可見包圍代碼塊的#if
和#endif
指令。例如按鈕功能的實現代碼:
// 在LVGL源文件中(如lv_button.c)
#include "lv_conf.h" // 包含定制化配置#if LV_USE_BUTTON // 僅當LV_USE_BUTTON為1時編譯本段// ...// 按鈕功能相關代碼// ...void lv_button_create(lv_obj_t *parent) {// 創建按鈕的代碼}// ...
#endif // LV_USE_BUTTON結束
同理,被禁用功能的代碼段:
// 在LVGL源文件中(如lv_calendar.c)
#include "lv_conf.h"#if LV_USE_CALENDAR // 當LV_USE_CALENDAR為0時跳過本段// ...// 日歷控件相關代碼// ...void lv_calendar_create(lv_obj_t *parent) {// 創建日歷的代碼}// ...
#endif
這種精妙的機制使LVGL具備極強的適應性,既能運行于資源有限的微型控制器,也能駕馭功能齊全的智能設備。
總結
我們已完成LVGL定制的第一步!理解lv_conf.h
至關重要,因為它直接影響項目的體積、性能和可用功能。
通過精心選擇組件
和調整內存參數
,可以確保LVGL完美適配目標嵌入式系統——無論是簡易顯示器還是功能豐富的智能設備。
現在我們已經掌握如何配置LVGL本身,接下來讓我們進入實際顯示環節
!
下一章:顯示屏(lv_display)
第二章:顯示屏(lv_display)
歡迎回來!
在第一章:配置(lv_conf.h)中,我們學習了如何為特定設備裁剪優化LVGL。可將lv_conf.h
視為為工具箱選擇合適工具
的過程。但若沒有可供繪制的畫布,再好的工具箱又有何用?
**顯示模塊(lv_display
)**正是為此而生!
設想我們已將物理屏幕連接到微控制器,LVGL需要全面了解該屏幕的信息:尺寸(分辨率)、色彩模式,以及最關鍵的部分——如何將LVGL內存中的精美畫面傳輸至物理屏幕實現可視化。
lv_display
對象如同物理屏幕的數字化身,負責處理LVGL繪圖引擎與顯示硬件之間的所有通信。若無此模塊,LVGL將無從知曉繪制位置及可視化方法
什么是lv_display
?
lv_display
(代碼中以lv_display_t
表示)是LVGL與物理屏幕交互的核心模塊,主要管理:
- 分辨率:屏幕像素尺寸(如320x240像素)
- 色深:每個色彩使用的位數(如16位RGB565)
- 繪圖緩沖區:微控制器內存中的專用區域,作為LVGL繪制圖形的臨時畫布
- 刷新回調函數:開發者編寫的關鍵函數,用于將緩沖區像素數據傳送至物理顯示硬件
LVGL支持多屏顯示,但本章聚焦單屏基礎配置。
顯示屏初始設置
我們以320x240分辨率、16位色的常見屏幕為例,詳解配置流程:
1. 創建顯示對象
首先需向LVGL聲明顯示設備的存在:
#include "lvgl.h" // 必須包含LVGL主頭文件// 定義顯示屏分辨率
#define MY_DISP_HOR_RES 320
#define MY_DISP_VER_RES 240void setup_display() {// 1. 創建顯示對象lv_display_t * my_display = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);// ... 后續配置將在此添加
}
lv_display_create()
函數向LVGL聲明了顯示設備的分辨率,返回的my_display
指針用于后續配置
2.配置繪圖緩沖區
LVGL采用"預渲染-傳輸"機制,需在微控制器RAM中開辟繪圖緩沖區:
- 單緩沖區:LVGL完成繪制后等待傳輸,可能導致低刷新率下的畫面撕裂
- 雙緩沖區:支持交替渲染與傳輸,建議RAM充足時采用
以下示例配置占屏幕1/10大小的單緩沖區:
#define LV_COLOR_DEPTH 16 // 需與lv_conf.h設置一致
#define MY_DISP_HOR_RES 320
#define MY_DISP_VER_RES 240// 根據色深計算每像素字節數
#define BYTES_PER_PIXEL (LV_COLOR_DEPTH / 8)// 靜態內存中聲明緩沖區(持久化)
static lv_color_t draw_buffer[MY_DISP_HOR_RES * MY_DISP_VER_RES / 10];void setup_display() {lv_display_t * my_display = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);// 2. 綁定繪圖緩沖區lv_display_set_buffers(my_display, draw_buffer, NULL, sizeof(draw_buffer), LV_DISPLAY_RENDER_MODE_PARTIAL);
}
LV_DISPLAY_RENDER_MODE_PARTIAL
啟用局部渲染模式,僅更新變化區域以優化性能
3. 實現刷新回調函數
此為核心環節,需開發者根據顯示硬件編寫像素傳輸邏輯:
// 實際屏幕寫入函數(需根據硬件實現)
void my_put_pixel_on_actual_screen(int32_t x, int32_t y, lv_color_t color) {// 示例:SPI屏可能需要通過協議發送坐標數據// 具體實現取決于顯示控制器與通信接口
}// 3. 自定義刷新回調函數
void my_display_flush_callback(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map) {lv_color_t * buf = (lv_color_t *)px_map; // 像素數據轉換// 遍歷待刷新區域for (int32_t y = area->y1; y <= area->y2; y++) {for (int32_t x = area->x1; x <= area->x2; x++) {my_put_pixel_on_actual_screen(x, y, *buf);buf++; // 移動至下一像素}}// 關鍵!通知LVGL刷新完成lv_display_flush_ready(disp);
}
area
參數指定需更新的屏幕矩形區域- 完成像素傳輸后必須調用
lv_display_flush_ready()
釋放緩沖區
4. 注冊回調函數
將自定義回調綁定至顯示對象:
void setup_display()
{lv_display_t * my_display = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);lv_display_set_buffers(my_display, draw_buffer, NULL, sizeof(draw_buffer), LV_DISPLAY_RENDER_MODE_PARTIAL);// 4. 注冊刷新回調lv_display_set_flush_cb(my_display, my_display_flush_callback);
}
至此,LVGL已完成顯示系統的初始化,可進行圖形渲染。
默認顯示對象
首個通過lv_display_create()
創建的顯示對象會自動成為默認顯示設備。
多數LVGL控件創建函數將自動關聯此默認顯示。
多屏系統可通過lv_display_set_default()
切換當前默認顯示。
顯示模塊工作原理
顯示模塊的運作流程可通過以下時序圖理解:
內部實現解析:
lv_display_create()
會在內存中分配lv_display_t
結構體,包含分辨率、緩沖區指針及回調函數等關鍵信息。刷新定時器(
refr_timer
)會周期性地觸發畫面更新。
總結
本章完成了LVGL顯示系統的配置,重點包括:
顯示對象
的創建與屬性設置繪圖緩沖區
的內存管理硬件相關的刷新
回調實現- LVGL
渲染管線
的運作原理
至此,我們已搭建起GUI系統的顯示基礎,下一章將深入探討如何構建交互界面元素。
下一章:控件(lv_obj)