gui guider生成的代码无人工修改移植esp32 实现拖曳式傻瓜生成嵌入式图形界面 及platform include 路径踩坑记
既然有了gui guider这么方便的东西,肯定想移植到实际的esp32单片机上 就不用手敲代码去写widget了
main.cpp改造
lvgl自带的arduino例子写的比较随性 东一坨西一坨的 想理解害的人脑编译下
参考guider的模拟器main.c
我自己改造的主程序,如果只是跑GUI的话,以下代码不需要任何更改。甚至如果自定义的代码都写到custom.h,custom.c里,完全可以main不动。里边的串口调试部分不需要的话可以注释掉。
#include <lvgl.h> #include <TFT_eSPI.h> #include "gui_guider.h" #include "events_init.h" #include "custom.h" //定义分辨率 static const uint16_t screenWidth = 480; static const uint16_t screenHeight = 320; //定义缓冲 static lv_disp_draw_buf_t draw_buf; static lv_color_t buf[ screenWidth * 10 ]; 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 /* Display flushing 显示填充 与LCD驱动关联*/ 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 ); 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 ); } /*Read the touchpad*/ /*输入设备,读取触摸板*/ void my_touchpad_read( lv_indev_drv_t * indev_driver, 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 tft_init() { tft.begin(); /* TFT init TFT初始化*/ tft.setRotation( 1 ); /* Landscape orientation, flipped 设置方向*/ /*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*/ /*设置触摸屏校准数据, 可以使用获取显示的实际数据 TFT_eSPI 库中的 Generic -> Touch_calibrate 示例*/ uint16_t calData[5] = { 187, 3596, 387, 3256, 5 }; tft.setTouch( calData ); } void lvgl_setup() { lv_init(); #if LV_USE_LOG != 0 lv_log_register_print_cb( my_print ); /* register print function for debugging 注册打印功能以进行调试*/ #endif lv_disp_draw_buf_init( &draw_buf, buf, NULL, screenWidth * 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 ); } lv_ui guider_ui;//结构体包含所有屏幕与部件,必不可少,且不能放到setup里 。使用该指针可以找到程序里任何对象 void setup() { Serial.begin( 115200 ); /* prepare for possible serial debug 为可能的串行调试做准备*/ tft_init(); lvgl_setup(); /*Create a GUI-Guider app */ setup_ui(&guider_ui);// events_init(&guider_ui);//事件初始化 custom_init(&guider_ui);//运行自定义代码,例如将实际输出跟gui显示的数值关联起来 Serial.println( "Setup done" ); } void loop() { lv_timer_handler(); /* let the GUI do its work 让 GUI 完成它的工作 */ delay( 5 ); }
把自动生成的代码文件复制到pio工程里
移植需要gui guider生成的custom 跟generated文件夹
因为pio默认的编译路径问题,如果直接把custom 跟generated文件夹复制到src文件夹里 会报编译找不到文件 。这里复习一下#include 的作用 。#include就是把后边写的什么。c.。h文件原模原样复制进来(这也是java 等使用import的语言在倒库文件比c快的多的原因)<> 跟"" 的区别是 使用尖括号< >
和双引号" "
的区别在于头文件的搜索路径不同:
使用尖括号< >
,编译器会到系统路径下查找头文件 而使用双引号" "
,编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找。
然而pio的系统路径如果不设置的话并没有那么简单就能用,我试了把俩文件夹放到src,放到include,放到lib 都会报错。
最简单粗暴的解决办法 把自动生成的每个文件都放到src里 就像这样 ,虽然不方便也不好看,注意需要把lv-font。h也考进来
虽然不完美,但是可以跑起来了(当然首先确保lvgl自带的例子跟guiguider的模拟器都运行正常)
7.97 xSL:/ gui guider实现拖曳式画界面移植esp32单片机,不写一行代码# 单片机开发 # esp32 https://v.douyin.com/j9x7j5U/ 复制此链接,打开Dou音搜索,直接观看视频!
开始改造程序,目标是main程序不动,gui guider生成的文件夹直接复制过来就能编译下载
参考这位大神的方法 platformio随意添加文件夹和文件JSON文件和INI文件配置 – 走着的博客 (openpilot.cc)
文件夹结构 ,在lib下再建一个文件夹 新建一个library,json文件 相当于自己建了个库。 并把lvlgl库里的lv_font.拷贝过来(我试图修改json文件想不拷贝lv-font文件,没有成功)
library.json文件全文。flag那些 -I的的 都是在给gcc编译器加参数
{ "name": "BLTGUI", "keywords": "bltgui", "description": "bltgui des", "version": "1.0", "authors": { "name": "lb" }, "licence": "MIT", "frameworks": "arduino", "platforms": "espressif32", "build" : { "unflags": "-std=gnu++11", "flags": [ "-std=c99", "-I custom", "-I generated", "-I generated/guider_customer_fonts", "-I generated/guider_fonts", "-I generated/images" ], "srcFilter": [ "+<*.c>", "+<custom/*.c>", "+<generated/*.c>", "+<generated/guider_customer_fonts/*.c>", "+<generated/guider_fonts/*.c>", "+<generated/images/*.c>" ] } }
测试编译成功
再修改,原来这些 -I 还有顺序 必选先提前引用
不想拷贝lv_font。h文件 ,万一库文件升级了,guiguider用的还是旧文件。
先尝试加入绝对路径 "-I C:/Users/kyo/Documents/PlatformIO/Projects/Esp32-espi-lvgl/.pio/libdeps/esp32dev/lvgl/src/font", 可以运行 。但是别人用就得改路径
尝试 相对路径 ” .pio\libdeps\esp32dev\lvgl\src\font“ 找不到h文件 这里继续复习 ../的意思
/
是指根目录:就是所有目录最顶层的目录。
./
表示当前目录,./ 一般需要和其他文件夹或者文件结合使用,指代当前目录下的东西。
1 2 | cd . 没有太多意义 cd ./文件夹 切换到当前目录的某个文件夹 |
..
表示上级目录
原来json的路径都是跟自己同级的
这里使用相对路径
"-I ../../.pio/libdeps/esp32dev/lvgl/src/font",
用两个../往上跳两个目录 测试正常
最终版本 吐槽下json居然不能加注释
{ "name": "BLTGUI", "keywords": "bltgui", "description": "bltgui des", "version": "1.0", "authors": { "name": "lb" }, "licence": "MIT", "frameworks": "arduino", "platforms": "espressif32", "build" : { "unflags": "-std=gnu++11", "flags": [ "-std=c99", "-I ../../.pio/libdeps/esp32dev/lvgl/src/font", "-I custom", "-I generated", "-I generated/guider_customer_fonts", "-I generated/guider_fonts", "-I generated/images" ], "srcFilter": [ "+<*.c>", "+<custom/*.c>", "+<generated/*.c>", "+<generated/guider_customer_fonts/*.c>", "+<generated/guider_fonts/*.c>", "+<generated/images/*.c>" ] } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升