前言
由于近期要做一個裝置 ,想著把裝置做的好看一點,就打算使用 GUI 來做一個信息的相關顯示,之前聽說過一款比較輕量級的圖形庫,也就是 lvgl,手頭又正好有一塊搭配屏幕的野火指南者開發(fā)板,單片機型號是 STM32F103VET6,F(xiàn)lash 為 512KB,RAM 為 64KB,屏幕為 3.2 寸電阻觸摸屏,我們在來看一下運行 lvgl 這個 GUI 需要的資源,所需資源如下圖所示:
幾個比較關鍵的就是控制器的主頻需要大于 16 MHz,對于 STM32F103來說,主頻可以達到 72MHz,滿足要求,所需要的 Flash 要大于 64KB,對于指南者這款開發(fā)板來將,他的主控是 STM32F103VET6,F(xiàn)lash 具有 512KB,遠遠滿足要求。對于 RAM 來講,lvgl 所需要的 RAM 是 8KB,推薦使用 24 KB,對于具有 64KB的 STM32F103VET6 來講,是完全滿足要求的。
綜上,可以知道,使用野火指南者開發(fā)板來跑 lvgl 是完全沒有問題的。
移植準備
為了更加快捷的完成移植,在這里就直接使用野火官方寫好的液晶屏幕的驅(qū)動來進行 lvgl 的移植,首先找到野火配套例程中的第 30 號例程,也就是電阻觸摸屏--觸摸畫板這個例程,將這個例程拷貝出來,在這個基礎上進行移植。
拷貝出來之后,進入到工程目錄里,工程目錄結構如下圖所示:
緊接著,我們進到 lvgl 的 github 倉庫,選擇已經(jīng)發(fā)布的 v7.6.1 版本進行移植,
![github倉庫](https://gitee.com/wenzi_D/images4mk/raw/master/lvgl github倉庫.png)
我們將代碼下載下來,放到 Libraries 里面,如下圖所示:
至此,我們就完成了移植前的準備工作,接下來進行移植代碼。
導入 lvgl 庫到 keil 工程中
首先在 keil 工程中新建 lvgl Groups 組,然后將?lvgl/src/lv_core
?lvgl/src/lv_draw
?lvgl/src/lv_font
?lvgl/src/lv_hal
?lvgl/src/lv_misc
?lvgl/src/lv_themes
?lvgl/src/lv_widgets
?路徑下的文件加入到新建的組中, 如下圖所示:
緊接著,我們來看一下 lvgl 官網(wǎng)中的文檔對于 lvgl 運行的要求:
![lvgl 運行要求](https://gitee.com/wenzi_D/images4mk/raw/master/lvgl 運行要求.png)
從序號 1 ,可以看出,??臻g需要大于 2KB 的空間,推薦大于 8 KB,我們這里設置棧空間為 8KB,也就是將如下所示位置的值改為?0x00002000
從序號 2 可以知道,它需要 C99 或者更新的編譯器,我們這里選擇 C99 進行編譯,
![image-20201102141751510](https://gitee.com/wenzi_D/images4mk/raw/master/C99 編譯器.png)
修改 lv_conf.h 配置文件
接下來,需要修改 lv_conf.h 這個文件,這個文件需要修改的地方有好幾個,分別是如下幾個地方:
首先先將田間編譯宏更改為?
#if 1
修改屏幕的分辨率,由于當前所用的野火指南者所搭配的是分辨率為 320 * 240 的,因此需要將?
LV_HOR_RES_MAX
更改為?240
以及將?LV_VER_RES_MAX
?更改為?320
?,如下圖所示:
修改?
LV_COLOR_DEPTH
,此值 1 是用于單色屏,當前我們的是彩色屏,應該設置為 16修改
LV_DPI
?的值,默認值為 130,我們把他設置到 60,這個宏是用來調(diào)節(jié)界面縮放比例的,此值越大,控件分布的就越散,控件自身的間隔也會變大 ,如下圖所示:
配置 lvgl 運行的動態(tài)堆的大小,再官方給出的堆的要求中,對于堆的要求是這樣的:
推薦使用大于 16KB 的堆內(nèi)存,因此這里配置的是 20KB,也就是將LV_MEM_SIZE
?設置為 20KB,也就是將?LV_MEM_SIZE
?的值設置為?20U * 1024U
因為當前開發(fā)板沒有使用到 GPU 和文件系統(tǒng),所以將 GPU 和文件系統(tǒng)的宏定義設置為 0,如下所示:
![image-20201102144629570](https://gitee.com/wenzi_D/images4mk/raw/master/GPU 和文件系統(tǒng).png)
至此,lvgl 的文件就修改完畢了。接下來,就需要提供 lvgl 運行的心跳節(jié)拍
lvgl 心跳節(jié)拍設置
這里采取的一個方案是通過定時器來為 lvgl 來提供心跳節(jié)拍,更為直觀的敘述也就是通過定時器產(chǎn)生 1ms 的定時中斷,然后在中斷服務函數(shù)里調(diào)用 lvgl 的心跳函數(shù)。野火的官方例程李提供了定時中斷的代碼,我們直接將這部分代碼移植過來就好,下面是定時中斷服務函數(shù)里面的相關內(nèi)容:
#include?"lvgl.h"
void?TIM6_IRQHandler(void)
{
????if?(?TIM_GetITStatus(?TIM6,?TIM_IT_Update)?!=?RESET?)?
????{???
????????lv_tick_inc(1);?????????????????????//lvgl?的?1ms?心跳
????????TIM_ClearITPendingBit(TIM6?,?TIM_FLAG_Update);???????????
????}
}
有了中斷服務函數(shù),那相應的就需要有初始化,下面是主函數(shù)的相關代碼:
int?main(void)
{????????
????//LCD?初始化
????ILI9341_Init();??
????//觸摸屏初始化
????XPT2046_Init();
????BASIC_TIM_Init();
????lv_init();??????????/*?lv?系統(tǒng)初始化?*/
????//其中0、3、5、6?模式適合從左至右顯示文字,
????//不推薦使用其它模式顯示文字?其它模式顯示文字會有鏡像效果??????????
????//其中?6?模式為大部分液晶例程的默認顯示方向??
????ILI9341_GramScan?(?3?);????
????while?(?1?)
????{
????????lv_task_handler();
????}
}
最后,我們需要將 lvgl 的相關頭文件路徑加入到 keil 的工程路徑中去,添加完成之后,就可以編譯了,但是使用野火的編寫的 LCD 驅(qū)動編譯之后會出現(xiàn)三個錯誤,如下圖所示:
出現(xiàn)該錯誤的原因是因為 C99 跟內(nèi)聯(lián)函數(shù)的一些關聯(lián),具體的細節(jié)不在這里深究了,更改方式是在三個函數(shù)前加上?static
,如下圖所示:
這樣更改之后,整個代碼就編譯通過了。
移植底層屏幕驅(qū)動
接下來就需要完成移植屏幕底層驅(qū)動了,對于這部分內(nèi)容,總的來說分為兩部分:
移植底層顯示驅(qū)動
移植底層觸摸驅(qū)動
我們將?Libraries\lvgl\examples\porting
里面的文件復制到Libraries\lvgl_driver
里面,并重命名為如下幾個文件:
移植底層顯示驅(qū)動
移植底層顯示驅(qū)動只需要更改?lv_port_disp.c
和?lv_port_disp.h
兩個文件,首先是?lv_port_disp.h
的更改,更改后的文件為:
#if?1
#ifndef?LV_PORT_DISP_H
#define?LV_PORT_DISP_H
#ifdef?__cplusplus
extern?"C"?{
#endif
#include?"lvgl/lvgl.h"
void?lv_port_disp_init(void);
#ifdef?__cplusplus
}?/*?extern?"C"?*/
#endif
#endif?/*LV_PORT_DISP_TEMPL_H*/
#endif?/*Disable/Enable?content*/
更改后的lv_port_disp.c
文件為:
第一個是留下一個例子,第二個是更改屏幕的分辨率。第三部分是
紅色標注部分的函數(shù)也就是以單個像素點填充屏幕的函數(shù),這個函數(shù)野火寫的不滿足調(diào)用要求,筆者稍微將原來的驅(qū)動代碼進行了更改,實現(xiàn)了如下所示的單個像素點填充函數(shù):
void?ILI9341_DrawPixel(uint16_t?usX,?uint16_t?usY,uint16_t?color)
{
????if?((usX?????{
????????ILI9341_SetCursor?(usX,usY);
????????ILI9341_FillColor?(1,color);
????}
}
這樣,就完成了底層屏幕顯示驅(qū)動的移植。
底層屏幕觸摸驅(qū)動移植
移植底層屏幕觸摸驅(qū)動只需要更改?lv_port_indev.c
和?lv_port_indev.h
兩個文件,首先是?lv_port_indev.h
的更改,更改后的文件為
#if?1
#ifndef?LV_PORT_INDEV_H
#define?LV_PORT_INDEV_H
#ifdef?__cplusplus
extern?"C"?{
#endif
#include?"lvgl/lvgl.h"
void?lv_port_indev_init(void);
#ifdef?__cplusplus
}?/*?extern?"C"?*/
#endif
#endif?/*LV_PORT_INDEV_TEMPL_H*/
#endif?/*Disable/Enable?content*/
緊接著就是lv_port_indev.c
的更改,關于這部分代碼,lvgl 官方給出了好幾個輸入設備的函數(shù),觸摸屏,鼠標,小鍵盤,旋鈕,按鍵等輸入設備,我們這里所選用的是觸摸屏,那么就可以把其他的都刪去。下面是幾處關鍵代碼:
最后,加入一個簡單的示例,GUI 就可以運行起來了,加如的程序如下所示:
static?void?btn_event_cb(lv_obj_t?*?btn,?lv_event_t?event)
{
????if(event?==?LV_EVENT_CLICKED)?{
????????static?uint8_t?cnt?=?0;
????????cnt++;
????????/*Get?the?first?child?of?the?button?which?is?the?label?and?change?its?text*/
????????lv_obj_t?*?label?=?lv_obj_get_child(btn,?NULL);
????????lv_label_set_text_fmt(label,?"Button:?%d",?cnt);
????}
}
/**
?*?Create?a?button?with?a?label?and?react?on?Click?event.
?*/
void?lv_ex_get_started_1(void)
{
????lv_obj_t?*?btn?=?lv_btn_create(lv_scr_act(),?NULL);?????/*Add?a?button?the?current?screen*/
????lv_obj_set_pos(btn,?10,?10);????????????????????????????/*Set?its?position*/
????lv_obj_set_size(btn,?120,?50);??????????????????????????/*Set?its?size*/
????lv_obj_set_event_cb(btn,?btn_event_cb);?????????????????/*Assign?a?callback?to?the?button*/
????lv_obj_t?*?label?=?lv_label_create(btn,?NULL);??????????/*Add?a?label?to?the?button*/
????lv_label_set_text(label,?"Button");?????????????????????/*Set?the?labels?text*/
}
主函數(shù)如下所示:
int?main(void)
{????????
????//LCD?初始化
????ILI9341_Init();??
????//觸摸屏初始化
????XPT2046_Init();
????BASIC_TIM_Init();
????lv_init();??????????/*?lv?系統(tǒng)初始化?*/
????lv_port_disp_init();????/*?lvgl?顯示接口初始化,放在?lv_init()后面?*/
????lv_port_indev_init();???/*?lvgl?輸入接口初始化,放在?lv_init()?后面?*/
????lv_ex_get_started_1();
????//其中0、3、5、6?模式適合從左至右顯示文字,
????//不推薦使用其它模式顯示文字?其它模式顯示文字會有鏡像效果??????????
????//其中?6?模式為大部分液晶例程的默認顯示方向??
????ILI9341_GramScan?(?6?);????
????while?(?1?)
????{
????????lv_task_handler();
????}
}
最終的顯示效果如下圖所示:
官方的 github 倉庫也有做好的比較完善的 demo 可供參考,下圖是 github 上的例程的截圖:
參照 README.md 文檔就可以順利跑起來,下圖是運行 demo 的動圖,效果還是很華麗的。
總結
上述就是移植 lvgl 的整個過程,寫下來記錄一下,移植結束,可以學習如何制作一個精美的界面了,這次的內(nèi)容就到這里,如果在使用過程中,有新的體會,再進行更文~
如果你覺得我的文章對你有所幫助,歡迎再看,點贊,轉(zhuǎn)發(fā)三連吶~歡迎各位添加好友,下圖是筆者的個人微信名片
歡迎關注筆者的公眾號,筆者將不定期更新文章~
免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!