[LVGL] 配置lv_conf.h | 條件編譯 | 顯示屏lv_display

鏈接:https://docs.lvgl.io/master/
在這里插入圖片描述

docs:LVGL

LVGL(Light and Versatile Graphics Library)是用于在資源受限的嵌入式系統上創建圖形用戶界面(GUI)的開源解決方案。

它提供豐富的控件和靈活的**事件系統**來實現動態交互。

該庫能高效處理繪制/渲染到各類顯示屏的操作,并支持來自多種**輸入設備**的輸入,所有功能都可通過中心化的配置進行定制。

概覽

在這里插入圖片描述

章節

  1. 配置(lv_conf.h)
  2. 顯示屏(lv_display)
  3. 控件(lv_obj)
  4. 樣式(lv_style)
  5. 布局(lv_flex, lv_grid)
  6. 輸入設備(lv_indev)
  7. 事件系統(lv_event)
  8. 繪制/渲染(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,請按以下步驟操作:

  1. 復制模板文件:復制lvgl/lv_conf_template.h并重命名為lv_conf.h

    • 重要提示:將lv_conf.h置于lvgl文件夾同級目錄,形成如下項目結構:
      項目目錄/
      ├── lvgl/
      │   ├── src/
      │   └── ...
      └── lv_conf.h
      └── main.c
      └── ...
      
  2. 激活配置內容:打開新建的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)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/92218.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/92218.shtml
英文地址,請注明出處:http://en.pswp.cn/web/92218.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

sqli-labs通關筆記-第32關 GET寬字符注入(單引號閉合 手工注入+腳本注入兩種方法)

目錄 一、寬字符注入 二、代碼審計 1、代碼審計 2、SQL注入安全性分析 三、滲透實戰 1、進入靶場 2、id1探測 3、id%df-- 探測 4、手工注入 &#xff08;1&#xff09;獲取列數 &#xff08;2&#xff09;獲取回顯位 &#xff08;3&#xff09;獲取數據庫名 &…

MySQL的創建管理表:

目錄 基礎知識&#xff1a; 一條數據存儲的過程&#xff1a; 標識符命名規則&#xff1a; 創建和管理數據庫&#xff1a; 創建數據庫&#xff1a; 創建數據庫&#xff1a; 創建數據庫并指定字符集&#xff1a; 判斷數據庫是否存在&#xff0c;不存在則創建數據庫&#…

Linux Vi常用指令總結

Vi&#xff08;及其改進版 Vim&#xff09;是 Linux 中常用的文本編輯器&#xff0c;雖然入門有一定門檻&#xff0c;但熟練掌握后效率極高。以下是常見指令分類整理&#xff1a;1. 模式切換 普通模式&#xff08;命令模式&#xff09;&#xff1a;啟動后的默認模式&#xff0c…

解決遠程連接云服務器mysql編號1130問題

連接云服務器mysql失敗&#xff0c;可能是因為ip發生改變&#xff0c;被mysql攔截。我自己前后做了兩件事。大家趕時間可直接從二開始&#xff0c;不放心的就從一開始到結束一、在云服務器實例中為當前ip配置安全組權限。1.找到當前服務器的實例&#xff0c;進入安全組。為其增…

大數據存儲域——HDFS存儲系統

摘要本文介紹了HDFS存儲系統&#xff0c;包括其組件、工作機制、實戰經驗總結、使用場景以及與SpringBoot的實戰示例和優化設計。HDFS由Client、NameNode、SecondaryNameNode、DataNode等組件構成&#xff0c;通過特定的工作機制實現文件的讀取和寫入。它適用于多種場景&#x…

jdk動態代理如何實現

口語化答案好的&#xff0c;面試官。jdk 的動態代理主要是依賴Proxy類 和InvocationHandler 接口。jdk 動態代理要求類必須有接口。在進行實現的時候&#xff0c;首先要定義接口&#xff0c;比如MyService&#xff0c;這個接口就是我們的正常功能的實現。但是希望在不更改MySer…

自然語言處理的相關概念與問題

目錄 一、學科的產生與發展 1、什么是自然語言&#xff1f; 2、自然語言處理技術的誕生 二、技術挑戰 三、基本方法 1、方法概述 理性主義方法 經驗主義方法 2、傳統的統計學習方法 3、深度學習方法 詞向量表示 詞向量學習 開源工具 四、應用舉例 1、漢語分詞 …

Anthropic MCP架構深度解析:下一代AI工具集成協議的設計哲學

本文深入剖析Anthropic提出的模型通信協議(MCP),揭示其如何重構AI與工具生態的交互范式,打造安全高效的智能體基礎設施。 引言:AI工具集成的"巴別塔困境" 當前AI生態面臨的核心挑戰: #mermaid-svg-lSpYBxzxD5oiYwcL {font-family:"trebuchet ms",verd…

【注意】HCIE-Datacom華為數通考試,第四季度將變題!

