天天看點

LVGL | lvgl最新版本在STM32上的移植使用

1024G 嵌入式資源大放送!包括但不限于C/C++、單片機、Linux等。關注微信公衆号【嵌入式大雜燴】,回複1024,即可免費擷取!

lvgl簡介

LittlevGL是一個免費的開源圖形庫,提供了建立嵌入式GUI所需的一切,具有易于使用的圖形元素、漂亮的視覺效果和低記憶體占用。

LVGL | lvgl最新版本在STM32上的移植使用

特點:

  • 強大的構模組化組 按鈕、圖表、清單、滑塊、圖像等
  • 先進的圖形 動畫、反鋸齒、半透明、平滑滾動
  • 多樣的輸入裝置 觸摸闆、滑鼠、鍵盤、編碼器等
  • 多顯示器支援 支援同時使用多個TFT或單色顯示器
  • 多語言支援 UTF-8格式文字編碼
  • 完全自定義 圖形元素
  • 硬體無關 可用于任意微控制器或顯示器
  • 可裁剪 用于小記憶體(80 KB FLASH,12 KB RAM)操作
  • 作業系統、外部存儲以及GPU 支援但非必須
  • 單幀緩存 即可實作先進的圖形效果
  • C語言編寫 以最大化相容(C++ 相容)
  • 模拟器 無需嵌入式硬體就可以在電腦上開始GUI設計
  • 教程、示例、主題 進而快速GUI設計
  • 文檔 線上及離線
  • 免費開源 基于MIT協定

運作的硬體要求:

LVGL | lvgl最新版本在STM32上的移植使用

lvgl資料

LVGL的資料很豐富,下面列出一些常用的資料連結:

1、lvgl英文官網:

https://lvgl.io/

2、lvgl中文網:

https://littlevgl.cn/    (還在建設中)

3、lvgl源碼:

https://github.com/lvgl/lvgl

4、lvgl基于Visual sudio 的PC模拟器:

https://github.com/lvgl/lv_sim_visual_studio

5、正點原子lvgl教程資料:

http://www.openedv.com/docs/book-videos/zdyzshipin/4free/littleVGL.html

6、基于荔枝派Nano開發闆的lvgl教程:

http://nano.lichee.pro/application/littlevgl.html

7、基于野牛開發闆的 lvgl 6.0 例程:

https://gitee.com/mzy2364/LittlevGL_Demo

8、lvgl線上體驗例程(可在浏覽器體驗):

https://lvgl.io/demos

9、lvgl官網教程:

https://docs.lvgl.io/latest/en/html/index.html

10、lvgl官方DEMO:

https://github.com/lvgl/lv_examples

lvgl移植到STM32

1、下載下傳源碼

源碼連結中下載下傳一份源碼,lvgl已經更新疊代了很多個版本,這裡我們選擇目前最新的7.10.1版本來移植:

LVGL | lvgl最新版本在STM32上的移植使用
注意:不同版本之間可能有很大的不同,是以看本篇教程移植的的小夥伴盡量使用與本文相同的版本。

下載下傳得到:

LVGL | lvgl最新版本在STM32上的移植使用

2、準備stm32工程

下面我基于普中的stm32f103開發闆來移植,首先準備一個lcd顯示的例程,并更名為lvgl_test:

LVGL | lvgl最新版本在STM32上的移植使用

3、建立GUI檔案夾

在工程目錄下建立一個GUI檔案夾,GUI檔案夾下建立兩個子檔案夾:

LVGL | lvgl最新版本在STM32上的移植使用

把剛才下載下傳的lvgl-7.10.1裡的所有内容複制到lvgl檔案夾中,lvgl_app檔案夾暫時留白。

4、移植檔案更名

下面,我們把GUI\lvgl\examples\porting下的檔案進行一個更名操作(其實不更名也可以,為了檔案名看起來規範一些我們進行一個更名):

LVGL | lvgl最新版本在STM32上的移植使用

這是移植相關的幾個檔案,其中:

lv_port_disp:顯示相關。

lv_port_indev:輸入相關。

lv_port_fs:檔案系統相關。

5、配置檔案更名

把GUI\lvgl\下的

lv_conf_template.h

檔案複制到GUI檔案夾下并更名為

lv_conf.h

LVGL | lvgl最新版本在STM32上的移植使用

6、keil工程配置

(1)導入檔案

