加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

Arduino應(yīng)用開發(fā)——esp32 lvgl v8.3環(huán)境搭建

04/01 16:11
6294
閱讀需 24 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

LVGL (Light and Versatile Graphics Library) 是一個(gè)很流行的免費(fèi)開源嵌入式圖形庫(kù),可以幫助很多 MCU、MPU 和顯示類型創(chuàng)建好看的 UI。它由Gábor Kiss-Vámosi于2016年創(chuàng)建的一個(gè)開源項(xiàng)目,目前由來自世界各地的志愿者共同維護(hù)和開發(fā)。LVGL是用C語言編寫的,遵循MIT協(xié)議,可以自由地使用和修改。LVGL支持多種操作系統(tǒng),例如Linux、Windows、RTOS等,也可以在開發(fā)板上運(yùn)行。LVGL還支持多種顯示器驅(qū)動(dòng)器觸摸屏驅(qū)動(dòng)器,可以與不同大小和分辨率的顯示器兼容。

LVGL還提供了多種語言的綁定,例如Python、Micropython、JavaScript等,以及多種開發(fā)工具,例如模擬器、視覺化設(shè)計(jì)器、字體轉(zhuǎn)換器等。

1 硬件設(shè)計(jì)

ESP32參數(shù)如下:

參數(shù)
型號(hào) esp32-s2
flash 8M
psram 2M

LCD屏幕參數(shù)如下:

參數(shù)
尺寸 2.6寸
分辨率 240*240
接口 spi
驅(qū)動(dòng)IC ST7789V
觸摸

ESP32與LCD的接線如下:

esp32-s2 lcd 說明
VCC VCC 電源
GND GND 電源負(fù)
GPIO36SPI_CLK CLK SPI時(shí)鐘線
GPIO35SPI_MOSI SDI SPI數(shù)據(jù)線,esp32輸出,lcd輸入
GPIO37SPI_MISO SDO SPI數(shù)據(jù)線,esp32輸入,lcd輸出,注:該引腳一般可以不用,除非你要讀取LCD的信息
GPIO34 CS SPI片選
GPIO4 WR(D/C) 并口時(shí)作為寫入信號(hào)/SPI時(shí)作為命令或參數(shù)的選擇
GPIO1 RST LCD復(fù)位引腳,可以用普通IO控制,引腳不足的情況下也可以和esp32的復(fù)位引腳接到一起
GPIO2 BL 背光引腳

2 軟件設(shè)計(jì)

注:本文是基于PlatformIO搭建的Arduino環(huán)境,所有軟件代碼也是基于這個(gè)環(huán)境編譯。不知道怎么搭建的同學(xué)自行查閱資料,這個(gè)網(wǎng)上教程有很多的。

2.1 新建PlatformIO工程

輸入項(xiàng)目名稱,選擇芯片及開發(fā)板,選擇arduino架構(gòu)。

請(qǐng)?zhí)砑訄D片描述

配置項(xiàng)目參數(shù)(platformio.ini)。
注:具體的項(xiàng)目參數(shù)根據(jù)自己的實(shí)際情況配置。更多的參數(shù)詳情及使用方法,可以在下面的鏈接查看。
https://docs.platformio.org/page/projectconf.html
https://docs.platformio.org/en/latest/platforms/espressif32.html

本文配置的參數(shù)如下:

[env:adafruit_metro_esp32s2]
platform = espressif32
board = adafruit_metro_esp32s2
framework = arduino
lib_deps = 
	bodmer/TFT_eSPI@^2.5.43
	lvgl/lvgl@^8.3.11
monitor_speed = 115200
board_build.f_cpu = 240000000L
board_build.f_flash = 80000000L
board_build.flash_mode = qio
board_upload.flash_size = 8MB
board_upload.speed = 921600
board_upload.use_1200bps_touch = true
board_upload.wait_for_upload_port = true
build_flags = 
	-DBOARD_HAS_PSRAM
	-mfix-esp32-psram-cache-issue
	-DARDUINO_USB_CDC_ON_BOOT=1
	-DARDUINO_USB_DFU_ON_BOOT=0
	-DARDUINO_USB_MSC_ON_BOOT=0
	-DCORE_DEBUG_LEVEL=0
lib_ldf_mode = deep+

