首先是如何配置好vgl在ArduinoIDE环境,可以参考Arduino — LVGL documentationhttps://docs.lvgl.io/master/get-started/platforms/arduino.html#get-the-lvgl-arduino-library
触摸板的ESP32配置选择ESP32S3 Dev module:其配置需要参照下面文档进行调整:
Sunton ESP32-S3 4.3 inch 800*400 IPS with Touch - Makerfabs Wiki
ArduinoIDE中需要下载的库“GFX_Library_for_Arduino”,“lvgl”,“TFT_eSPI”,“TAMC_GT911”
本文的lvgl型号在TFT_eSPI函数中找不到配置,所以不需要开启。
只需要将通过“SquareLine_Studio_1.3.0_Setup”软件配置好的界面并输出的函数,放置在链接:
https://pan.baidu.com/s/1thKSFWSKnEtGQOKIohUy6A?pwd=8888
提取码:8888
下载好的这个文件夹中,将用“SquareLine_Studio_1.3.0_Setup” 软件输出的文件的具体放置位置是将输出的“SquareLine_Project”文件放置到“Sunton_ESP32-8048S043-liu”的“src”文件夹中,再将“sketch_jul30a”文件夹中的“lvgl_conf.h”和“touch.h”文件放置到ui.ino文件旁边,修改ui文件夹中src文件夹中的“ui.c”文件。布局如下:
当将文件和函数的位置弄好后,需要最重要的一步就是将sketch_jul30a文件夹中的“sketch_jul30a.ino”里面,void setup()上面的函数全部复制,替代“ui.ino”里面对应的函数部分,同时将多余的自定义变量删除,同时将touch、TFT、GFX初始化函数写入值setup中,请参考以下主函数代码:
注意:将原来的“#include <ui.h>”改为“#include "src/ui.h""
#include <lvgl.h>
#include <TFT_eSPI.h>
#include "src/ui.h"
/*Don't forget to set Sketchbook location in File/Preferencesto the path of your UI project (the parent foder of this INO file)*/
/*Change to your screen resolution*/
static const uint16_t screenWidth = 800;
static const uint16_t screenHeight = 480;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[ screenWidth * screenHeight / 10 ];
#define pin0 17
#define pin1 18
TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */
#if LV_USE_LOG != 0
/* Serial debugging */
void my_print(const char * buf)
{
Serial.printf(buf);
Serial.flush();
}
#endif
/*******************************************************************************
* LVGL Widgets
* This is a widgets demo for LVGL - Light and Versatile Graphics Library
* import from: https://github.com/lvgl/lv_demos.git
*
* This was created from the project here
* https://www.makerfabs.com/sunton-esp32-s3-4-3-inch-ips-with-touch.html
*
* Dependent libraries:
* LVGL: https://github.com/lvgl/lvgl.git
* Touch libraries:
* FT6X36: https://github.com/strange-v/FT6X36.git
* GT911: https://github.com/TAMCTec/gt911-arduino.git
* XPT2046: https://github.com/PaulStoffregen/XPT2046_Touchscreen.git
*
* LVGL Configuration file:
* Copy your_arduino_path/libraries/lvgl/lv_conf_template.h
* to your_arduino_path/libraries/lv_conf.h
* Then find and set:
* #define LV_COLOR_DEPTH 16
* #define LV_TICK_CUSTOM 1
*
* For SPI display set color swap can be faster, parallel screen don't set!
* #define LV_COLOR_16_SWAP 1
*
* Optional: Show CPU usage and FPS count
* #define LV_USE_PERF_MONITOR 1
******************************************************************************/
//#include "lv_demo_widgets.h"
#include <demos/lv_demos.h>
/*******************************************************************************
******************************************************************************/
#include <Arduino_GFX_Library.h>
#define TFT_BL 2
#define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */
);
// ST7262 IPS LCD 800x480
Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
bus,
800 /* width */, 0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 8 /* hsync_back_porch */,
480 /* height */, 0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 8 /* vsync_back_porch */,
1 /* pclk_active_neg */, 14000000 /* prefer_speed */, true /* auto_flush */);
#include "touch.h"
/* Change to your screen resolution */
static lv_disp_drv_t disp_drv;
/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, 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);
#if (LV_COLOR_16_SWAP != 0)
gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif
lv_disp_flush_ready(disp);
}
void my_touchpad_read(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
if (touch_has_signal())
{
if (touch_touched())
{
data->state = LV_INDEV_STATE_PR;
/*Set the coordinates*/
data->point.x = touch_last_x;
data->point.y = touch_last_y;
}
else if (touch_released())
{
data->state = LV_INDEV_STATE_REL;
}
}
else
{
data->state = LV_INDEV_STATE_REL;
}
}
void openleft(void)
{
if(lv_obj_has_state(ui_Switchopenleft, LV_STATE_CHECKED)==1) // 返回 bool 类型, 开-1 ; 关-2
{
pinMode(pin0,OUTPUT);
digitalWrite(pin0,HIGH);
}
}
void openright(void)
{
if(lv_obj_has_state(ui_Switchopenright, LV_STATE_CHECKED)==1) // 返回 bool 类型, 开-1 ; 关-2
{
pinMode(pin1,OUTPUT);
digitalWrite(pin1,HIGH);
}
}
void brakeleft(void)
{
if(lv_obj_has_state(ui_Switchbrakeleft, LV_STATE_CHECKED)==1) // 返回 bool 类型, 开-1 ; 关-2
{
pinMode(pin0,OUTPUT);
digitalWrite(pin0,LOW);
}
}
void brakeright(void)
{
if(lv_obj_has_state(ui_Switchbrakeright, LV_STATE_CHECKED)==1) // 返回 bool 类型, 开-1 ; 关-2
{
pinMode(pin1,OUTPUT);
digitalWrite(pin1,LOW);
}
}
void setup()
{
Serial.begin( 115200 ); /* prepare for possible serial debug */
gfx->begin();
#ifdef TFT_BL
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH);
#endif
String LVGL_Arduino = "Hello Arduino! ";
LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();
Serial.println( LVGL_Arduino );
Serial.println( "I am LVGL_Arduino" );
lv_init();
delay(10);
touch_init();
#if LV_USE_LOG != 0
lv_log_register_print_cb( my_print ); /* register print function for debugging */
#endif
tft.begin(); /* TFT init */
tft.setRotation( 3 ); /* Landscape orientation, flipped */
lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * screenHeight / 10 );
/*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 = screenWidth;
disp_drv.ver_res = screenHeight;
disp_drv.flush_cb = my_disp_flush;
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 );
ui_init();
Serial.println( "Setup done" );
openleft();
openright();
brakeleft();
brakeright();
}
void loop()
{
lv_timer_handler(); /* let the GUI do its work */
delay(5);
}
以下列出的是一些模块代码:
开关函数可以参考
LVGL学习笔记17 - 开关Switch_lvgl switch_pq113_6的博客-CSDN博客
滑块函数可以参考:
按钮模块函数可以参考:
lvgl-按钮学习篇(三)_lvgl 按钮_无为扫地僧的博客-CSDN博客
标签函数请参考:
ESP32开发路程LVGL篇(四)——常用函数介绍,屏幕、标签_lvgl 设置背景色-CSDN博客
这些函数的调用需要在ui.c文件中调用,调用前,如果需要做一些改动,清先到“screen.h”文件中,看看你需要修改的模块是否有重合的命令。本文的ui.c代码:
// This file was generated by SquareLine Studio
// SquareLine Studio version: SquareLine Studio 1.3.0
// LVGL version: 8.3.6
// Project name: SquareLine_Project
#include "ui.h"
#include "ui_helpers.h"
/ VARIABLES
// SCREEN: ui_Screen1
void ui_Screen1_screen_init(void);
void ui_event_Screen1(lv_event_t * e);
lv_obj_t * ui_Screen1;
lv_obj_t * ui_Left;
lv_obj_t * ui_Right;
lv_obj_t * ui_Switchopenleft;
lv_obj_t * ui_Label1;
lv_obj_t * ui_Switchopenright;
lv_obj_t * ui_Label2;
lv_obj_t * ui_Switchbrakeleft;
lv_obj_t * ui_Switchbrakeright;
lv_obj_t * ui_Leftslide;
lv_obj_t * ui_Rightslide;
lv_obj_t * ui_Label3;
lv_obj_t * ui_Label4;
lv_obj_t * ui_Label5;
lv_obj_t * ui_Label6;
lv_obj_t * ui_Label8;
lv_obj_t * ui_Stop;
lv_obj_t * ui_Label10;
lv_obj_t * ui_Label9;
lv_obj_t * ui_Image1;
lv_obj_t * ui_Label12;
lv_obj_t * ui_Label11;
lv_obj_t * ui_Label7;
lv_obj_t * ui_Label13;
lv_obj_t * ui_Label14;
lv_obj_t * ui_Leftspeed;
lv_obj_t * ui_Rightspeed;
lv_obj_t * ui_Label16;
lv_obj_t * ui_Label15;
lv_obj_t * ui____initial_actions0;
const lv_img_dsc_t * ui_imgset_337415967[1] = {&ui_img_1806934165};
const lv_img_dsc_t * ui_imgset_392147749[3] = {&ui_img_999838862, &ui_img_355854617, &ui_img_1807947869};
/ TEST LVGL SETTINGS
#if LV_COLOR_DEPTH != 32
#endif
#if LV_COLOR_16_SWAP !=0
#error "LV_COLOR_16_SWAP should be 0 to match SquareLine Studio's settings"
#endif
/ ANIMATIONS
/ FUNCTIONS
void ui_event_Screen1(lv_event_t * e)
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t * target = lv_event_get_target(e);
if(event_code == LV_EVENT_CLICKED) {
(e);
}
}
//brake开关
void ui_event_Switchbrakeleft(lv_event_t * e)//左制动
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t * target = lv_event_get_target(e);
if(event_code == LV_EVENT_VALUE_CHANGED)
{
if(lv_obj_has_state(target,LV_STATE_CHECKED) == true )
{
lv_obj_add_state(target, LV_STATE_CHECKED);//将brake设为开状态,此时的open失效,滑块为0
lv_obj_add_state(ui_Switchopenleft, LV_STATE_DISABLED);
lv_slider_set_value(ui_Leftslide,000,LV_ANIM_ON);
lv_label_set_text_fmt(ui_Leftspeed,"%s","OFF");
}
else{lv_obj_clear_state(target, LV_STATE_CHECKED);//将brake设为关状态,此时open生效
lv_obj_clear_state(ui_Switchopenleft, LV_STATE_DISABLED);}
}
}
void ui_switchbrakeleft()
{
lv_obj_clear_state(ui_Switchbrakeleft, LV_STATE_CHECKED);//brake初始值为关闭
lv_obj_add_event_cb(ui_Switchbrakeleft,ui_event_Switchbrakeleft,LV_EVENT_VALUE_CHANGED,NULL);
}
//brake开关
void ui_event_Switchbrakeright(lv_event_t * e)//右制动
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t * target = lv_event_get_target(e);
if(event_code == LV_EVENT_VALUE_CHANGED)
{
if(lv_obj_has_state(target,LV_STATE_CHECKED) == true )
{
lv_obj_add_state(target, LV_STATE_CHECKED);//将brake设为开状态,此时的open失效,滑块为0
lv_obj_add_state(ui_Switchopenright, LV_STATE_DISABLED);
lv_slider_set_value(ui_Rightslide,000,LV_ANIM_ON);
lv_label_set_text_fmt(ui_Rightspeed,"%s","OFF");
}
else{lv_obj_clear_state(target, LV_STATE_CHECKED);//将brake设为关状态,此时open生效
lv_obj_clear_state(ui_Switchopenright, LV_STATE_DISABLED);}
}
}
void ui_switchbrakeright()
{
lv_obj_clear_state(ui_Switchbrakeright, LV_STATE_CHECKED);//brake初始值为关闭
lv_obj_add_event_cb(ui_Switchbrakeright,ui_event_Switchbrakeright,LV_EVENT_VALUE_CHANGED,NULL);
}
//open开关
void ui_event_leftopenswitch(lv_event_t * e) //左开关
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t * target = lv_event_get_target(e);
if(event_code == LV_EVENT_VALUE_CHANGED)
{
if(lv_obj_has_state(target,LV_STATE_CHECKED) == 1 )
{
lv_obj_add_state(target, LV_STATE_CHECKED);
ui_slideleftspeed();
lv_obj_clear_state(ui_Switchbrakeleft, LV_STATE_DISABLED);
}
if(lv_obj_has_state(target,LV_STATE_CHECKED) == 0){
lv_obj_add_state(ui_Switchbrakeleft, LV_STATE_DISABLED);
lv_obj_clear_state(target, LV_STATE_CHECKED);
lv_slider_set_value(ui_Leftslide,000,LV_ANIM_ON);
lv_label_set_text_fmt(ui_Leftspeed,"%s","OFF");
}
}
}
void ui_leftopenswitch(void)
{
lv_obj_add_state(ui_Switchopenleft, LV_STATE_CHECKED); // 开
ui_slideleftspeed();
lv_obj_add_event_cb(ui_Switchopenleft,ui_event_leftopenswitch,LV_EVENT_VALUE_CHANGED,NULL);
}
void ui_event_rightopenswitch(lv_event_t * e) //右开关
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t * target = lv_event_get_target(e);
if(event_code == LV_EVENT_VALUE_CHANGED)
{
if(lv_obj_has_state(target,LV_STATE_CHECKED) == 0 )
{
lv_obj_add_state(ui_Switchbrakeright, LV_STATE_DISABLED);
lv_obj_clear_state(target, LV_STATE_CHECKED);
lv_slider_set_value(ui_Rightslide,000,LV_ANIM_ON);
lv_label_set_text_fmt(ui_Rightspeed,"%s","OFF");
}
if(lv_obj_has_state(target,LV_STATE_CHECKED) == 1){
lv_obj_clear_state(ui_Switchbrakeright, LV_STATE_DISABLED);
lv_obj_add_state(target, LV_STATE_CHECKED);
ui_sliderightspeed();}
}
}
void ui_rightopenswitch(void)
{
lv_obj_add_state(ui_Switchopenright, LV_STATE_CHECKED); // 开
ui_sliderightspeed();
lv_obj_add_event_cb(ui_Switchopenright,ui_event_rightopenswitch,LV_EVENT_VALUE_CHANGED,NULL);
}
//按钮stop
void ui_event_stop(lv_event_t * e)
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t * target = lv_event_get_target(e);
if(event_code == LV_EVENT_PRESSED) {
lv_slider_set_value(ui_Leftslide,000,LV_ANIM_ON);
lv_label_set_text_fmt(ui_Leftspeed,"%s","OFF");
lv_slider_set_value(ui_Rightslide,000,LV_ANIM_ON);
lv_label_set_text_fmt(ui_Rightspeed,"%s","OFF");
}
}
void ui_stop(void)
{
lv_obj_add_event_cb(ui_Stop,ui_event_stop,LV_EVENT_PRESSED,NULL);
}
//滑块部分
void ui_slideleftspeed(void) //左滑块初始值,范围设置
{
lv_slider_set_value(ui_Leftslide,000,LV_ANIM_OFF);
lv_slider_set_range(ui_Leftslide, 0, 800); // 设置滑块值的变化范围0-800
lv_obj_add_event_cb(ui_Leftslide, ui_event_receive_left, LV_EVENT_VALUE_CHANGED, NULL);
}
void ui_sliderightspeed(void) //右滑块初始值,范围设置
{
lv_slider_set_value(ui_Rightslide,000,LV_ANIM_OFF);
lv_slider_set_range(ui_Rightslide, 0, 800); // 设置滑块值的变化范围0-800
lv_obj_add_event_cb(ui_Rightslide, ui_event_receive_right, LV_EVENT_VALUE_CHANGED,NULL);
}
void ui_event_receive_left(lv_event_t *e) //左滑块标签数据显示
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t *target = lv_event_get_target(e);
if(event_code == LV_EVENT_VALUE_CHANGED)
{
if(lv_obj_has_state(ui_Switchopenleft,LV_STATE_CHECKED) == 1)
{
if(lv_obj_has_state(ui_Switchbrakeleft,LV_STATE_CHECKED) == 0 )
{
lv_label_set_text_fmt(ui_Leftspeed,"%d",lv_slider_get_value(target));
}
}
}
}
void ui_event_receive_right(lv_event_t *e) //右滑块标签数据显示
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t *target = lv_event_get_target(e);
if(event_code == LV_EVENT_VALUE_CHANGED)
{
if(lv_obj_has_state(ui_Switchopenright,LV_STATE_CHECKED) == 1)
{
if(lv_obj_has_state(ui_Switchbrakeright,LV_STATE_CHECKED) == 0 )
{
lv_label_set_text_fmt(ui_Rightspeed,"%d",lv_slider_get_value(target));
}
}
}
}
void ui_event_speedback(void)
{
lv_label_set_text_fmt(ui_Label16,"%d",50);
lv_label_set_text_fmt(ui_Label15,"%d",300);
}
/ SCREENS
void ui_init(void)
{
lv_disp_t * dispp = lv_disp_get_default();
lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED),
false, LV_FONT_DEFAULT);
lv_disp_set_theme(dispp, theme);
ui_Screen1_screen_init();
ui____initial_actions0 = lv_obj_create(NULL);
lv_disp_load_scr(ui_Screen1);
ui_event_speedback();
ui_stop();
ui_leftopenswitch();
ui_rightopenswitch();
ui_switchbrakeleft();
ui_switchbrakeright();
}
切记一定要将前面写好的函数放在ui_init()函数里。
“screen.c”文件可能会出现报错,一个是字体只能用默认值14,全部改为“&lv_font_montserrat_14”所以改过来就好了。
“ui.c”文件也有一个坑,就是“LV_COLOR_DEPTH|=32”下面的“ERROR”部分删除就行了。
写好之后,需要单独引用的函数一定要放在ui.h头文件中声明,然后再调用到主函数中