打開keil工程,在工程下建立三個組,并導入檔案:

LVGL | lvgl最新版本在STM32上的移植使用

導入完成後得到:

LVGL | lvgl最新版本在STM32上的移植使用

這裡的lvgl_porting中我們暫時隻導入lv_port_disp.c檔案,這是顯示相關的移植檔案。本篇筆記先把顯示打通,其它兩個檔案後續有機會再弄。

(2)包含頭檔案路徑

下面包含頭檔案路徑:

LVGL | lvgl最新版本在STM32上的移植使用

(3)修改堆棧大小

因為官方說明文檔中推薦我們堆、棧大小設定為8k:

LVGL | lvgl最新版本在STM32上的移植使用

是以這裡我們就按推薦進行設定:

LVGL | lvgl最新版本在STM32上的移植使用

(4)設定C99模式

lvgl需要編譯器支援C99或更新的标準:

LVGL | lvgl最新版本在STM32上的移植使用

C99模式可進行如下設定:

LVGL | lvgl最新版本在STM32上的移植使用

(5)使能lv_conf.h的條件編譯

進行上面的設定後我們首先進行編譯,會報很多個錯誤:

LVGL | lvgl最新版本在STM32上的移植使用

這是因為需要lv_conf.h裡的一些東西,打開lv_conf.h裡的條件編譯即可:

LVGL | lvgl最新版本在STM32上的移植使用

再次編譯,編譯通過:

LVGL | lvgl最新版本在STM32上的移植使用

(6)lvgl配置

我們可以對lvgl進行一些定制配置,這些配置内容在lv_conf.h檔案中,下面進行一些關鍵配置:

  • 顯示器寬度:#define LV_HOR_RES_MAX (240)
  • 顯示器高度:#define LV_VER_RES_MAX (480)
  • 色彩深度: #define LV_COLOR_DEPTH 16
  • DPI: #define LV_DPI  100
  • 提供給lvgl的空間: #define LV_MEM_SIZE  (32U * 1024U)

其中調整LV_DPI  可以調整各控件間的緊湊,可根據實際情況進行更改;LV_MEM_SIZE  為lvgl可用空間,資源允許的情況下可以稍微設大些,這個設定過小的話,在跑一些稍微複雜的demo時界面就會刷不出來。

這裡隻是列出了幾個常用的配置,lv_conf.h還有很多的配置,可根據實際情況進行配置。

(7)填充、修改lv_port_disp.c

LVGL | lvgl最新版本在STM32上的移植使用
LVGL | lvgl最新版本在STM32上的移植使用

lv_port_disp.c裡面的内容主要有:

LVGL | lvgl最新版本在STM32上的移植使用

我們需要重點關注lv_port_disp_init顯示接口初始化函數與disp_flush螢幕重新整理兩個函數。

其中,lv_port_disp_init函數裡主要要選擇一種寫緩存的方式及設定顯示分辨。我們選擇第一種寫緩存的方式,修改後的函數如:

void lv_port_disp_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    disp_init();

    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/

    /* LVGL requires a buffer where it internally draws the widgets.
     * Later this buffer will passed your display drivers `flush_cb` to copy its content to your display.
     * The buffer has to be greater than 1 display row
     *
     * There are three buffering configurations:
     * 1. Create ONE buffer with some rows:
     *      LVGL will draw the display's content here and writes it to your display
     *
     * 2. Create TWO buffer with some rows:
     *      LVGL will draw the display's content to a buffer and writes it your display.
     *      You should use DMA to write the buffer's content to the display.
     *      It will enable LVGL to draw the next part of the screen to the other buffer while
     *      the data is being sent form the first buffer. It makes rendering and flushing parallel.
     *
     * 3. Create TWO screen-sized buffer:
     *      Similar to 2) but the buffer have to be screen sized. When LVGL is ready it will give the
     *      whole frame to display. This way you only need to change the frame buffer's address instead of
     *      copying the pixels.
     * */

    /* Example for 1) */
    static lv_disp_buf_t draw_buf_dsc_1;
    static lv_color_t draw_buf_1[LV_HOR_RES_MAX * 10];                          /*A buffer for 10 rows*/
    lv_disp_buf_init(&draw_buf_dsc_1, draw_buf_1, NULL, LV_HOR_RES_MAX * 10);   /*Initialize the display buffer*/

    // /* Example for 2) */
    // static lv_disp_buf_t draw_buf_dsc_2;
    // static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * 10];                        /*A buffer for 10 rows*/
    // static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * 10];                        /*An other buffer for 10 rows*/
    // lv_disp_buf_init(&draw_buf_dsc_2, draw_buf_2_1, draw_buf_2_1, LV_HOR_RES_MAX * 10);   /*Initialize the display buffer*/

    // /* Example for 3) */
    // static lv_disp_buf_t draw_buf_dsc_3;
    // static lv_color_t draw_buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX];            /*A screen sized buffer*/
    // static lv_color_t draw_buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX];            /*An other screen sized buffer*/
    // lv_disp_buf_init(&draw_buf_dsc_3, draw_buf_3_1, draw_buf_3_2, LV_HOR_RES_MAX * LV_VER_RES_MAX);   /*Initialize the display buffer*/

    /*-----------------------------------
     * Register the display in LVGL
     *----------------------------------*/

    lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

    /*Set up the functions to access to your display*/

    /*Set the resolution of the display*/
    disp_drv.hor_res = 240;
    disp_drv.ver_res = 400;

    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = disp_flush;

    /*Set a display buffer*/
    disp_drv.buffer = &draw_buf_dsc_1;