2.2 添加開源庫(kù)

在PIO Home界面選擇Libraries,搜索需要的庫(kù)并添加到自己的工程目錄下。

注:每個(gè)PlatformIO工程的庫(kù)都是獨(dú)立的,所以你這里要把庫(kù)添加到對(duì)應(yīng)的工程,舊工程下載的庫(kù)并不能直接用于新工程上。

本文需要使用的Arduino庫(kù)如下:

Arduino庫(kù) 版本 說明
TFT_eSPI 2.5.43 該庫(kù)通過SPI方式驅(qū)動(dòng)LCD,支持多種LCD常用驅(qū)動(dòng)IC
lvgl 8.3.11 lvgl庫(kù),方便做各種圖形處理

配置流程大致如下:

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

添加成功后可以在工程目錄下看到已添加的庫(kù),platformio.ini文件中也會(huì)自動(dòng)生成依賴庫(kù)代碼。

在這里插入圖片描述
在這里插入圖片描述

2.3 配置LCD底層接口

2.3.1 LCD接口配置

TFT_eSPI庫(kù)集成了很多常用LCD驅(qū)動(dòng)IC的接口,根據(jù)自己使用的LCD屏幕參數(shù)修改User_Setup.h文件,即可調(diào)用底層的接口函數(shù)。

注:User_Setup.h定義的參數(shù)比較多,我這里就不一個(gè)個(gè)細(xì)說了。我主要講幾個(gè)重要的參數(shù)。

1)驅(qū)動(dòng)IC

根據(jù)自己使用的LCD驅(qū)動(dòng)IC打開對(duì)應(yīng)的宏。注意這些驅(qū)動(dòng)只能選擇一個(gè)打開,不用的要注釋掉。

在這里插入圖片描述

2)RGB數(shù)據(jù)格式

RGB格式指的是像素點(diǎn)顏色數(shù)據(jù)的排列方式,一般就BGR和RGB兩種,區(qū)別其實(shí)就是數(shù)據(jù)高位在前還是低位在前,這個(gè)主要是用于圖片顯示,要用哪種格式主要是看你要顯示的內(nèi)容是怎么排的,不確定的話可以先不改,調(diào)試的時(shí)候如果顏色不對(duì)的話再換過來就好了。

在這里插入圖片描述

3)像素

根據(jù)自己屏幕的像素修改,也可以先不改,直接在后面應(yīng)用的時(shí)候再改。

在這里插入圖片描述

4)GPIO

根據(jù)自己的電路設(shè)置引腳,除了幾個(gè)必要的引腳,有些引腳可以不配置。

如:RST可以通過硬件和MCU的RST接到一起,軟件配置成-1即可。BL背光也可以硬件直接控制。

注意:相同的GPIO定義只能打開一個(gè),默認(rèn)有些打開了的要注釋掉。

特別說明:建議使用2.4.0以上版本,因?yàn)橹暗陌姹娟P(guān)于ESP32的引腳定義是分成HSPI和VSPI的,默認(rèn)使用VSPI,如果要用HSPI要打開USE_HSPI_PORT定義,但是這套框架兼容性不強(qiáng),不適用于ESP32-S2和ESP32-C2,而2.4.0以上版本取消了這個(gè)定義,直接都按引腳號(hào)來定義,這樣一來就不用區(qū)分HSPI和VSPI了。

在這里插入圖片描述

5)字庫(kù)

TFT_eSPI自帶的這些字庫(kù)你可以直接用,如果你有自己的字庫(kù)不用這里的話也可以注釋掉。flash空間足夠的情況下,這點(diǎn)代碼加不加都沒關(guān)系。

在這里插入圖片描述

6)SPI通訊速率

SPI通訊速率一般默認(rèn)即可,默認(rèn)的這個(gè)速率一般是足夠了的,如果需要更快的話可以自己修改。

在這里插入圖片描述

7)ESP32的特殊定義

TFT_eSPI舊版本關(guān)于ESP32的SPI接口是分為HSPI和VSPI兩種的,默認(rèn)使用VSPI,如果要用HSPI要打開USE_HSPI_PORT定義,如果你只是用ESP32,那這個(gè)框架是沒什么問題的。

