1. 这不是“跑个LVGL”那么简单RK3566泰山派上手前必须看清的三重现实你搜到“手把手教你用RK3566泰山派开发板跑LVGL”点进来大概率是刚拆开那块带金属散热片、印着“Taishan Pi”字样的蓝色开发板手边还堆着USB转TTL线、HDMI线、一块7英寸LVDS屏甚至可能已经烧好了官方Ubuntu镜像——但一打开终端敲lvgl_demo_widgets屏幕要么黑着要么花屏要么直接卡死。别急着骂板子、骂文档、骂自己手残。我用RK3566泰山派做了整整11个月的工业HMI项目从第一版LVGL 8.2跑在裸机上到最终交付客户时稳定运行在LinuxWaylandLVGL 9.1组合下踩过的坑比你编译失败的次数还多。这根本不是“装个库、跑个demo”就能闭环的事。它是一条横跨硬件驱动适配、交叉编译链深度定制、图形栈底层协同、内存与DMA资源争抢的完整技术链。RK3566本身是Cortex-A55四核Mali-G52 GPU的SoC泰山派是国产小众但做工扎实的开发板LVGL是轻量级嵌入式GUI框架——三者叠加表面看是“嵌入式GUI入门”实际是嵌入式Linux图形开发里最硬的一块骨头。为什么因为LVGL在ARM平台上的性能瓶颈从来不在CPU算力而在显示控制器DCU与GPU之间的数据通路是否通畅、Framebuffer内存是否被正确映射、DMA传输是否被其他进程抢占。你看到的“花屏”可能是DCU配置参数和LVDS时序不匹配你遇到的“卡顿”大概率是LVGL渲染帧率被Linux内核调度器压低了优先级你改完代码却没生效十有八九是交叉编译工具链里libpng或freetype版本太老导致字体渲染模块静默失败。所以这篇不是教程是我在泰山派上把LVGL从“能亮”做到“稳如磐石”的实操笔记。核心关键词就四个RK3566、泰山派、LVGL、交叉编译——每一个词背后都藏着必须亲手拧紧的螺丝。适合谁不是纯新手而是已经能用make menuconfig配Linux内核、会写简单CMakeLists.txt、知道arm-linux-gnueabihf-gcc和aarch64-linux-gnu-gcc区别的人。如果你还在纠结“该选Qt还是LVGL”这篇文章会告诉你在RK3566这种资源受限但实时性要求高的场景下LVGL不是备选是唯一解。2. 为什么必须放弃“官方SDK一键编译”RK3566泰山派LVGL部署的底层逻辑重构2.1 官方SDK的温柔陷阱你以为的“开箱即用”其实是预设的性能天花板泰山派官方提供的SDK通常是基于Rockchip Linux SDK v2.2.x或v3.0.x里确实打包了LVGL demobuild.sh脚本执行后也能生成可执行文件./lvgl_demo_widgets一跑屏幕上真能出来按钮、滑块、图表。但这个“能跑”是高度阉割的。我第一次信了这个邪直接拿官方编译好的二进制丢进客户现场的设备结果连续运行72小时后触摸响应延迟从20ms飙升到300ms最后直接卡死。抓取dmesg日志才发现问题出在官方SDK默认启用的DRM/KMS显示后端上。RK3566的DCUDisplay Control Unit在KMS模式下LVGL的flush_cb回调函数每次提交一帧都要触发一次完整的KMS原子提交atomic commit而这个过程涉及内核态锁竞争、GPU命令队列排队、以及framebuffer物理地址的反复重映射。实测下来官方SDK编译的LVGL demo在泰山派上最高帧率只有18fps且波动极大12~22fps。更致命的是KMS后端强制使用drmModeSetCrtc接口这会导致LVGL无法利用DCU的双缓冲机制画面撕裂几乎不可避免。这不是LVGL的问题是Rockchip官方SDK为了“兼容性”牺牲了“实时性”。所以第一步必须彻底抛弃官方SDK的LVGL构建路径从零开始搭建一条绕过KMS、直连DCU寄存器、由用户空间控制DMA传输的通道。这条路难但它是泰山派上LVGL真正发挥RK3566 Mali-G52 GPU潜力的唯一路径。2.2 真正的起点理解泰山派的显示硬件拓扑与LVGL后端选择泰山派的显示系统不是简单的“HDMI or LVDS”它的DCU支持三种输出模式RGB、LVDS、MIPI-DSI。而LVGL官方支持的后端只有三种Framebuffer、SDL2、DRM。Framebuffer后端最简单但性能最差——它只是把LVGL渲染的buffer memcpy到/dev/fb0完全不利用GPU加速SDL2后端需要X11或Wayland对泰山派这种工业场景属于过度设计DRM后端就是前面说的KMS陷阱。所以我的方案是自定义DCU后端 Mali-G52 GPU加速渲染。具体怎么做先看硬件拓扑泰山派的DCU通过AXI总线连接到SoC其寄存器基地址为0xff9e0000参考《RK3566 TRM》第12章LVDS PHY的配置寄存器在0xff9e8000。LVGL的lv_port_disp.c里flush_cb函数原本只是把buffer地址传给display driver现在我们要把它改成1将LVGL buffer地址转换为DCU DMA的物理地址2配置DCU的layer0为RGB888格式起始地址指向该物理地址3触发DCU的DMA传输使能位4等待VSYNC中断确认帧提交完成。这个过程绕过了整个Linux内核的显示子系统把DCU当成了一个纯粹的“画布搬运工”。而GPU加速部分则用Mali的OpenGLES 2.0 API在LVGL的lv_gpu_mali_gles.c里实现draw_rect、draw_img_decoded等函数让复杂图形比如圆角矩形、渐变填充由GPU计算再把结果写回同一块buffer。这样CPU只负责UI逻辑和事件分发GPU负责像素计算DCU负责像素搬运——三者流水线并行帧率轻松突破60fps。这个架构的代价是你必须自己写DCU寄存器配置代码必须处理物理地址映射必须确保buffer内存是cache一致的用__builtin_arm_dcache_clean和__builtin_arm_dcache_invalidate。但回报是系统负载降低40%触摸响应延迟稳定在15ms以内功耗下降22%实测数据。2.3 交叉编译链不是“选个工具链”而是“重建信任链”网络热词里反复出现“rk3566 android ch340”、“orangepi cm5安装qt5 交叉编译”说明很多人把交叉编译当成一个“下载、解压、配置PATH”的机械动作。但在RK3566泰山派上这是最危险的认知误区。我见过太多人用arm-linux-gnueabihf-gcc针对ARMv7去编译RK3566ARMv8-A的代码结果程序启动就segment fault也有人用Ubuntu 22.04自带的aarch64-linux-gnu-gcc版本11.2编译出来的LVGL链接时找不到clock_gettime符号——因为新版glibc默认用clock_gettimeGLIBC_2.17而泰山派烧录的Ubuntu rootfs里glibc是2.28但动态链接器ld-linux-aarch64.so.1却是2.27版本存在ABI不兼容。所以真正的交叉编译链必须是三件套严格匹配编译器gcc、C库glibc或musl、Linux内核头文件kernel headers。我的标准配置是aarch64-buildroot-linux-musl_gcc-10.3.0Buildroot 2021.02提供原因有三第一musl libc比glibc小60%启动更快内存占用更低这对LVGL这种内存敏感型框架至关重要第二Buildroot的toolchain是为嵌入式定制的所有组件版本经过验证不存在ABI错配第三它自带m4、autoconf、automake等构建工具能无缝编译LVGL依赖的libpng、freetype、libjpeg。你可能会问为什么不用Rockchip官方推荐的gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu因为它太老了——不支持ARMv8.2的CRC32指令而LVGL 9.x的lv_memset优化就依赖这个指令用老工具链编译性能损失15%。所以“交叉编译避坑指南”的第一课不是教你怎么写--sysroot而是教你怎么判断手里的工具链是否真的可信。3. 从零构建LVGL泰山派专用交叉编译环境搭建与核心参数调优3.1 工具链安装与验证三步确认法拒绝“假成功”很多教程让你wget一个tar包tar -xzf解压然后export PATH就完事。这在泰山派上是自杀行为。我用三步法验证工具链真实性第一步检查目标架构与ABI$ aarch64-buildroot-linux-musl-gcc -v # 输出中必须包含 # Target: aarch64-buildroot-linux-musl # Thread model: posix # gcc version 10.3.0 (Buildroot 2021.02) # 注意Target必须是aarch64不是arm-linux-gnueabihfversion必须是10.3.0不是7.5.0或11.2.0第二步验证C库兼容性# 编译一个极简测试程序 $ cat test.c EOF #include stdio.h #include time.h int main() { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, ts); printf(OK\n); return 0; } EOF $ aarch64-buildroot-linux-musl-gcc -o test test.c $ file test # 输出必须是test: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-aarch64.so.1 # 关键点interpreter必须是ld-musl-aarch64.so.1不是ld-linux-aarch64.so.1第三步实机运行验证# 将test可执行文件拷贝到泰山派假设IP 192.168.1.100 $ scp test root192.168.1.100:/tmp/ # 在泰山派上执行 $ ssh root192.168.1.100 /tmp/test # 必须输出OK且返回值为0。如果报错not found说明musl libc路径不对如果报错symbol not found说明glibc/musl混用。这三步缺一不可。我曾因跳过第二步用了一个Target为aarch64-linux-gnuglibc的工具链去编译musl环境的LVGL结果在泰山派上运行时lv_init()函数内部调用malloc失败整个UI初始化直接abortdebug花了两天才定位到工具链ABI错配。3.2 LVGL源码配置不是cmake .. make而是逐行修改lv_conf.hLVGL的配置不是靠CMake选项开关而是靠lv_conf.h里宏定义的精细调控。泰山派的资源限制决定了我们必须做减法内存管理关闭所有动态分配强制静态buffer#define LV_MEM_CUSTOM 1 // 启用自定义内存分配 // 在lv_port_disp.c里实现 void * lv_mem_alloc(uint32_t size) { return NULL; } // 禁用malloc void lv_mem_free(void * p) { } // 空实现 // 所有buffer必须静态声明 static uint8_t disp_buf1[240 * 320 * 4]; // 320x240 RGB888 buffer static lv_disp_draw_buf_t draw_buf1; lv_disp_draw_buf_init(draw_buf1, disp_buf1, NULL, sizeof(disp_buf1)/4);理由泰山派DDR带宽有限频繁malloc/free会引发内存碎片LVGL的lv_mem_buf在高帧率下容易耗尽。静态buffer虽然占内存但确定性强。渲染优化启用GPU加速禁用软件抗锯齿#define LV_USE_GPU_MALI_GLES 1 // 启用Mali GPU后端 #define LV_ANTIALIAS 0 // 关闭全局抗锯齿GPU已处理 #define LV_DRAW_COMPLEX 1 // 启用复杂图形GPU渲染 #define LV_IMG_CACHE_DEF_SIZE 0 // 关闭图片缓存内存紧张注意LV_USE_GPU_MALI_GLES必须配合Mali用户空间驱动libmali使用不能只编译LVGL就完事。输入设备精简触摸校准流程#define LV_INDEV_DEF_READ_PERIOD 10 // 触摸读取周期10ms非50ms #define LV_INDEV_DEF_TRANSPORT_TYPE LV_INDEV_TRANSPORT_TYPE_POINTER // 屏幕尺寸必须精确匹配LVDS屏规格 #define LV_HOR_RES_MAX 1024 #define LV_VER_RES_MAX 600泰山派常用7英寸LVDS屏分辨率为1024x600LV_HOR_RES_MAX必须设为此值否则LVGL的坐标系会错乱触摸点偏移。3.3 依赖库交叉编译libpng、freetype、libjpeg的版本锁死策略LVGL的字体渲染、图片解码依赖这三个库但它们的交叉编译极易出错。我的经验是版本锁死 补丁注入。libpng 1.6.37必须用1.6.x1.7.x移除了png_set_gray_1_2_4_to_8LVGL 9.x仍依赖此函数./configure --hostaarch64-buildroot-linux-musl \ --prefix/opt/rk3566-toolchain/sysroot \ --disable-shared \ --enable-static \ ac_cv_lib_z_compressyes \ ZLIB_LIBS-L/opt/rk3566-toolchain/sysroot/lib -lz \ ZLIB_CFLAGS-I/opt/rk3566-toolchain/sysroot/include make make install关键点ac_cv_lib_z_compressyes是必须的否则configure会误判zlib不可用。freetype 2.10.42.11.x引入了FT_Face_GetCharVariantIndexLVGL未适配./configure --hostaarch64-buildroot-linux-musl \ --prefix/opt/rk3566-toolchain/sysroot \ --without-harfbuzz \ --without-bzip2 \ --without-png \ --without-zlib \ --enable-static \ --disable-shared--without-png和--without-zlib是重点避免与libpng/zlib版本冲突。libjpeg 9d不是9e9e移除了jpeg_mem_srcLVGL的jpg解码器需要它./configure --hostaarch64-buildroot-linux-musl \ --prefix/opt/rk3566-toolchain/sysroot \ --enable-static \ --disable-shared编译完成后必须将/opt/rk3566-toolchain/sysroot/lib下的.a文件和/opt/rk3566-toolchain/sysroot/include下的头文件完整复制到LVGL源码的libs目录下并在CMakeLists.txt中显式指定target_include_directories(lvgl PRIVATE ${CMAKE_SOURCE_DIR}/libs/freetype/include) target_link_libraries(lvgl PRIVATE ${CMAKE_SOURCE_DIR}/libs/freetype/lib/libfreetype.a)这样做的好处是避免系统级pkg-config干扰确保LVGL链接的是我们交叉编译的、版本锁定的库。4. 实操全流程从泰山派烧录到LVGL demo稳定运行的七步落地4.1 硬件准备与固件烧录避开“救砖”雷区的第一道防线泰山派的烧录不是插上USB线就能刷。它的BootROM只识别特定格式的boot.img且必须通过rkdeveloptool不是rkflashtool烧录。步骤如下进入Loader模式断电按住板载RECOVERY键插入USB-C线到电脑再上电。此时lsusb应看到ID 2207:350a Rockchip Semiconductor Co., Ltd。下载正确固件不要用Rockchip官网的通用固件。泰山派有自己定制的uboot和trust镜像必须从泰山派官网下载TaishanPi_RK3566_Ubuntu20.04_V1.2.img日期20230815。烧录命令# 解压固件 $ unzip TaishanPi_RK3566_Ubuntu20.04_V1.2.img.zip # 使用rkdeveloptool烧录必须是v3.6 $ sudo rkdeveloptool db rk3566_loader_v1.14.112.bin # 下载loader $ sudo rkdeveloptool wl 0 TaishanPi_RK3566_Ubuntu20.04_V1.2.img # 写入整盘 $ sudo rkdeveloptool rd # 重启常见错误用rkflashtool会报错ERROR: Failed to init usb device用旧版rkdeveloptoolv3.5烧录后板子无法启动表现为红灯常亮——这就是“救砖”场景的起点。我救过3块板子都是因为用了错误工具。4.2 开发环境搭建在Ubuntu 20.04虚拟机中构建纯净交叉编译环境我坚持用Ubuntu 20.04非22.04作为宿主机因为泰山派官方rootfs基于20.04glibc ABI一致。环境搭建步骤安装基础工具sudo apt update sudo apt install -y git build-essential python3-pip wget curl vim创建隔离工作区mkdir -p ~/rk3566-dev/{toolchain,lvgl,build} cd ~/rk3566-dev下载并安装Buildroot工具链wget https://buildroot.org/downloads/buildroot-2021.02.tar.gz tar -xzf buildroot-2021.02.tar.gz cd buildroot-2021.02 make menuconfig # 进入Toolchain → C library → musl # 进入Toolchain → Toolchain type → External toolchain # 进入Toolchain → Toolchain origin → Download toolchain from the web # 保存退出执行make all # 工具链会生成在 output/host/ 目录下软链接到统一路径ln -sf ~/rk3566-dev/buildroot-2021.02/output/host/ ~/rk3566-dev/toolchain export PATH$HOME/rk3566-dev/toolchain/bin:$PATH这样做的好处是所有后续编译都基于Buildroot验证过的工具链杜绝版本混乱。4.3 LVGL源码编译与部署CMake配置的魔鬼细节LVGL官方CMakeLists.txt对交叉编译支持不完善必须手动补全。我的CMakeLists.txt关键片段cmake_minimum_required(VERSION 3.10) project(lvgl-demo LANGUAGES C) # 交叉编译设置 set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-buildroot-linux-musl-gcc) set(CMAKE_CXX_COMPILER aarch64-buildroot-linux-musl-g) # sysroot路径必须 set(CMAKE_SYSROOT /opt/rk3566-toolchain/sysroot) set(CMAKE_FIND_ROOT_PATH /opt/rk3566-toolchain/sysroot) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # LVGL配置 add_subdirectory(lvgl) target_compile_definitions(lvgl PRIVATE LV_CONF_INCLUDE_SIMPLE) target_include_directories(lvgl PRIVATE ${CMAKE_SOURCE_DIR}/lv_conf.h) # 链接依赖 target_link_libraries(lvgl PRIVATE ${CMAKE_SOURCE_DIR}/libs/freetype/lib/libfreetype.a ${CMAKE_SOURCE_DIR}/libs/libpng/lib/libpng.a ${CMAKE_SOURCE_DIR}/libs/libjpeg/lib/libjpeg.a m dl rt pthread ) # 可执行文件 add_executable(lvgl-demo main.c) target_link_libraries(lvgl-demo PRIVATE lvgl)关键点在于CMAKE_FIND_ROOT_PATH_MODE_*的设置PROGRAM设为NEVER表示不搜索宿主机的可执行文件LIBRARY和INCLUDE设为ONLY强制只在sysroot下找库和头文件。漏掉这一项CMake会错误地链接宿主机的glibc导致运行时报错。4.4 DCU后端实现128行寄存器操作代码详解lv_port_disp.c是LVGL移植的核心。我的DCU后端代码精简版#include lvgl.h #include sys/mman.h #include fcntl.h #include unistd.h #define DCU_BASE 0xff9e0000 #define LVDS_PHY_BASE 0xff9e8000 static int dcu_fd -1; static void *dcu_map NULL; static void dcu_init(void) { dcu_fd open(/dev/mem, O_RDWR | O_SYNC); if (dcu_fd 0) { LV_LOG_ERROR(Failed to open /dev/mem); return; } dcu_map mmap(NULL, 0x10000, PROT_READ | PROT_WRITE, MAP_SHARED, dcu_fd, DCU_BASE); if (dcu_map MAP_FAILED) { LV_LOG_ERROR(Failed to mmap DCU); close(dcu_fd); return; } // 配置DCU layer0为RGB888buffer地址为0x80000000DDR起始 *(volatile uint32_t*)(dcu_map 0x100) 0x80000000; // LAYER0_ADDR *(volatile uint32_t*)(dcu_map 0x104) 1024; // LAYER0_PITCH *(volatile uint32_t*)(dcu_map 0x108) 0x00000000; // LAYER0_CTRL (RGB888, enable) *(volatile uint32_t*)(dcu_map 0x10c) 0x00000000; // LAYER0_SIZE (1024x600) } static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { // 1. 清理cache确保CPU写入的数据对DCU可见 __builtin_arm_dcache_clean((void*)color_p, area-x2 * sizeof(lv_color_t)); // 2. 触发DCU DMA传输 *(volatile uint32_t*)(dcu_map 0x200) 0x1; // START_DMA // 3. 等待VSYNC简化版实际应注册中断 usleep(16667); // ~60Hz lv_disp_flush_ready(disp_drv); } void lv_port_disp_init(void) { static lv_disp_draw_buf_t draw_buf; static lv_color_t buf[1024 * 600]; lv_disp_draw_buf_init(draw_buf, buf, NULL, 1024 * 600); static lv_disp_drv_t disp_drv; lv_disp_drv_init(disp_drv); disp_drv.hor_res 1024; disp_drv.ver_res 600; disp_drv.flush_cb disp_flush; disp_drv.draw_buf draw_buf; disp_drv.direct_mode 1; // 关键启用direct mode绕过double buffer lv_disp_drv_register(disp_drv); dcu_init(); }这段代码的难点在于__builtin_arm_dcache_clean——这是GCC内置函数用于清理ARM的data cache。如果不调用CPU写入buffer的数据可能还在cache里DCU读到的还是旧数据导致画面不更新。direct_mode 1是另一个关键它告诉LVGL不要维护自己的double buffer直接把render buffer交给DCU减少一次memcpy。4.5 运行与调试从“黑屏”到“流畅”的五级诊断法LVGL在泰山派上启动失败90%的情况不是代码问题而是环境问题。我的诊断流程一级确认串口输出# 连接CH340串口波特率1500000泰山派默认 $ screen /dev/ttyUSB0 1500000 # 正常启动应看到U-Boot打印然后Linux kernel log最后LVGL的lv_init()成功信息 # 如果卡在U-Boot说明固件烧录失败二级检查Framebuffer设备# 登录泰山派后执行 $ ls /dev/fb* # 应输出 /dev/fb0 DCU framebuffer $ fbset -fb /dev/fb0 # 应显示mode 1024x600如果不是说明DCU驱动未加载 $ dmesg | grep -i dcu # 应看到rockchip-drm dcu: bound字样三级验证LVGL可执行文件$ file lvgl-demo # 必须是ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-aarch64.so.1 $ ldd lvgl-demo # 应显示所有库都指向 /lib/ld-musl-aarch64.so.1无not found四级运行时日志# 设置LVGL日志级别 $ export LV_LOG_LEVEL4 $ ./lvgl-demo # 观察输出重点关注 # [lv_disp] flush ready - 表示display driver注册成功 # [lv_draw] gpu init ok - 表示GPU后端初始化成功 # 如果卡在[lv_disp]说明disp_flush没返回五级硬件信号测量用示波器测量LVDS的CLK引脚泰山派原理图标为LVDS_CLK_P正常应有25MHz方波。如果没有说明DCU没有输出问题在寄存器配置或电源时序。5. 常见问题与独家避坑技巧那些文档里不会写的实战血泪5.1 “花屏”问题的七种根因与对应解法花屏是泰山派LVGL最常见问题但原因千差万别现象根因解法整屏随机色块随时间变化DCU buffer地址未对齐必须128字节对齐posix_memalign(buf, 128, size)分配buffer左半屏正常右半屏错位LVDS时序参数错误hactive,vactive与屏规格不符查屏规格书修改rk3566-evb.dtsi中lvds节点的rockchip,data-rate和rockchip,format水平方向重复两次图像DCU pitch值设错应为width * bytes_per_pixel不是widthpitch 1024 * 4RGB888为3字节但DCU要求4字节对齐屏幕顶部有固定黑条DCU vertical start位置设错vstart应为0检查LAYER0_SIZE寄存器低16位height和高16位vstart花屏伴随触摸失灵中断线冲突DCU IRQ与触摸IC IRQ共用GPIO修改DTS为DCU分配独立IRQ或调整触摸IC的中断触发方式花屏仅在高分辨率下出现DDR带宽不足DCU DMA抢占失败降低LVGL render buffer分辨率或关闭LV_USE_GPU_MALI_GLES花屏随温度升高恶化散热不良导致DCU PLL失锁加装散热片或在DTS中降低DCU clock频率assigned-clocks cru SCLK_DCU提示我解决过一次“低温花屏”问题——冬天实验室温度低于10℃LVDS PHY芯片工作异常。解决方案是在DTS中增加rockchip,phy-voltage 1200提高PHY供电电压。5.2 “触摸不准”的终极校准方案放弃 tslib拥抱 evdev 原生网络热词里常提“tslib校准”但在泰山派上这是过时方案。现代Linux内核的evdev子系统已足够强大。正确做法确认触摸设备$ ls /dev/input/by-path/ # 找到类似 platform-ff3c0000.i2c-event 的设备 $ cat /proc/bus/input/devices | grep -A 10 FT5* # FT5x06是泰山派常用触摸IC获取原始坐标$ evtest /dev/input/event2 # 替换为你的event节点 # 点击屏幕观察ABS_X、ABS_Y值范围例如ABS_X: 0-2047, ABS_Y: 0-1280编写校准矩阵无需tslib 在/etc/X11/xorg.conf.d/40-touch.conf中添加Section InputClass Identifier calibration MatchProduct Goodix Capacitive TouchScreen Option Calibration 0 2047 0 1280 Option SwapAxes 0 EndSection但LVGL不走X11所以要在lv_port_indev.c中应用static void indev_read(lv_indev_drv_t * drv, lv_indev_data_t * data) { struct input_event ev; read(indev_fd, ev, sizeof(ev)); if (ev.type EV_ABS) { if (ev.code ABS_X) { >#define LV_FONT_FMT_TXT 1 // 启用txt格式字体体积小 #define LV_FONT_DEFAULT lv_font_montserrat_12 // 改用12号体积减半 // 在lv_conf.h中注释掉 // #define LV_FONT_DEJAVU_10 1 // #define LV_FONT_DEJAVU_10_LATIN_SUP 1 // 只保留一个字体更彻底的方案用lv_font_conv工具将字体转为bin格式并静态链接lv_font_conv --font Montserrat-Regular.ttf --size 14 --format bin --output montserrat_14.bin # 然后在C代码中 extern const uint8_t montserrat_14_compressed[]; lv_font