十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

113_跟着伟哥学UI之LVGL移植教程

113_跟着伟哥学UI之LVGL移植教程 新手教程链接链接1:百问网LVGL链接2:百问网LVGL(实用性更强一点?)一、下载 LVGL 源码打开 LVGL 官方仓库https://github.com/lvgl/lvgl(1) 推荐使用git clone方式下载方便以后更新-- GitHub链接(2) 或者直接点击 GitHub 页面上的Code按钮选择Download ZIP下载压缩包并解压。下载后你会得到一个名为lvgl的文件夹里面包含lvgl/——核心库源码这是我们要用的examples/—— 官方示例代码可选docs/—— 文档demos/—— 演示程序scripts/—— 辅助脚本lv_conf_template.h——配置模板文件二、将 LVGL 核心库加入你的工程找到lvgl文件夹刚下载的。(1) 将该文件夹整体复制到你的嵌入式工程目录中例如放在Middlewares/或ThirdParty/下。(2) 注意不要复制整个下载下来的文件夹只需要复制里面的lvgl子目录。在工程中创建以下文件分组以 Keil 为例其他 IDE 类似lvgl_core添加lvgl/src下所有.c文件递归添加子目录如core、draw、extra、font、hal、misc、widgets等lvgl_port存放你自己编写的移植文件下面会创建添加头文件包含路径大型工程用Cmake 管理包含lvgl目录即lvgl文件夹本身包含lvgl/src目录包含你的移植文件所在目录例如lvgl_port三、配置lv_conf.h找到lvgl/lv_conf_template.h文件。(1) 将它复制一份放到lvgl目录旁边例如工程根目录下与lvgl同级。(2) 将复制后的文件改名为lv_conf.h。打开lv_conf.h进行以下修改(1) 将文件开头的#if 0改为#if 1使配置生效。(2) 设置颜色深度根据你的屏幕#defineLV_COLOR_DEPTH16// 常见 RGB565 屏幕什么叫设置颜色深度颜色深度Color Depth 是指每个像素用多少位bit来存储颜色信息。它决定了屏幕能够显示的颜色数量也直接影响内存占用和显示性能。常见的颜色深度有1位、8位、16位、24位和32位。以16位颜色深度为例每个像素用16个二进制位表示可以组合出2166553621665536种颜色足够大多数嵌入式GUI使用。而24位真彩色可以表示224≈1677224≈1677万种颜色但占用的内存是16位的1.5倍。颜色深度Color Depth是指每个像素用多少位bit来存储颜色信息它直接决定了屏幕能显示的颜色数量以及帧缓冲区的内存占用——位深越大色彩越丰富但内存和传输带宽开销也越高。对于嵌入式GUI16位RGB565可显示65536色是绝大多数场景的最佳平衡点其色彩表现人眼已难以察觉明显色阶而单帧缓冲区仅需150KB以240×320分辨率计远低于24位真彩色的225KB你的项目中LVGL配置为CONFIG_LV_COLOR_DEPTH16既满足遥控器界面的色彩需求又能在BK7258有限的RAM资源下保证流畅渲染是工程上最合理的选择。工程的最终目的是在符合实际功能的前提下以最小的消耗完成最优解.而不是为了极致的性能.除非极致的性能是用户需要的(3) 启用日志可选建议开发时打开#defineLV_USE_LOG1#defineLV_LOG_LEVELLV_LOG_LEVEL_WARN#defineLV_LOG_PRINTF1(4) 根据你的内存大小调整动态内存分配可选#defineLV_MEM_SIZE(48U*1024U)// 例如 48KB根据实际修改(5) 其他配置暂时保持默认后续按需修改。扩展:如果不想把lv_conf.h放在lvgl旁边也可以放在别处但需要在编译选项中添加宏定义LV_CONF_INCLUDE_SIMPLE手动将lv_conf.h所在目录加入头文件搜索路径四、编写显示驱动移植屏幕准备一个显示缓冲区绘制缓冲。(1) 在lvgl_port目录下新建lv_port_disp.c和lv_port_disp.h。(2) 在.c文件中定义缓冲区必须是 static 或全局#defineDISP_HOR_RES320#defineDISP_VER_RES240#defineDISP_BUF_SIZE(DISP_HOR_RES*10)// 1/10 屏幕大小可调整staticlv_color_tbuf_1[DISP_BUF_SIZE];staticlv_disp_draw_buf_tdraw_buf;初始化显示缓冲区/** * brief CN初始化 LVGL 显示绘制缓冲区结构体。设置缓冲区指针和大小 * 支持单缓冲或双缓冲模式buf2 可为 NULL。 * ENInitialize an LVGL display draw buffer structure. Sets the buffer pointers and size, * supporting single or double buffering (buf2 can be NULL). * * param CNdraw_buf 显示绘制缓冲区结构体指针将被初始化。 * ENdraw_buf - Pointer to the display draw buffer structure to be initialized. * param CNbuf1 第一个缓冲区指针。 * ENbuf1 - Pointer to the first buffer. * param CNbuf2 第二个缓冲区指针单缓冲模式下传入 NULL。 * ENbuf2 - Pointer to the second buffer, pass NULL for single buffering. * param CNsize_in_px_cnt 缓冲区大小以像素为单位。 * ENsize_in_px_cnt - Buffer size in pixels. * * return CN无。 * ENNone. */voidlv_disp_draw_buf_init(lv_disp_draw_buf_t*draw_buf,// CN显示缓冲区结构体指针。-- ENDisplay draw buffer structure pointer.void*buf1,// CN第一个缓冲区。-- ENFirst buffer.void*buf2,// CN第二个缓冲区可选。-- ENSecond buffer (optional).uint32_tsize_in_px_cnt// CN缓冲区大小像素数。-- ENBuffer size in pixels.);实现flush_cb回调函数将像素数据发送到屏幕(1) 根据你的屏幕驱动实现像素发送例如使用SPI或LTDC。(2) 示例适用于大部分 SPI 彩屏staticvoidmy_flush_cb(lv_disp_drv_t*disp_drv,constlv_area_t*area,lv_color_t*color_p){// 设置显示窗口LCD_SetWindow(area-x1,area-y1,area-x2,area-y2);// 发送像素数据假设每个像素 2 字节RGB565uint32_tw(area-x2-area-x11);uint32_th(area-y2-area-y11);LCD_SendPixels((uint8_t*)color_p,w*h*2);// 告诉 LVGL 刷新完成lv_disp_flush_ready(disp_drv);}注册显示驱动(1) 在初始化函数中voidlv_port_disp_init(void){staticlv_disp_drv_tdisp_drv;lv_disp_drv_init(disp_drv);disp_drv.hor_resDISP_HOR_RES;disp_drv.ver_resDISP_VER_RES;disp_drv.flush_cbmy_flush_cb;disp_drv.draw_bufdraw_buf;lv_disp_drv_register(disp_drv);}五、编写输入设备驱动以触摸屏为例在lvgl_port目录下新建lv_port_indev.c和lv_port_indev.h。实现触摸读取回调staticvoidtouchpad_read(lv_indev_drv_t*indev_drv,lv_indev_data_t*data){uint16_tx,y;if(Touch_GetXY(x,y))// 返回是否被按下{data-point.xx;data-point.yy;data-stateLV_INDEV_STATE_PRESSED;}else{data-stateLV_INDEV_STATE_RELEASED;}}注册输入设备voidlv_port_indev_init(void){staticlv_indev_drv_tindev_drv;lv_indev_drv_init(indev_drv);indev_drv.typeLV_INDEV_TYPE_POINTER;indev_drv.read_cbtouchpad_read;lv_indev_drv_register(indev_drv);}六、实现 Tick 和时间基准在你的 MCU 定时器中断中例如 SysTick 1ms 中断调用voidSysTick_Handler(void){lv_tick_inc(1);// 每 1ms 调用一次}如果使用 FreeRTOS可以在vApplicationTickHook中调用。七、初始化 LVGL 并启动主循环在main()函数中依次调用intmain(void){// 硬件初始化HAL_Init();SystemClock_Config();LCD_Init();Touch_Init();// LVGL 初始化lv_init();lv_port_disp_init();lv_port_indev_init();// 启动系统滴答中断确保 Tick 正常工作// ...while(1){lv_timer_handler();delay_ms(5);// 延时 5ms根据实际情况调整}}如果使用 RTOS可以将lv_timer_handler()放在独立任务中并保证调用互斥锁保护。八、验证移植是否成功编译工程修复可能的头文件或路径错误。烧录程序观察屏幕是否显示 LVGL 默认界面可能是一片蓝色或黑色取决于主题。如果没有任何显示请检查lv_conf.h中#if 1是否已修改显示驱动中hor_res和ver_res是否设置正确flush_cb中是否最终调用了lv_disp_flush_ready()屏幕初始化是否成功可先用纯色填充测试日志是否输出错误信息开启LV_USE_LOG并重定向printf九、常见问题排查编译时提示找不到lv_conf.h确认lv_conf.h所在目录已加入头文件搜索路径或者定义LV_CONF_INCLUDE_SIMPLE并确保路径正确屏幕显示花屏或颜色不正常检查LV_COLOR_DEPTH与屏幕接口是否匹配例如 RGB565 应设为 16检查flush_cb中像素格式转换是否正确如字节顺序触摸无反应确认输入设备类型为LV_INDEV_TYPE_POINTER检查read_cb中是否正确填写data-point和data-state可在read_cb中添加日志打印坐标进行调试动画不运行确认lv_tick_inc()在中断中被周期调用确认lv_timer_handler()在主循环中被周期调用约 5ms通过以上步骤你应该能够成功将 LVGL 移植到你的嵌入式平台。记住显示驱动和输入驱动是移植的核心务必确保它们与你的硬件正确配合。
返回列表