但是我之前因?yàn)轫?xiàng)目需要從ESP32改用ESP32-S2,結(jié)果發(fā)現(xiàn)ESP32-S2就沒有HSPI和VSPI,所有接口都是FSPI,于是我就要把底層很多東西都改掉才能正常使用。

不過現(xiàn)在TFT_eSPI庫(kù)2.4.0以上版本就已經(jīng)把這個(gè)問題改掉了,兼容了ESP32-S2和ESP-C3,取消了USE_HSPI_PORT這個(gè)定義,SPI接口都以GPIO引腳號(hào)來定義。

所以,我建議都用新版本的庫(kù)吧,兼容性更好,也不用去考慮用HSPI還是VSPI。

在這里插入圖片描述

2.3.2 LCD驅(qū)動(dòng)測(cè)試

TFT_eSPI庫(kù)配置好了之后可以先燒錄一個(gè)簡(jiǎn)單的程序,驗(yàn)證一下硬件接線和代碼是否能正常運(yùn)行。當(dāng)然,到了后面把lvgl配置好再一步到位也行。

注意:如果此時(shí)已經(jīng)把lvgl庫(kù)加入到工程,又沒有配置的話,編譯會(huì)出錯(cuò)(找不到lv_conf.h文件),得把lvgl庫(kù)刪除或者配置好lvgl庫(kù)再測(cè)試。

測(cè)試代碼如下:

#include <Arduino.h>
#include <SPI.h>
#include <TFT_eSPI.h>

TFT_eSPI tft = TFT_eSPI(); 

void setup() 
{
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);
}

void loop()
{
    tft.fillScreen(TFT_RED);
    delay(1000);
    tft.fillScreen(TFT_GREEN);
    delay(1000);
    tft.fillScreen(TFT_BLUE);
    delay(1000);
}

測(cè)試結(jié)果:

如果能正常運(yùn)行的話,屏幕每隔1s會(huì)依次點(diǎn)亮紅綠藍(lán)三種顏色。

2.4 配置lvgl

2.4.1 添加配置文件

復(fù)制lv_conf_template.h到同一路徑下,并改名為lvgl_conf.h。否則編譯會(huì)報(bào)錯(cuò)(找不到lv_conf.h文件)。

2.4.2 修改lvgl配置

lvgl里面的lvgl_conf.h文件有很多配置參數(shù),具體的我就不一一描述了。需要用到哪些配置,網(wǎng)上都能找到詳細(xì)的教程。我這里講幾個(gè)必須要配置的東西。

1)把下面的宏打開。

在這里插入圖片描述

2)啟用自定義時(shí)鐘

注意:沒有一步的話會(huì)導(dǎo)致屏幕停留在第一幀的界面。

在這里插入圖片描述

3)配置lvgl的顯示接口

要把底層的LCD顯示接口對(duì)接到lvgl這套框架里面,這樣lvgl才能控制顯示屏。

參考代碼:

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
  uint32_t w = ( area->x2 - area->x1 + 1 );
  uint32_t h = ( area->y2 - area->y1 + 1 );

  tft.startWrite();
  tft.setAddrWindow( area->x1, area->y1, w, h );
  tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
  tft.endWrite();

  lv_disp_flush_ready( disp_drv );
}

4)配置lvgl的觸摸接口

:因?yàn)槲疫@里屏幕沒有觸摸接口,所以我這里把代碼注釋掉了,如果要用觸摸接口的話,這里需要打開。

參考代碼:

/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
  // uint16_t touchX, touchY;

  // bool touched = tft.getTouch( &touchX, &touchY, 600 );

  // if( !touched )
  // {
  //     data->state = LV_INDEV_STATE_REL;
  // }
  // else
  // {
  //     data->state = LV_INDEV_STATE_PR;

  //     /*Set the coordinates*/
  //     data->point.x = touchX;
  //     data->point.y = touchY;

  //     Serial.print( "Data x " );
  //     Serial.println( touchX );

  //     Serial.print( "Data y " );
  //     Serial.println( touchY );
  // }
}
2.4.3 lvgl代碼測(cè)試

示例代碼:

#include <Arduino.h>
#include <SPI.h>
#include <TFT_eSPI.h>
#include "lvgl.h"

TFT_eSPI tft = TFT_eSPI(); 