#if LV_USE_GPU
    /*Optionally add functions to access the GPU. (Only in buffered mode, LV_VDB_SIZE != 0)*/

    /*Blend two color array using opacity*/
    disp_drv.gpu_blend_cb = gpu_blend;

    /*Fill a memory array with a color*/
    disp_drv.gpu_fill_cb = gpu_fill;
#endif

    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}

           

disp_flush需要調用底層lcd操作接口,這裡修改為:

LVGL | lvgl最新版本在STM32上的移植使用

這裡我們調用一個寫像素點的函數,也可以直接調用一個顯示的填充方形函數。

最後,需要再頭檔案中聲明lv_port_disp_init函數:

LVGL | lvgl最新版本在STM32上的移植使用

(8)配置一個定時器為lvgl提供心跳

lvgl需要一個心跳節拍,可以使用系統滴答定時器,也可以使用其它定時器。我們這裡的配置如下:

TIM4_Init(999, 71);     // 1ms進入一次中斷,為lvgl提供心跳
           
void TIM4_IRQHandler(void)
{
 if(TIM_GetITStatus(TIM4,TIM_IT_Update))
 {
  lv_tick_inc(1);
 }
 TIM_ClearITPendingBit(TIM4,TIM_IT_Update); 
}
           

(9)測試官方demo

下面開始進行測試,至此我們的

GUI\lvgl_app

檔案夾裡還沒有任何内容,我們下載下傳官方提供的demo來進行測試,同樣地,下載下傳官方demo:

LVGL | lvgl最新版本在STM32上的移植使用

官方給我們提供了很多demo:

LVGL | lvgl最新版本在STM32上的移植使用

複制lv_examples-7.10.1整個檔案夾至

GUI\lvgl_app

檔案夾下并更名為lv_examples:

LVGL | lvgl最新版本在STM32上的移植使用

把GUI\lvgl_app\lv_examples下的lv_ex_conf_template.h複制到GUI檔案夾下并更名為

lv_ex_conf.h

,這是demo的配置檔案:

LVGL | lvgl最新版本在STM32上的移植使用
LVGL | lvgl最新版本在STM32上的移植使用

想跑哪個demo就配置相關宏。

下面我們跑一個lv_demo_widgets的demo進行示範:

LVGL | lvgl最新版本在STM32上的移植使用
LVGL | lvgl最新版本在STM32上的移植使用
LVGL | lvgl最新版本在STM32上的移植使用

主函數:

LVGL | lvgl最新版本在STM32上的移植使用

運作測試:

LVGL | lvgl最新版本在STM32上的移植使用

至此,lvgl顯示移植成功。要想示範其它綜合demo或控件例子也同上面一樣導入源檔案、包含頭檔案、打開demo宏開關等步驟進行示範。

本工程可在微信公衆号背景回複關鍵詞:

LittlevGL移植

,進行擷取。

猜你喜歡:

基于GUILite的簡易萬年曆

2020年精選原創筆記彙總

1024G 嵌入式資源大放送!包括但不限于C/C++、單片機、Linux等。關注微信公衆号【嵌入式大雜燴】,回複1024,即可免費擷取!