1. LVGL簡介
LittlevGL是一個免費的開源圖形庫,提供了建立嵌入式GUI所需的一切,具備易於使用的圖形元素、漂亮的視覺效果和低內存佔用。
使用效果能夠去:LittlevGL開源GUI看看,使用效果然的非常驚豔,這裏使用羣友的一張圖來看看近年來各類GUI圖形庫的發展趨勢:
html
2. 演示效果
對於ESP32上使用LVGL,我在三種設備上進行了測試,屏幕驅動型號分別爲:1.14寸ST7789V、3.5寸ILI9488、3.5寸ST7796S,爲了方便對比,我在他們上邊建立了一樣的儀表控件,下面請看演示效果:git
-
我本身的小手錶
我在前幾個月基於ESP32製做的小手錶,集成多種功能,硬件資源有:1.14寸屏幕、自動下載電路、溫溼度、RTC時鐘、大氣壓計、光亮度傳感、加速度計、撥輪按鍵、TFT卡、蜂鳴器、振動馬達、WS2812RGB燈、鋰電池管理,能夠說是能夠知足目前的開發要求了;
項目地址 : ESP32-Watch
github -
啓明雲端GUI開發板
該開發板是啓明雲端公司推出的一款基於ESP32的GUI開發板,搭載了3.5寸ST7796S屏幕和FT6336U電容觸摸,開發平臺爲自研的8ms創新視界拖拽式平臺,有點相似Mixly吧,具體使用效果請查看:ESP32GUI開發板
屏幕和觸摸的驅動,我也進行了移植和修改,下面放出修改後的庫:
①3.5寸ST7796S屏幕驅動
②FT6336U電容觸摸驅動
移植了LVGL儀表盤的演示效果:
ide -
3.5寸ILI9488屏幕
這種屏幕相信某寶能隨處買到了,屏幕硬件爲:3.5寸ILI9488屏幕和XPT2046電阻觸摸,屏幕分辨率爲480x320,在初始化觸摸屏時,也要注意觸摸分辨率也要初始化爲480x320,並設置好觸摸方向,下面看演示效果:
oop
看完這些演示,你應該明白我爲何使用LVGL了吧,一樣的GUI源碼能夠很方便的在各類移植了LVGL的硬件上使用,達到一樣的演示效果,這是我最喜歡的part了學習
3. 開始移植
3.1 源碼準備
3.1.1 目前lvgl在GitHub上已經有了Arduino上的庫支持,庫名字爲 lv_arduino進去後你能夠發現該庫已經有不少版本了,能夠根據本身的喜愛下載,並放入到你的Arduino的Library文件夾下:測試
-
lv_arduino V2.1.5 版本對應的 LVGL 版本爲V6,適合已經習慣 LittlevGL V6 的老師傅們了。ui
-
lv_arduino V3.0.1 版本對應的 LVGL 版本爲V7,適合正在學習的新人們,可是沒法兼容老版本的GUI程序。spa
3.1.2 完成以上操做,你能夠根據你選擇的 lv_arduino 版本下載 LVGL 的例程進行學習,版本對應關係請看上述「1和2」,例程連接爲:lv_examples.net
3.1.3 lv_arduino 給出的 examples 使用的是 TFT_eSPI 庫,這個庫刷屏速度比其餘庫要快,配合 lv_arduino 的例程能夠直接使用。
3.2 學習文檔
固然,嫌麻煩的,能夠把文檔下載下來,進去以後頁面頂部有PDF下載按鈕。
可是,這種英文文檔對咱們來講着實不友好,尤爲是我這種英語四級還沒經過的zhazha,還記得我以前提過GUI代碼是通用的嘛,所以你能夠學習其餘廠商的LVGL教程,畢竟GUI代碼通用,只是接口移植部分不同而已。
3.3 移植
因爲屏幕衆多,就不一一演示移植過程了,下面就以最簡單的 3.5寸 ILI9488屏幕爲例,lv_arduino 庫版本爲 lv_arduino V3.0.1 ,購買連接就不放出來了,你們經過圖片在某寶搜索便可,尺寸隨意,可是我感受3.5寸顯示更漂亮:
屏幕的引腳說明爲:
【屏幕驅動】: TFT_eSPI
【觸摸驅動】: TFT_Touch
【LVGL庫】: lv_arduino
3.3.1 第1步(下載庫)
將 TFT_eSPI 、TFT_Touch、lv_arduino 三個庫放入到你的Arduino的Library文件夾下。
3.3.2 第2步(修改屏幕驅動庫TFT_eSPI)
打開Arduino的Library文件夾下的TFT_eSPI目錄,打開 User_Setup_Select.h 文件:
將第22行的
#include <User_Setup.h> // Default setup is root library folder
註釋掉爲
//#include <User_Setup.h> // Default setup is root library folder
將第47行的
//#include <User_Setups/Setup21_ILI9488.h> // Setup file for ESP32 and ILI9488 SPI bus TFT
取消註釋爲
#include <User_Setups/Setup21_ILI9488.h> // Setup file for ESP32 and ILI9488 SPI bus TFT
完成以上操做後打開 User_Setups 目錄下的 Setup21_ILI9488.h 文件:
將其內容刪掉並修改成:
// See SetupX_Template.h for all options available #define ILI9488_DRIVER //#define TFT_INVERSION_OFF #define TFT_MISO 19 // (leave TFT SDO disconnected if other SPI devices share MISO) #define TFT_MOSI 23 #define TFT_SCLK 18 #define TFT_CS 15 // Chip select control pin #define TFT_DC 2 // Data Command control pin #define TFT_RST 4 // Reset pin (could connect to RST pin) #define TFT_BL 21 //背光引腳 #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts #define SMOOTH_FONT // #define SPI_FREQUENCY 20000000 // #define SPI_FREQUENCY 27000000 // #define SPI_FREQUENCY 40000000 // #define SPI_FREQUENCY 80000000 #define SPI_FREQUENCY 60000000 // Optional reduced SPI frequency for reading TFT #define SPI_READ_FREQUENCY 16000000 #define SPI_TOUCH_FREQUENCY 2500000
3.3.3 第3步(ESP32與屏幕接線)
屏幕引腳 | ESP32引腳 |
---|---|
VCC | 5V |
GND | GND |
CS | IO15 |
RESET | IO4 |
DC/RS | IO2 |
SDI(MOSI) | IO23 |
SCK | IO18 |
LED | IO21 |
SDO(MISO) | IO19 |
—— | —— |
T_CLK | IO25 |
T_CS | IO26 |
T_DIN | IO27 |
T_DO | IO14 |
T_IRQ | 不接 |
3.3.4 第4步 (測試例程)
/** * @name:liuzewen * @title:lvgl_test * @time:2020/8/14 */ #include <lvgl.h> #include <TFT_eSPI.h> #include <Arduino.h> #include <SPI.h> #include <TFT_Touch.h> #define LVGL_TICK_PERIOD 60 TFT_eSPI tft = TFT_eSPI(); /* TFT instance */ static lv_disp_buf_t disp_buf; static lv_color_t buf[LV_HOR_RES_MAX * 10]; lv_obj_t * slider_label; int screenWidth = 480; int screenHeight = 320; //觸摸 #define DOUT 14 /* Data out pin (T_DO) of touch screen */ #define DIN 27 /* Data in pin (T_DIN) of touch screen */ #define DCS 26 /* Chip select pin (T_CS) of touch screen */ #define DCLK 25 /* Clock pin (T_CLK) of touch screen */ TFT_Touch touch = TFT_Touch(DCS, DCLK, DIN, DOUT); int X_Raw = 0, Y_Raw = 0; #if USE_LV_LOG != 0 /* Serial debugging */ void my_print(lv_log_level_t level, const char * file, uint32_t line, const char * dsc) { Serial.printf("%s@%d->%s\r\n", file, line, dsc); delay(100); } #endif /* Display flushing */ void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { uint16_t c; tft.startWrite(); /* Start new TFT transaction */ tft.setAddrWindow(area->x1, area->y1, (area->x2 - area->x1 + 1), (area->y2 - area->y1 + 1)); /* set the working window */ for (int y = area->y1; y <= area->y2; y++) { for (int x = area->x1; x <= area->x2; x++) { c = color_p->full; tft.writeColor(c, 1); color_p++; } } tft.endWrite(); /* terminate TFT transaction */ lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */ } bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data) { uint16_t touchX, touchY; bool touched = touch.Pressed();//檢測觸摸是否按下 //獲取屏幕座標 touchX = touch.X(); touchY = touch.Y(); if(!touched) { return false; } if(touchX>screenWidth || touchY > screenHeight) { Serial.println("Y or y outside of expected parameters.."); Serial.print("y:"); Serial.print(touchX); Serial.print(" x:"); Serial.print(touchY); } else { data->state = touched ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; /*Save the state and save the pressed coordinate*/ //if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&last_x, &last_y); /*Set the coordinates (if released use the last pressed coordinates)*/ data->point.x = touchX; data->point.y = touchY; Serial.print("Data x"); Serial.println(touchX); Serial.print("Data y"); Serial.println(touchY); } return false; /*Return `false` because we are not buffering and no more data to read*/ } lv_obj_t * gauge1; long date = 0; uint8_t date_cotter = 0; void setup() { //屏幕背光采用PWM調光 ledcSetup(10, 5000/*freq*/, 10 /*resolution*/); ledcAttachPin(TFT_BL, 10); analogReadResolution(10); ledcWrite(10,1023); Serial.begin(115200); /* prepare for possible serial debug */ lv_init(); #if USE_LV_LOG != 0 lv_log_register_print_cb(my_print); /* register print function for debugging */ #endif //屏幕初始化 tft.begin(); /* TFT init */ tft.setRotation(1); //觸摸初始化 touch.setCal(481, 3395, 755, 3487, 480, 320, 1); //旋轉 touch.setRotation(3); lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10); //顯示刷新接口 lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.hor_res = screenWidth; disp_drv.ver_res = screenHeight; disp_drv.flush_cb = my_disp_flush; disp_drv.buffer = &disp_buf; lv_disp_drv_register(&disp_drv); //觸摸板輸入接口 lv_indev_drv_t indev_drv; lv_indev_drv_init(&indev_drv); /*Descriptor of a input device driver*/ indev_drv.type = LV_INDEV_TYPE_POINTER; /*Touch pad is a pointer-like device*/ indev_drv.read_cb = my_touchpad_read; /*Set your driver function*/ lv_indev_drv_register(&indev_drv); /*Finally register the driver*/ //放置儀表盤控件 static lv_color_t needle_colors[1]; needle_colors[0] = LV_COLOR_PURPLE; //gauge控件 gauge1 = lv_gauge_create(lv_scr_act(), NULL); lv_gauge_set_needle_count(gauge1, 1, needle_colors); lv_obj_set_size(gauge1, 300, 300); lv_obj_align(gauge1, NULL, LV_ALIGN_CENTER, 0, 0); //設置儀表指針指向的值 lv_gauge_set_value(gauge1, 0, 0); date = millis(); } void loop() { lv_task_handler(); /* let the GUI do its work */ delay(5); if(millis()-date>20) { date = millis(); date_cotter++; date_cotter = date_cotter>100?0:date_cotter; //刷新儀表指針指向的值 lv_gauge_set_value(gauge1, 0, date_cotter); Serial.printf("date_cotter: %d\n",date_cotter); } }
上傳程序到你的ESP32開發板,便可看到屏幕上出現儀表控件,而且指針也在轉圈圈,哈哈!
3.3.5 第5步 (跑一下官方demo)
最後在啓明雲端的板子和3.5寸的ILI9488屏幕上跑一下LVGL官方的demo程序lv_demo_widgets()
,下面放出演示效果:
3.3.6 第6步 (注意事項)
若是你按照過程操做,卻未看到預想的效果,請注意從新認真看一遍本文檔,並留意其中每一句話。
待續~~~~~~~~