static lv_disp_draw_buf_t draw_buf;

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
  uint32_t w = ( area->x2 - area->x1 + 1 );
  uint32_t h = ( area->y2 - area->y1 + 1 );

  tft.startWrite();
  tft.setAddrWindow( area->x1, area->y1, w, h );
  tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
  tft.endWrite();

  lv_disp_flush_ready( disp_drv );
}

/*Read the touchpad*/
void my_touchpad_read( lv_indev_drv_t * indev_drv, lv_indev_data_t * data )
{
  // uint16_t touchX, touchY;

  // bool touched = tft.getTouch( &touchX, &touchY, 600 );

  // if( !touched )
  // {
  //     data->state = LV_INDEV_STATE_REL;
  // }
  // else
  // {
  //     data->state = LV_INDEV_STATE_PR;

  //     /*Set the coordinates*/
  //     data->point.x = touchX;
  //     data->point.y = touchY;

  //     Serial.print( "Data x " );
  //     Serial.println( touchX );

  //     Serial.print( "Data y " );
  //     Serial.println( touchY );
  // }
}

void lvgl_user_init(void)
{
  lv_init();
  
  /*Set the touchscreen calibration data,
    the actual data for your display can be acquired using
    the Generic -> Touch_calibrate example from the TFT_eSPI library*/
  // uint16_t calData[5] = { 275, 3620, 264, 3532, 1 };
  // tft.setTouch( calData );
  
  lv_color_t* buf1 = (lv_color_t*) heap_caps_malloc(240 * 240, MALLOC_CAP_SPIRAM);
  // lv_color_t* buf2 = (lv_color_t*) heap_caps_malloc(240 * 240, MALLOC_CAP_SPIRAM);
  lv_disp_draw_buf_init( &draw_buf, buf1, NULL, 240 * 240);

  /*Initialize the display*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init( &disp_drv );
  /*Change the following line to your display resolution*/
  disp_drv.hor_res = 240;
  disp_drv.ver_res = 240;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.full_refresh = 1;
  disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register(&disp_drv);

  /*Initialize the (dummy) input device driver*/
  static lv_indev_drv_t indev_drv;
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = my_touchpad_read;
  lv_indev_drv_register(&indev_drv);

  /*Get lvgl version*/
  String LVGL_Arduino = "Hello LVGL! ";
  LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch(); // version
  lv_obj_t *label = lv_label_create(lv_scr_act());
  lv_label_set_text(label, LVGL_Arduino.c_str());
  lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); //display
}

void setup() 
{
  Serial.begin(115200);
  tft.begin();
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);

  lvgl_user_init();
}

void loop()
{
  lv_timer_handler(); /* let the GUI do its work */
  delay(5);
}

測(cè)試結(jié)果:
代碼正常運(yùn)行,調(diào)用lvgl的文本控件,打印lvgl的版本號(hào)。
在這里插入圖片描述

結(jié)束語

我這里只是舉了一個(gè)簡(jiǎn)單的例子講解如何搭建lvgl的環(huán)境,實(shí)際上lvgl還有很多的控件和功能,也有一些demo可以運(yùn)行測(cè)試,這些就留給你們繼續(xù)探索了。如果還有什么問題,歡迎在評(píng)論區(qū)留言。

完整工程源碼下載鏈接

想了解更多Arduino的內(nèi)容,可以關(guān)注一下博主,后續(xù)我還會(huì)繼續(xù)分享更多的經(jīng)驗(yàn)給大家。
基于Arduino的開發(fā)教程匯總:
https://blog.csdn.net/ShenZhen_zixian/article/details/121659482

如果這篇文章能夠幫到你,就…你懂得。

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
JST01TMAC1CY5GE2 1 Viavi Solutions Inc Transceiver,
暫無數(shù)據(jù) 查看
6N137-X007T 1 Vishay Intertechnologies Optocoupler Logic-Out Open Collector DC-IN 1-CH 8-Pin PDIP SMD T/R

ECAD模型

下載ECAD模型
$2.22 查看
TJA1055T/3/CM,118 1 NXP Semiconductors TJA1055 - Enhanced fault-tolerant CAN transceiver SOIC 14-Pin

ECAD模型

下載ECAD模型
$1.95 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