最近&#xff0c;數據通信圈子可熱鬧壞啦&#xff01;好幾個渠道都證實了&#xff0c;HCIE - Datacom實驗考試馬上要有大變化咯&#xff01; 這可不是啥小道消息&#xff0c;也不是那種試點的傳言&#xff0c;而是從IE內部技術交流會上得到的確切消息。 這邊聯系了華為認證的好…

MySql 硬核解析系列 一 MySQL的鎖機制

MySQL 的鎖機制是其并發控制的核心,直接影響數據庫的性能、一致性與可用性。本文將從底層原理、鎖的分類、實現機制、鎖的粒度、鎖的兼容性、死鎖處理、InnoDB 的行鎖實現、MVCC 與鎖的關系等多個維度,進行硬核、深度解析,適用于希望深入理解 MySQL 并發控制機制的開發者與 …

7.軟件工程

軟件生命周期軟件生命周期什么是軟件工程&#xff1f;以工程化的原則和方法來開發軟件&#xff0c;其目的是提高軟件生產率、提高軟件質量、降低軟件成本。軟件工程3大組成部分&#xff1a;方法、工具、過程。什么是軟件生命周期&#xff1a;經過開發、使用和維護&#xff0c;直…

C 語言結構體與 Java 類的異同點深度解析

在編程語言的發展歷程中,C 語言的結構體與 Java 的類扮演著至關重要的角色。作為面向過程編程的經典代表,C 語言的結構體為數據封裝提供了基礎形式;而 Java 作為純面向對象語言,類則是其核心語法結構。二者既存在一脈相承的設計思想,又因編程語言范式的差異呈現出顯著區別…

C++、STL面試題總結(二)

1. 必須實現拷貝構造函數的場景 核心問題&#xff1a;默認拷貝構造的缺陷 C 默認的拷貝構造函數&#xff08;淺拷貝&#xff09;&#xff0c;會直接拷貝指針 / 引用成員的地址。若類包含引用成員或指向堆內存的指針&#xff0c;淺拷貝會導致 “多個對象共享同一份資源”&…

IntelliJ IDEA2024 錯誤‘http://start.spring.io/‘的初始化失敗,請檢查URL、網絡和代理設置。

下載新版本的intellij idea2024創建項目時&#xff0c;服務器URL報錯誤http://start.spring.io/的初始化失敗&#xff0c;請檢查URL、網絡和代理設置。錯誤消息&#xff1a;Cannot download http://start.spring.io/:Permission denied:getsockopt&#xff0c;具體如下圖&#…

從零開始的云計算生活——第三十八天,避坑落井,Docker容器模塊

一.故事背景 在綜合使用了之前全部的知識完成項目之后&#xff0c;接下來將學習更簡單的方法來對之前的命令進行使用&#xff0c;馬上進入容器模塊 二. Docker概述 Docker簡介 Docker&#xff0c;翻譯過來就是碼頭工人 Docker是一個開源的應用容器引擎&#xff0c;讓開發者…

Python與自動化運維:構建智能IT基礎設施的終極方案

Python與自動化運維:構建智能IT基礎設施的終極方案 引言:運維革命的Python引擎 在DevOps理念席卷全球的今天,企業IT基礎設施的復雜度呈指數級增長。某跨國銀行的數據顯示,采用Python構建的自動化運維體系使其服務器部署效率提升400%,故障響應時間縮短至原來的1/8。本文將…

HarmonyOS應用開發環境搭建以及快速入門介紹

下載并安裝DevEco Studio&#xff0c;這是華為官方提供的HarmonyOS應用開發IDE。訪問華為開發者聯盟官網下載對應操作系統的版本。安裝完成后&#xff0c;配置HarmonyOS SDK和必要的工具鏈。 確保計算機滿足開發環境要求&#xff0c;包括Windows 10 64位或macOS 10.14及以上操…

RocketMQ與Kafka 消費者組的?重平衡操作消息順序性對比

RocketMQ 的重平衡機制本身不會直接影響消息順序&#xff0c;但消費模式的選擇和使用需注意以下細節&#xff1a;重平衡機制RocketMQ消費者組的重平衡策略是每隔20秒從Broker獲取消費組的最新消費進度&#xff0c;并根據訂閱信息重新分配消息隊列。該策略主要影響消息拉取的均衡…

學習 Android(十四)NDK基礎

學習 Android&#xff08;十四&#xff09;NDK基礎 Android NDK 是一個工具集&#xff0c;可讓我們使用 C 和 C 等語言以原生代碼實現應用的各個部分。對于特定類型的應用&#xff0c;這可以幫助我們重復使用以這些語言編寫的代碼庫。 接下來&#xff0c;我們將按照以下步驟進行…

寶塔(免費版9.2.0)的docker拉取倉庫失敗的加速方法

寶塔docker拉取倉庫失敗 完美加速方法_寶塔docker加速-CSDN博客 版本&#xff1a;免費版 9.2.0 https://docker.1ms.run 其他的試了很多 都不行 最后不要用寶塔的控制面板(很卡)&#xff0c;直接在linux中用命令行&#xff0c;效果就很好了。