概述
本文介紹目前LVGL的應用小知識,希望對采用MCU設計UI界面的用戶有所啟發(fā),開發(fā)出界面更友好的消費品或者工業(yè)產(chǎn)品,造福大眾。
01.
LVGL系統(tǒng)架構(gòu)
LVGL系統(tǒng)框架
應用程序創(chuàng)建GUI并處理特定任務的應用程序。
LVGL本身是一個圖形庫。我們的應用程序通過調(diào)用LVGL庫來創(chuàng)建GUI。它包含一個HAL(硬件抽象層)接口,用于注冊顯示和輸入設備驅(qū)動程序。
驅(qū)動程序除特定的驅(qū)動程序外,它還有其他的功能,可驅(qū)動顯示器到GPU (可選)、讀取觸摸板或按鈕的輸入。
根據(jù)MCU,有兩種典型的硬件設置。一個帶有內(nèi)置LCD/TFT驅(qū)動器的外圍設備,而另一種是沒有內(nèi)置LCD/TFT驅(qū)動器的外圍設備。在這兩種情況下,都需要一個幀緩沖區(qū)來存儲屏幕的當前圖像。
1.集成了TFT/LCD驅(qū)動器的MCU如果MCU集成了TFT/LCD驅(qū)動器外圍設備,則可以直接通過RGB接口連接顯示器。在這種情況下,幀緩沖區(qū)可以位于內(nèi)部RAM(如果MCU有足夠的RAM)中,也可以位于外部RAM(如果MCU具有存儲器接口)中。
2.如果MCU沒有集成TFT/LCD驅(qū)動程序接口,則必須使用外部顯示控制器(例如SSD1963、SSD1306、ILI9341 )。在這種情況下,MCU可以通過并行端口,SPI或通過I2C與顯示控制器進行通信。幀緩沖區(qū)通常位于顯示控制器中,從而為MCU節(jié)省了大量RAM。
02.
建立一個LVGL項目
要在我們的項目中使用 lvgl ,我們起碼需要獲取到官方的這兩個庫:
lvgl(lvgl)核心圖形庫的官方 GitHub 倉庫地址:https://github.com/lvgl/lvgl。
lvgl(lv_drivers)輸入輸出設備驅(qū)動官方 GitHub 倉庫地址:https://github.com/lvgl/lv_drivers
我們可以克隆或下載這兩個庫的最新版本,將它們復制到我們的項目中,然后進行適配。
目錄 lvgl 就是 lvgl 的官方圖形庫
目錄 lv_drivers 是 lvgl 輸入輸出設備驅(qū)動官方示例配置
目錄 lv_examples 是 lvgl 的官方demo(可選,但不要直接使用到實際項目中)
配置文件
上面的三個庫中有一個類似名為 lv_conf_template.h 的配置頭文件(template就是模板的意思)。通過它可以設置庫的基本行為,裁剪不需要模塊和功能,在編譯時調(diào)整內(nèi)存緩沖區(qū)的大小等等。
將 lvgl/lv_conf_template.h 復制到 lvgl 同級目錄下,并將其重命名為 lv_drv_conf.h 。打開文件并將開頭的 #if 0 更改為 #if 1 以使能其內(nèi)容。
將 lv_drivers/lv_drv_conf_template.h 復制到 lv_drivers 同級目錄下,并將其重命名為 lv_conf.h 。打開文件并將開頭的 #if 0 更改為 #if 1 以使能其內(nèi)容。
(可選)將 lv_examples/lv_ex_conf_template.h 復制到 lv_examples 同級目錄下,并將其重命名為 lv_ex_conf.h 。打開文件并將開頭的 #if 0 更改為 #if 1 以使能其內(nèi)容。
準備lvgl配置文件
使能配置文件
lv_conf.h 也可以復制到其他位置,但是應該在編譯器選項中添加 ``LV_CONF_INCLUDE_SIMPLE``定義(例如,對于gcc編譯器為``-DLV_CONF_INCLUDE_SIMPLE`` ) 并手動設置包含路徑。
在配置文件中,注釋說明了各個選項的含義。我們在移植時至少要檢查以下三個配置選項,其他配置根據(jù)具體的需要進行修改:
LV_HOR_RES_MAX 顯示器的水平分辨率。
LV_VER_RES_MAX 顯示器的垂直分辨率。
LV_COLOR_DEPTH 顏色深度,其可以是:
8 - RG332
16 - RGB565
32 - (RGB888和ARGB8888)
初始化LVGL
準備好這三個庫:lvgl、lv_drivers、lv_examples 后,我們就要開始使用lvgl帶給我們的功能了。使用 lvgl 圖形庫之前,我們還必須初始化 lvlg 以及相關其他組件。初始化的順序為:
調(diào)用 lv_init() 初始化 lvgl 庫;
初始化驅(qū)動程序;
在 LVGL 中注冊顯示和輸入設備驅(qū)動程序;
在中斷中每隔 x毫秒 調(diào)用 lv_tick_inc(x) 用以告知 lvgl 經(jīng)過的時間;
每隔 x毫秒 定期調(diào)用 lv_task_handler() 用以處理與 LVGL相關的任務。
03.
顯示接口
要設置顯示,必須初始化 lv_disp_buf_t 和 lv_disp_drv_t 變量。
lv_disp_buf_t 保存顯示緩沖區(qū)信息的結(jié)構(gòu)體
lv_disp_drv_t HAL要注冊的顯示驅(qū)動程序、與顯示交互并處理與圖形相關的結(jié)構(gòu)體、回調(diào)函數(shù)。
顯示緩存區(qū)
關于緩沖區(qū)大小,有 3 種情況:
一個緩沖區(qū) LVGL將屏幕的內(nèi)保存到緩沖區(qū)中并將其發(fā)送到顯示器。緩沖區(qū)可以小于屏幕。在這種情況下,較大的區(qū)域?qū)⒈恢禺嫵啥鄠€部分。如果只有很小的區(qū)域發(fā)生變化(例如按下按鈕),則只會刷新該部分的區(qū)域。
兩個非屏幕大小的緩沖區(qū) 具有兩個緩沖區(qū)的 LVGL 可以將其中一個作為顯示緩沖區(qū),而另一緩沖區(qū)的內(nèi)容發(fā)送到后臺顯示。應該使用 DMA 或其他硬件將數(shù)據(jù)傳輸?shù)斤@示器,以讓CPU同時繪圖。這樣,渲染和刷新并行處理。與 一個緩沖區(qū) 的情況類似,如果緩沖區(qū)小于要刷新的區(qū)域,LVGL將按塊繪制顯示內(nèi)容
兩個屏幕大小的緩沖區(qū) 與兩個非屏幕大小的緩沖區(qū)相反,LVGL將始終提供整個屏幕的內(nèi)容,而不僅僅是塊。這樣,驅(qū)動程序可以簡單地將幀緩沖區(qū)的地址更改為從 LVGL 接收的緩沖區(qū)。因此,當MCU具有 LCD/TFT 接口且?guī)彌_區(qū)只是 RAM 中的一個位置時,這種方法的效果很好。
顯示驅(qū)動器
一旦緩沖區(qū)初始化準備就緒,就需要初始化顯示驅(qū)動程序。在最簡單的情況下,僅需要設置 lv_disp_drv_t 的以下兩個字段:
buffer 指向已初始化的 lv_disp_buf_t 變量的指針。
flush_cb 回調(diào)函數(shù),用于將緩沖區(qū)的內(nèi)容復制到顯示的特定區(qū)域。刷新準備就緒后,需要調(diào)用lv_disp_flush_ready()。LVGL可能會以多個塊呈現(xiàn)屏幕,因此多次調(diào)用flush_cb。使用 lv_disp_flush_is_last() 可以查看哪塊是最后渲染的。
其中,有一些可選的數(shù)據(jù)字段:
hor_res 顯示器的水平分辨率。(默認為 lv_conf.h 中的 LV_HOR_RES_MAX )
ver_res 顯示器的垂直分辨率。(默認為 lv_conf.h 中的 LV_VER_RES_MAX )
color_chroma_key 在 chrome 鍵控圖像上將被繪制為透明的顏色。(默認為 lv_conf.h 中的 LV_COLOR_TRANSP )
user_data 驅(qū)動程序的自定義用戶數(shù)據(jù)。可以在 lv_conf.h 中修改其類型。
anti-aliasing 使用抗鋸齒(anti-aliasing)(邊緣平滑)。缺省情況下默認為 lv_conf.h 中的 LV_ANTIALIAS 。
rotated 如果 1 交換 hor_res 和 ver_res 。兩種情況下 LVGL 的繪制方向相同(從上到下的線條),因此還需要重新配置驅(qū)動程序以更改顯示器的填充方向。
screen_transp 如果為 1 ,則屏幕可以具有透明或不透明的樣式。需要在 lv_conf.h 中啟用 LV_COLOR_SCREEN_TRANSP 。
要使用GPU,可以使用以下回調(diào):
gpu_fill_cb 用顏色填充內(nèi)存中的區(qū)域。
gpu_blend_cb 使用不透明度混合兩個內(nèi)存緩沖區(qū)。
gpu_wait_cb 如果在 GPU 仍在運行 LVGL 的情況下返回了任何 GPU 函數(shù),則在需要確保GPU渲染就緒時將使用此函數(shù)。
注意,這些功能需要繪制到內(nèi)存(RAM)中,而不是直接顯示在屏幕上。
其他一些可選的回調(diào),使單色、灰度或其他非標準RGB顯示一起使用時更輕松、優(yōu)化:
rounder_cb 四舍五入要重繪的區(qū)域的坐標。例如。2x2像素可以轉(zhuǎn)換為2x8。如果顯示控制器只能刷新特定高度或?qū)挾鹊膮^(qū)域(對于單色顯示器,通常為8 px高),則可以使用它。
set_px_cb 編寫顯示緩沖區(qū)的自定義函數(shù)。如果顯示器具有特殊的顏色格式,則可用于更緊湊地存儲像素。(例如1位單色,2位灰度等)。這樣,lv_disp_buf_t中使用的緩沖區(qū)可以較小,以僅保留給定區(qū)域大小所需的位數(shù)。set_px_cb不能與兩個屏幕大小的緩沖區(qū)一起顯示緩沖區(qū)配置。
monitor_cb 回調(diào)函數(shù)告訴在多少時間內(nèi)刷新了多少像素。
clean_dcache_cb 清除與顯示相關的所有緩存的回調(diào)
要設置 lv_disp_drv_t 變量的字段,需要使用 lv_disp_drv_init(&disp_drv) 進行初始化。最后,要為 LVGL 注冊顯示設備,需要調(diào)用lv_disp_drv_register(&disp_drv)。
04.
輸入設備接口
(一)、輸入設備的類型
要設置輸入設備,必須初始化 lv_indev_drv_t 變量:
類型 (indev_drv.type)可以是:
LV_INDEV_TYPE_POINTER 觸摸板或鼠標
LV_INDEV_TYPE_KEYPAD 鍵盤或小鍵盤
LV_INDEV_TYPE_ENCODER 帶有左,右,推動選項的編碼器
LV_INDEV_TYPE_BUTTON 外部按鈕按下屏幕
read_cb (indev_drv.read_cb)是一個函數(shù)指針,將定期調(diào)用該函數(shù)指針以報告輸入設備的當前狀態(tài)。它還可以緩沖數(shù)據(jù)并在沒有更多數(shù)據(jù)要讀取時返回 false ,或者在緩沖區(qū)不為空時返回 true 。
進一步了解有關 輸入設備 的更多信息。
(二)、觸摸板,鼠標或任何指針
可以單擊屏幕點的輸入設備屬于此類別。
即使狀態(tài)為 LV_INDEV_STATE_REL ,觸摸板驅(qū)動程序也必須返回最后的 X/Y 坐標。
要設置鼠標光標,請使用 lv_indev_set_cursor(my_indev,&img_cursor) 。( my_indev 是 lv_indev_drv_register 的返回值)鍵盤或鍵盤
(三)、觸摸板或鍵盤
帶有所有字母的完整鍵盤或帶有一些導航按鈕的簡單鍵盤均屬于此處。
要使用鍵盤/觸摸板:
注冊具有 LV_INDEV_TYPE_KEYPAD 類型的 read_cb 函數(shù)。
在 lv_conf.h 中啟用 LV_USE_GROUP
必須創(chuàng)建一個對象組:lv_group_t * g = lv_group_create(),并且必須使用 lv_group_add_obj(g,obj) 向其中添加對象
必須將創(chuàng)建的組分配給輸入設備:lv_indev_set_group(my_indev,g)( my_indev 是 lv_indev_drv_register 的返回值)
使用 LV_KEY _… 在組中的對象之間導航。有關可用的密鑰,請參見 lv_core/lv_group.h。
(四)、編碼器
可以通過下面四種方式使用編碼器:
按下按鈕
長按其按鈕
轉(zhuǎn)左
右轉(zhuǎn)
簡而言之,編碼器輸入設備的工作方式如下:
通過旋轉(zhuǎn)編碼器,可以專注于下一個/上一個對象。
在簡單對象(如按鈕)上按下編碼器時,將單擊它。
如果將編碼器按在復雜的對象(如列表,消息框等)上,則該對象將進入編輯模式,從而轉(zhuǎn)動編碼器即可在對象內(nèi)部導航。
長按按鈕,退出編輯模式。
要使用編碼器(類似于鍵盤),應將對象添加到組中。
(五)、使用帶有編碼器邏輯的按鈕
除了標準的編碼器行為外,您還可以利用其邏輯來使用按鈕導航(聚焦)和編輯小部件。如果只有幾個按鈕可用,或者除編碼器滾輪外還想使用其他按鈕,這將特別方便。
需要有3個可用的按鈕:
LV_KEY_ENTER 將模擬按下或推動編碼器按鈕
LV_KEY_LEFT 將向左模擬轉(zhuǎn)向編碼器
LV_KEY_RIGHT 將正確模擬轉(zhuǎn)向編碼器
其他鍵將傳遞給焦點小部件
如果按住這些鍵,它將模擬indev_drv.long_press_rep_time中指定的時間段內(nèi)的編碼器單擊。
(六)、按鍵
按鈕是指屏幕旁邊的外部“硬件”按鈕,它們被分配給屏幕的特定坐標。如果按下按鈕,它將模擬在指定坐標上的按下。(類似于觸摸板)
使用 lv_indev_set_button_points(my_indev, points_array) 將按鈕分配給坐標。points_array應該看起來像const lv_point_t points_array [] = {{12,30},{60,90},…}
points_array不能超出范圍。將其聲明為全局變量或函數(shù)內(nèi)部的靜態(tài)變量。
(七)、其它功能
除了 read_cb 之外,還可以在 lv_indev_drv_t 中指定 feedback_cb 回調(diào)。輸入設備發(fā)送任何類型的事件時,都會調(diào)用feedback_cb。(獨立于其類型)。它允許為用戶提供反饋,例如在LV_EVENT_CLICK上播放聲音。
可以在lv_conf.h中設置以下參數(shù)的默認值,但可以在lv_indev_drv_t中覆蓋默認值:
拖拽限制(drag_limit) 實際拖動對象之前要滑動的像素數(shù) drag_throw 拖曳速度降低[%]。更高的價值意味著更快的減速
(drag_throw) 拖曳速度降低[%]。更高的價值意味著更快的減速
(long_press_time) 按下時間發(fā)送 LV_EVENT_LONG_PRESSED (以毫秒為單位)
(long_press_rep_time) 發(fā)送 LV_EVENT_LONG_PRESSED_REPEAT 的時間間隔(以毫秒為單位)
(read_task) 指向讀取輸入設備的lv_task的指針。可以通過 lv_task_.。。() 函數(shù)更改其參數(shù)
每個輸入設備都與一個顯示器關聯(lián)。默認情況下,新的輸入設備將添加到最后創(chuàng)建的或顯式選擇的顯示設備(使用lv_disp_set_default())。相關的顯示已存儲,并且可以在驅(qū)動程序的顯示字段中更改。
(八)、心跳
LVGL 需要系統(tǒng)滴答聲才能知道動畫和其他任務的經(jīng)過時間。
為此我們需要定期調(diào)用 lv_tick_inc(tick_period) 函數(shù),并以毫秒為單位告知調(diào)用周期。例如, lv_tick_inc(1) 用于每毫秒調(diào)用一次。
為了精確地知道經(jīng)過的毫秒數(shù),lv_tick_inc 應該在比 lv_task_handler() 更高優(yōu)先級的例程中被調(diào)用(例如在中斷中),即使 lv_task_handler 的執(zhí)行花費較長時間。
(九)、任務處理器(Task Handler)
要處理 LVGL 的任務,我們需要定期通過以下方式之一調(diào)用 lv_task_handler() :
mian 函數(shù)中設置 while(1) 調(diào)用
定期定時中斷(低優(yōu)先級然后是 lv_tick_inc()) 中調(diào)用
定期執(zhí)行的 OS 任務中調(diào)用
計時并不嚴格,但應保持大約5毫秒以保持系統(tǒng)響應。
05.
日志記錄
LVGL 內(nèi)置有日志模塊,用于記錄用戶庫中正在發(fā)生的事情。
(一)、日志級別
要啟用日志記錄,需要在 lv_conf.h 中將 LV_USE_LOG 設置為 1 ,并將 LV_LOG_LEVEL 設置為以下值之一:
LV_LOG_LEVEL_TRACE 記錄所有信息
LV_LOG_LEVEL_INFO 記錄重要事件
LV_LOG_LEVEL_WARN 記錄是否發(fā)生了警告事件
LV_LOG_LEVEL_ERROR 記錄錯誤信息,當系統(tǒng)可能發(fā)生故障時或致命錯誤
LV_LOG_LEVEL_NONE 不要記錄任何東西
級別高于設置的日志級別的事件也將被記錄。例如。如果使用 LV_LOG_LEVEL_WARN ,也會記錄錯誤。
(二)、使用printf記錄
如果您的系統(tǒng)支持printf,則只需在 lv_conf.h 中啟用 **LV_LOG_PRINTF **即可發(fā)送帶有 printf 的日志。
(三)、自定義日志功能
如果不能使用 printf 或想要使用自定義函數(shù)進行日志記錄,可以使用 lv_log_register_print_cb() 注冊 “l(fā)ogger” 回調(diào)。
編輯:jq
-
處理器
+關注
關注
68文章
19852瀏覽量
234153 -
編碼器
+關注
關注
45文章
3786瀏覽量
137588 -
gpu
+關注
關注
28文章
4925瀏覽量
130908 -
函數(shù)
+關注
關注
3文章
4377瀏覽量
64540 -
LVGL
+關注
關注
1文章
103瀏覽量
3610
原文標題:華芯微特小課堂--LVG免費開源GUI圖形庫
文章出處:【微信號:gh_ed4f95bde4df,微信公眾號:華芯微特32位MCU】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
10分鐘上手睿擎平臺GUI開發(fā):第一個LVGL圖形應用

從“代碼迷宮”到“視覺藍圖”——LVGL的嵌入式UI設計哲學!

如何在linux小核下運行lvgl?
瑞芯微RK3506開發(fā)板必備之LVGL應用開發(fā)手冊,深圳觸覺智能出品

觸覺智能RK3506核心板,工業(yè)應用之LVGL顯示方案分享

基于RTThread nano的LVGL線程卡頓是什么原因引起的?
LVGL開發(fā)入門教程

芯原股份與LVGL達成戰(zhàn)略合作,共推嵌入式圖形處理能力
芯原股份與開源圖形庫LVGL達成戰(zhàn)略合作
如何優(yōu)雅的在OpenMV上使用LVGL

評論