境配置到交互調(diào)試)
簡(jiǎn)介面向嵌入式圖形界面開(kāi)發(fā)者與 LVGL 學(xué)習(xí)者的 9.2.2 模擬器完整工程解決在 Windows 環(huán)境下使用 Visual Studio 2022 快速搭建模擬運(yùn)行環(huán)境、驗(yàn)證界面邏輯與控件交互的實(shí)際需求。工程集成了模擬器核心源碼、VS2022 項(xiàng)目配置以及大量示例界面資源如音樂(lè)播放器演示中的封面與頻譜素材配套的 Python 輔助腳本和 TXT/Markdown 文檔可幫助使用者理解構(gòu)建流程、快速排查路徑與依賴(lài)配置問(wèn)題。資源共 2000 個(gè)文件以 C 源碼和 H 頭文件為主涵蓋 LVGL 核心組件與基礎(chǔ)控件實(shí)現(xiàn)同時(shí)包含 CPP 工程文件、JSON 配置文件及少量腳本與文檔壓縮包約 153.63MB目錄結(jié)構(gòu)按模塊劃分便于檢索。目前已有 517 人瀏覽/學(xué)習(xí)面向需要直接在 PC 端評(píng)估 LVGL 9.2.2 特性、進(jìn)行界面原型驗(yàn)證或二次開(kāi)發(fā)的工程師能省去從零搭建環(huán)境的精力獲得可直接編譯運(yùn)行的模擬器方案與排錯(cuò)參考。 搞嵌入式GUI開(kāi)發(fā)的應(yīng)該沒(méi)人不知道LVGL。但很多人拿到LVGL源碼后的第一反應(yīng)是移植到板子上結(jié)果開(kāi)發(fā)板還沒(méi)到手、編譯鏈沒(méi)配好一天就折騰完了。其實(shí)在PC上跑模擬器是最快的驗(yàn)證方式不用碰硬件就能把界面邏輯全部調(diào)通等UI成型后再往目標(biāo)板遷效率完全不一樣。這篇我以L(fǎng)VGL 9.2.2為例帶你把官方模擬器完整地跑在VS2022上整個(gè)過(guò)程覆蓋環(huán)境搭建、源碼配置、CMake構(gòu)建和常見(jiàn)坑跟著操作一遍就能跑起來(lái)。1. 為什么要用VS2022跑LVGL 9.2.2模擬器1.1 模擬器能解決什么問(wèn)題很多初學(xué)者把LVGL模擬器理解成“一個(gè)可以預(yù)覽界面的小工具”實(shí)際它的價(jià)值遠(yuǎn)不止預(yù)覽。LVGL模擬器是在PC上完整運(yùn)行LVGL引擎包括顯示驅(qū)動(dòng)、輸入設(shè)備、定時(shí)器、動(dòng)畫(huà)、布局、事件系統(tǒng)全部按真實(shí)環(huán)境執(zhí)行。你寫(xiě)的每一行界面代碼在模擬器上跑的效果和板子上幾乎一致區(qū)別只是渲染后端不同。這意味著你做菜單、彈窗、列表、圖表、動(dòng)畫(huà)這些交互邏輯完全可以在電腦上迭代調(diào)試不用一遍遍燒錄固件。我有段時(shí)間做STM32項(xiàng)目一天編譯下載幾十次后來(lái)改成先在模擬器上把UI和交互全部調(diào)好再移植過(guò)去只需要處理驅(qū)動(dòng)和資源適配開(kāi)發(fā)周期至少縮短一半。1.2 為什么選9.2.2版本LVGL在8.x到9.x之間做了一次比較大的重構(gòu)9.x版本的API和8.x有本質(zhì)差異比如顯示驅(qū)動(dòng)和輸入設(shè)備的注冊(cè)方式變了很多8.x的示例代碼不能直接拿到9.x編譯。如果網(wǎng)上搜索到的教程多半還是8.x的寫(xiě)法你拿9.2.2去編譯就會(huì)看到一堆報(bào)錯(cuò)。9.2.2是當(dāng)前9.x系列里比較穩(wěn)定的一個(gè)release版本修復(fù)了大量驅(qū)動(dòng)和高DPI適配問(wèn)題SDL2桌面驅(qū)動(dòng)已經(jīng)原生集成在源碼里不需要像8.x那樣額外拉一個(gè)lv_drivers倉(cāng)庫(kù)。對(duì)于新項(xiàng)目直接上車(chē)9.2.2是對(duì)的不用擔(dān)心學(xué)了一個(gè)即將淘汰的舊版本。1.3 技術(shù)方案選擇在Windows下跑LVGL模擬器常見(jiàn)方案有這么幾種官方VS工程模板.sln直接打開(kāi)純CMake命令行構(gòu)建CMake vcpkg管理依賴(lài)MinGW SDL2我自己實(shí)測(cè)下來(lái)最省心的是CMake配合vcpkg安裝SDL2再讓CMake生成VS2022的.sln工程。這樣既能享受VS的智能提示和調(diào)試器又不依賴(lài)某個(gè)倉(cāng)庫(kù)里可能過(guò)時(shí)的VS工程文件整個(gè)構(gòu)建過(guò)程完全可控。2. 環(huán)境準(zhǔn)備VS2022與基礎(chǔ)工具安裝2.1 VS2022社區(qū)版安裝要點(diǎn)VS2022社區(qū)版對(duì)個(gè)人開(kāi)發(fā)者完全免費(fèi)直接去Visual Studio官網(wǎng)下載安裝器就行。需要注意的只有一個(gè)點(diǎn)安裝時(shí)“工作負(fù)載”必須勾選“使用C的桌面開(kāi)發(fā)”這一項(xiàng)包含MSVC編譯器、Windows SDK和C CMake工具。很多人在這一步踩坑裝完VS后創(chuàng)建不了C項(xiàng)目或者CMake找不到編譯器基本都是因?yàn)橹谎b了默認(rèn)的.NET負(fù)載。建議順手把右側(cè)“單個(gè)組件”里的“C CMake tools for Windows”也勾上后面構(gòu)建省事很多。安裝完后打開(kāi)VS2022在“工具-獲取工具和功能”里可以確認(rèn)組件是否齊全??梢杂孟旅娴暮?jiǎn)單代碼驗(yàn)證編譯器#include iostream int main() { std::cout LVGL Simulator Ready std::endl; return 0; }新建一個(gè)控制臺(tái)應(yīng)用跑一下能輸出就說(shuō)明環(huán)境沒(méi)問(wèn)題。2.2 CMake和Git的準(zhǔn)備VS2022自帶的CMake版本一般夠用但我還是建議裝一個(gè)最新的CMake獨(dú)立版本因?yàn)長(zhǎng)VGL官方文檔和一些第三方demo有時(shí)會(huì)用到較新的CMake命令。到cmake.org下載Windows x64安裝包安裝時(shí)勾選“Add CMake to system PATH”這樣命令行里就能直接敲cmake。Git同樣建議裝。雖然可以直接在GitHub頁(yè)面下載zip但用git clone能精確鎖定tag版本后續(xù)想切分支或者更新也比較方便。裝好Git后在任意目錄右鍵看到“Git Bash Here”就說(shuō)明成功了。檢查工具是否就位cmake --version git --version cl能輸出版本號(hào)就說(shuō)明環(huán)境沒(méi)問(wèn)題。如果cl命令提示找不到打開(kāi)“x64 Native Tools Command Prompt for VS 2022”再試。3. 獲取LVGL 9.2.2源碼并完成配置3.1 源碼下載與目錄結(jié)構(gòu)LVGL源碼托管在GitHub上倉(cāng)庫(kù)名就是lvgl。我們直接拉指定taggit clone --branch v9.2.2 --depth 1 https://github.com/lvgl/lvgl.git如果已經(jīng)克隆過(guò)完整倉(cāng)庫(kù)也可以用git checkout v9.2.2拉下來(lái)的目錄結(jié)構(gòu)大致如下lvgl/ ├── src/ │ ├── core/ # 核心對(duì)象、事件、刷新 │ ├── draw/ # 渲染引擎 │ ├── drivers/ # 各類(lèi)驅(qū)動(dòng)含sdl、windows等 │ ├── fonts/ # 內(nèi)置字體 │ ├── layouts/ # Flex和Grid布局 │ ├── libs/ # 額外庫(kù)如png、jpeg、fs │ ├── misc/ # 內(nèi)存、日志、系統(tǒng)接口 │ ├── themes/ # 默認(rèn)主題 │ └── widgets/ # 常用控件 ├── demos/ ├── examples/ ├── lvgl.h ├── lv_conf_template.h └── CMakeLists.txt9.x把驅(qū)動(dòng)全部收進(jìn)了src/driversSDL驅(qū)動(dòng)就在src/drivers/sdl目錄下這對(duì)模擬器項(xiàng)目來(lái)說(shuō)非常友好不需要額外引用外部驅(qū)動(dòng)庫(kù)。3.2 創(chuàng)建并修改lv_conf.hLVGL使用宏定義來(lái)控制編譯配置配置文件叫l(wèi)v_conf.h。源碼目錄里默認(rèn)只有模板文件lv_conf_template.h第一次使用需要復(fù)制一份并命名為lv_conf.hcp lvgl/lv_conf_template.h lvgl/lv_conf.h推薦把lv_conf.h放在工程源碼目錄下比如項(xiàng)目根目錄的config文件夾然后在CMake里通過(guò)include目錄指過(guò)去。但最省事的方式是直接放在lvgl目錄里這樣LVGL源碼會(huì)自動(dòng)找到它。我習(xí)慣放lvgl目錄下簡(jiǎn)單直接。打開(kāi)lv_conf.h重點(diǎn)檢查這幾個(gè)宏#define LV_COLOR_DEPTH 32 // 模擬器建議32位色 #define LV_USE_SDL 1 // 啟用SDL驅(qū)動(dòng) #define LV_USE_DEMO_WIDGETS 1 // 啟用官方demo #define LV_FONT_SIMSUN_16_CJK 1 // 需要顯示中文時(shí)打開(kāi) #define LV_USE_LOG 1 // 建議打開(kāi)日志調(diào)試時(shí)有用LV_COLOR_DEPTH在PC模擬器上直接設(shè)32板子如果屏是16位的再改回去。SDL驅(qū)動(dòng)宏不打開(kāi)模擬器的窗口和鼠標(biāo)鍵盤(pán)驅(qū)動(dòng)都不會(huì)被編譯進(jìn)來(lái)這一步容易漏。9.2.2的配置項(xiàng)比8.x精簡(jiǎn)了不少比較復(fù)雜的模塊比如各種第三方解碼庫(kù)默認(rèn)就是關(guān)閉狀態(tài)不用動(dòng)。3.3 SDL2依賴(lài)的安裝方式在Windows上LVGL的SDL驅(qū)動(dòng)依賴(lài)SDL2庫(kù)。強(qiáng)烈推薦用vcpkg安裝比手動(dòng)下載SDL2開(kāi)發(fā)包配置環(huán)境變量簡(jiǎn)單太多。git clone https://github.com/microsoft/vcpkg.git cd vcpkg .\bootstrap-vcpkg.bat .\vcpkg install sdl2:x64-windows安裝完成后記住vcpkg目錄的位置后面CMake配置時(shí)要通過(guò)toolchain文件指定。vcpkg會(huì)自動(dòng)編譯SDL2并生成CMake可識(shí)別的配置文件這是我認(rèn)為最不容易出錯(cuò)的路徑。如果你不想用vcpkg也可以去SDL官網(wǎng)下載SDL2-devel-2.30.x-VC.zip解壓后手動(dòng)在CMake里設(shè)置SDL2_DIR變量。但需要確認(rèn)下載的包是否帶CMake config文件有些版本只有.lib和.dll沒(méi)有CMake配置find_package會(huì)失敗。vcpkg方案能避開(kāi)這些不確定性。4. 創(chuàng)建模擬器工程并編譯運(yùn)行4.1 CMake工程結(jié)構(gòu)我習(xí)慣把所有文件放在一個(gè)干凈的simulator目錄下目錄結(jié)構(gòu)如下lvgl_simulator/ ├── CMakeLists.txt ├── main.c └── lvgl/ └── ...上面拉下來(lái)的源碼CMakeLists.txt是工程的核心先看完整內(nèi)容cmake_minimum_required(VERSION 3.16) project(lvgl_simulator C) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) add_subdirectory(lvgl) add_executable(lvgl_simulator main.c) target_include_directories(lvgl_simulator PRIVATE lvgl) target_link_libraries(lvgl_simulator PRIVATE lvgl::lvgl) find_package(SDL2 REQUIRED) target_link_libraries(lvgl_simulator PRIVATE SDL2::SDL2)這里有個(gè)細(xì)節(jié)要注意add_subdirectory(lvgl)會(huì)把LVGL源碼編譯成靜態(tài)庫(kù)目標(biāo)目標(biāo)名一般是lvgl::lvgl。如果CMake配置時(shí)報(bào)找不到這個(gè)目標(biāo)去lvgl/CMakeLists.txt里搜一下實(shí)際的target名字把鏈接行改成對(duì)應(yīng)名稱(chēng)即可。find_package(SDL2 REQUIRED)需要在add_subdirectory(lvgl)之前或之后都行但為了讓LVGL編譯SDL驅(qū)動(dòng)時(shí)能識(shí)別SDL2頭文件建議把find_package放到add_subdirectory之前。我自己測(cè)試時(shí)放前面更能保證LVGL里的SDL源碼能拿到SDl2頭文件搜索路徑。4.2 main.c核心代碼main.c是整個(gè)模擬器的入口代碼如下#include lvgl.h #include lvgl/src/drivers/sdl/lv_sdl_window.h #include lvgl/src/drivers/sdl/lv_sdl_mouse.h #include lvgl/src/drivers/sdl/lv_sdl_keyboard.h int main(void) { lv_init(); /* 創(chuàng)建SDL窗口指定分辨率 */ lv_display_t * display lv_sdl_window_create(800, 480); /* 注冊(cè)鼠標(biāo)輸入 */ lv_indev_t * mouse lv_sdl_mouse_create(); lv_indev_set_display(mouse, display); /* 注冊(cè)鍵盤(pán)輸入 */ lv_indev_t * keyboard lv_sdl_keyboard_create(); lv_indev_set_display(keyboard, display); /* 加載官方控件demo */ lv_demo_widgets(); while (1) { lv_timer_handler(); lv_delay_ms(5); } return 0; }這個(gè)代碼的流程很清晰先lv_init初始化LVGL然后創(chuàng)建SDL窗口得到display對(duì)象再創(chuàng)建鼠標(biāo)和鍵盤(pán)輸入設(shè)備最后在死循環(huán)里不斷調(diào)用lv_timer_handler處理界面刷新和事件響應(yīng)。lv_demo_widgets默認(rèn)會(huì)展示按鈕、滑塊、儀表盤(pán)、圖表、日歷等常用控件。如果你只想跑一個(gè)空白界面把這行注釋掉即可。需要注意的是9.x的API和8.x差別很大。8.x里有l(wèi)v_disp_drv_register和lv_indev_drv_register9.x換成了lv_display_create和lv_indev_createSDL驅(qū)動(dòng)也直接返回lv_display_t指針。如果你在網(wǎng)上看到的是lv_disp_drv_t初始化那套老代碼直接套用到9.2.2必然編譯失敗。4.3 使用vcpkg配置并編譯CMake配置命令如下需要指定vcpkg的toolchain文件cmake -B build -G Visual Studio 17 2022 -A x64 -DCMAKE_TOOLCHAIN_FILED:/vcpkg/scripts/buildsystems/vcpkg.cmake執(zhí)行完會(huì)在build目錄下生成lvgl_simulator.sln。之后有兩種方式編譯運(yùn)行方式一命令行直接構(gòu)建cmake --build build --config Release方式二用VS打開(kāi)build目錄下的解決方案start build/lvgl_simulator.sln然后在VS里把啟動(dòng)項(xiàng)目設(shè)為lvgl_simulator配置改成Release x64按F5直接運(yùn)行。我實(shí)際更推薦用VS運(yùn)行因?yàn)榭梢源驍帱c(diǎn)調(diào)試UI流程。如果生成解決方案時(shí)VS提示找不到SDK或MSVC版本不匹配把VS2022更新到最新版即可或者換用“Visual Studio 17 2022”老一點(diǎn)的generator名稱(chēng)。運(yùn)行成功后你會(huì)看到一個(gè)800x480的窗口里面顯示LVGL官方demo界面鼠標(biāo)可以點(diǎn)擊控件鍵盤(pán)能觸發(fā)焦點(diǎn)事件。4.4 CMake生成解決方案的常見(jiàn)參數(shù)這里補(bǔ)充一下-G參數(shù)的用法。如果你電腦上同時(shí)裝有VS2019和VS2022需要明確指定generator名稱(chēng)。VS2022對(duì)應(yīng)“Visual Studio 17 2022”VS2019對(duì)應(yīng)“Visual Studio 16 2019”。另外如果源碼和生成目錄在不同磁盤(pán)有些復(fù)雜項(xiàng)目的相對(duì)路徑會(huì)出問(wèn)題。建議build目錄就放在工程目錄下形成lvgl_simulator/build的結(jié)構(gòu)我這個(gè)工程就是這么安排的。5. 常見(jiàn)問(wèn)題與排查實(shí)錄5.1 SDL2庫(kù)找不到這是最常遇到的問(wèn)題。CMake報(bào)錯(cuò)信息大概長(zhǎng)這樣Could not find a package configuration file provided by SDL2 with any of the following names: SDL2Config.cmake sdl2-config.cmake原因基本是vcpkg的toolchain路徑?jīng)]寫(xiě)對(duì)或者SDL2還沒(méi)安裝。重點(diǎn)檢查確認(rèn)vcpkg路徑正確windows路徑分隔符正斜杠反斜杠都行確認(rèn)sdl2已經(jīng)裝到x64-windows可以用vcpkg list查看確認(rèn)CMakeLists里的find_package(SDL2 REQUIRED)和toolchain文件在同一套環(huán)境中還有個(gè)容易忽略的點(diǎn)如果改了vcpkg路徑一定要?jiǎng)h除build目錄重新配置CMake會(huì)緩存舊的SDL2路徑不清理緩存改多少遍都報(bào)同樣的錯(cuò)。5.2 編譯報(bào)錯(cuò)API不匹配這個(gè)問(wèn)題的根源大多是代碼用了8.x的API。常見(jiàn)報(bào)錯(cuò)有l(wèi)v_disp_drv_register未聲明lv_disp_buf_t類(lèi)型不存在lv_indev_drv_t結(jié)構(gòu)體成員不存在9.x不再使用lv_disp_drv_t手動(dòng)初始化顯示驅(qū)動(dòng)改成直接調(diào)用lv_sdl_window_create獲取display對(duì)象。輸入設(shè)備也一樣不再需要手動(dòng)填充lv_indev_drv_t結(jié)構(gòu)體。所以寫(xiě)代碼前先確認(rèn)你參考的教程或demo對(duì)應(yīng)的LVGL版本8.x的示例不能直接用于9.2.2。5.3 窗口黑屏窗口能彈出來(lái)但全黑排查順序是否調(diào)用了lv_timer_handler沒(méi)有這個(gè)循環(huán)界面永遠(yuǎn)不會(huì)刷新是否重復(fù)調(diào)用了lv_init或者聲明了兩個(gè)displayDLL是否齊全SDL2.dll要放在生成的exe同目錄下vcpkg安裝的sdl2是靜態(tài)鏈接的一般不會(huì)缺DLL。如果你是手動(dòng)下載SDL2開(kāi)發(fā)包則需要把SDL2.dll復(fù)制到exe目錄否則窗口會(huì)提示找不到入口點(diǎn)或者直接黑屏。5.4 中文顯示亂碼LVGL默認(rèn)字體不包含中文字符。顯示中文只有兩條路在lv_conf.h中啟用CJK字體比如LV_FONT_SIMSUN_16_CJK使用字體轉(zhuǎn)換工具將ttf轉(zhuǎn)成LVGL格式然后加載自定義字體CJK字體文件較大正式產(chǎn)品里通常用后一種方式控制資源體積。模擬器調(diào)試階段直接用內(nèi)置CJK字體最省事記得到lv_conf.h里把對(duì)應(yīng)宏打開(kāi)。還要注意源碼文件本身編碼必須是UTF-8如果是GBK編碼VS編譯時(shí)會(huì)警告顯示出來(lái)就是亂碼。5.5 Debug模式性能差LVGL模擬器在Debug模式下跑官方demo會(huì)明顯卡頓因?yàn)長(zhǎng)VGL大量使用了內(nèi)聯(lián)和內(nèi)存操作Debug版本的優(yōu)化程度很低。解決辦法很簡(jiǎn)單構(gòu)建Release版本。我自己調(diào)試邏輯的時(shí)候用Debug驗(yàn)證性能的時(shí)候切Release兩邊切換成本很低。如果Release下還是卡檢查L(zhǎng)V_DISP_ROT、LV_DPI_DEF等宏是否設(shè)得離譜分辨率越大渲染開(kāi)銷(xiāo)越高。5.6 常見(jiàn)問(wèn)題速查表癥狀可能原因解決方案CMake找不到SDL2vcpkg路徑錯(cuò)誤檢查toolchain路徑刪除build緩存重跑編譯報(bào)API錯(cuò)誤使用了8.x舊API改用9.x的lv_display_create系列API窗口黑屏未調(diào)用lv_timer_handler死循環(huán)中加上定時(shí)刷新調(diào)用中文亂碼未啟用CJK字體lv_conf.h打開(kāi)LV_FONT_SIMSUN_16_CJK鼠標(biāo)點(diǎn)擊無(wú)反應(yīng)未注冊(cè)輸入設(shè)備創(chuàng)建lv_sdl_mouse并掛到display界面卡頓Debug模式切換Release構(gòu)建編譯報(bào)C4996MSVC安全函數(shù)警告添加_CRT_SECURE_NO_WARNINGS宏6. 環(huán)境隔離與后續(xù)擴(kuò)展6.1 多版本LVGL共存管理很多人的電腦上不止一套LVGL8.3的工程和9.2.2的工程可能同時(shí)存在。建議每個(gè)工程目錄里獨(dú)立放置lvgl源碼不要共用一份源碼。LVGL的太多項(xiàng)目會(huì)互相污染特別是lv_conf.h這類(lèi)配置文件的改動(dòng)一旦共用很容易影響其他工程。我用Git管理項(xiàng)目時(shí)把lvgl作為submodule引入這樣每個(gè)工程鎖定自己的版本需要升級(jí)時(shí)單獨(dú)切換到目標(biāo)tag控制起來(lái)很清楚。6.2 從模擬器遷移到真實(shí)板卡模擬器調(diào)通之后遷移到真實(shí)硬件要注意以下差異顯示驅(qū)動(dòng)從SDL驅(qū)動(dòng)換成項(xiàng)目使用的TFTLCD或者RGB屏驅(qū)動(dòng)輸入設(shè)備從鼠標(biāo)換成觸摸屏或編碼器內(nèi)存配置PC上內(nèi)存充裕板子上要規(guī)劃好LV_MEM_SIZE字體資源模擬器用PC字體文件板子上要處理字庫(kù)存儲(chǔ)界面的核心邏輯包括布局、事件、動(dòng)畫(huà)遷移時(shí)基本不需要改這就是模擬器最大的價(jià)值。我自己做產(chǎn)品原型時(shí)通常先在模擬器里畫(huà)好界面和交互邏輯然后進(jìn)入硬件聯(lián)調(diào)階段這樣能把“寫(xiě)UI”和“調(diào)驅(qū)動(dòng)”兩個(gè)任務(wù)解耦每一步都足夠聚焦。最后再分享一個(gè)個(gè)人實(shí)操經(jīng)驗(yàn)如果你發(fā)現(xiàn)SDL窗口創(chuàng)建的界面顯示比例不對(duì)先把LV_DPI_DEF設(shè)成模擬器的DPI值比如Windows縮放125%時(shí)設(shè)成120窗口里的控件大小就會(huì)更接近真實(shí)設(shè)備效果。這個(gè)值直接影響控件默認(rèn)尺寸不在硬件上對(duì)比很難發(fā)現(xiàn)差異很多人到移植后才意識(shí)到最后又得回頭調(diào)布局。本文還有配套的精品資源點(diǎn)擊獲取