[活动专区] 【AT-START-F405测评】移植LVGL

[复制链接]
 楼主| [鑫森淼焱垚] 发表于 2024-5-8 20:08 | 显示全部楼层 |阅读模式
本帖最后由 [鑫森淼焱垚] 于 2024-5-8 20:08 编辑

#申请原创#
LVGL 简介
LVGL是最流行的免费和开源嵌入式图形库,可为任何MCU, MPU和显示类型创建漂亮的 UI。

它具有如下特性:
  • 丰富且强大的模块化图形组件:按钮 (buttons)、图表 (charts)、列表 (lists)、滑动条 (sliders)、图片 (images) 等
  • 高级的图形引擎:动画、抗锯齿、透明度、平滑滚动、图层混合等效果
  • 支持多种输入设备:触摸屏、 键盘、编码器、按键等
  • 支持多显示设备
  • 不依赖特定的硬件平台,可以在任何显示屏上运行
  • 配置可裁剪(最低资源占用:64 kB Flash,16 kB RAM)
  • 基于UTF-8的多语种支持,例如中文、日文、韩文、阿拉伯文等
  • 可以通过类CSS的方式来设计、布局图形界面(例如:Flexbox、Grid)
  • 支持操作系统、外置内存、以及硬件加速(LVGL已内建支持STM32 DMA2D、NXP PXP和VGLite)
  • 即便仅有单缓冲区(frame buffer)的情况下,也可保证渲染如丝般顺滑
  • 支持模拟器仿真,可以无硬件依托进行开发
  • 丰富详实的例程
  • 详尽的文档以及API参考手册,可线上查阅或可下载为PDF格式
  • 在 MIT 许可下免费和开源



基本上,每个能够驱动显示器的现代控制器都适合运行 LVGL。最低要求是:

  • 16/32或者64位微控制器或处理器
  • 建议使用 >16MHz 时钟速度
  • 闪存/ROM: >64KB 用于非常重要的组件 (建议使用 180KB)
  • RAM:
  • 静态RAM使用量:~2KB,取决于使用的功能和对象类型
  • 堆:>2KB(建议使用8KB)
  • 动态数据(堆):>2KB
  • 显示缓冲区:> 水平分辨率像素
  • MCU 或外部显示控制器中的一个帧缓冲区

  • C99 或更新的编译器



LVGL 源码下载

它的官网地址是 https://github.com/lvgl/lvgl

从网页选择 Tags 然后选择 v8.3.11 版本下载。

51687663b6611bb327.png

LVGL 目录组织

把下载好的 LVGL 源码拷贝到当前工程,放在 middlewares/lvgl_v8.3.11 。

LVGL 源码目录很多,文件很多,概括如下:

67005663b684a4d806.png
LVGL 移植

第一步 新建 lvgl_port 目录,拷贝文件
在 bsp 目录下新建 lvgl_port 目录,然后:

  • 拷贝 lv_conf_template.h 到 lvgl_port/ 目录下,重命名为 lv_conf.h;
  • 拷贝 lvgl_v8.3.11/examples/porting/ 目录下的 lv_port_disp_template.c 和 lv_port_disp_template.h 两个文件到 lvgl_port/ 目录下,分别重命名为 lv_port_disp.c 和 lv_port_disp.h;



第二步 修改 lv_conf.h 文件

  • 把文件中的 #if 0 改成 #if 1 使能这个文件;
  • 根据显示屏修改 LV_COLOR_DEPTH 数值,这里就使用 16 即可;
  • 设置 LVGL 使用的堆,宏定义 LV_MEM_CUSTOM 为0,由 LV_MEM_SIZE 设定堆大小,这里设置48KB;
  • 使能宏定义 LV_USE_PERF_MONITOR LV_USE_MEM_MONITOR 显示帧率和内存占用率;
  • 其他根据需要设定;



第三步 修改 lv_port_disp.c 文件

  • 在文件头添加宏定义 MY_DISP_HOR_RES = 320MY_DISP_VER_RES = 240 ,设定屏幕水平和垂直方向分辨率;
  • 实现 disp_init() 函数,即显示屏初始化;
  • 实现 disp_flush() 函数,调用 LCD 接口并像素显示出来;
  • lv_port_disp_init() 函数中选择一种缓冲模式,这里选择单缓冲;
  • 修改头文件包含,即包含 lv_port_disp.h 头文件,而不是 lv_port_disp_template.h 头文件;



关键代码如下所示:

75634663b672eec015.png

43576663b673650c57.png

  1. /*Flush the content of the internal buffer the specific area on the display
  2. *You can use DMA or any hardware acceleration to do this operation in the background but
  3. *'lv_disp_flush_ready()' has to be called when finished.*/
  4. static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
  5. {
  6.         if (disp_flush_enabled) {
  7.                 int32_t x;
  8.                 int32_t y;
  9.                 for (y = area->y1; y <= area->y2; y++) {
  10.                         for (x = area->x1; x <= area->x2; x++) {
  11.                                 LCD_DrawPointColor(x, y, color_p->full);
  12.                                 color_p++;
  13.                         }
  14.                 }
  15.         }

  16.     /*IMPORTANT!!!
  17.      *Inform the graphics library that you are ready with the flushing*/
  18.     lv_disp_flush_ready(disp_drv);
  19. }


第四步 初始化 lvgl 并添加 lvgl 应用

创建一个线程,线程代码如下:

  1. void lvgl_ui_entry(void* arg)
  2. {
  3.         lv_init();
  4.         lv_port_disp_init();

  5.         bbs_21ic_demo();
  6.         while (1) {
  7.                 vTaskDelay(pdMS_TO_TICKS(3));
  8.                 lv_tick_inc(3);

  9.                 lv_task_handler();
  10.         }
  11. }

  12. void bbs_21ic_demo(void)
  13. {
  14.     lv_obj_t * label_21ic = lv_label_create(lv_scr_act());
  15.     lv_label_set_long_mode(label_21ic, LV_LABEL_LONG_WRAP);     /*Break the long lines*/
  16.     lv_label_set_recolor(label_21ic, true);                      /*Enable re-coloring by commands in the text*/
  17.         lv_label_set_text(label_21ic, "21IC -- #00FF00 Best# #FF0000 Embedded World#");
  18.         lv_obj_set_width(label_21ic, 280);  /*Set smaller width to make the lines wrap*/
  19.     lv_obj_set_style_text_align(label_21ic, LV_TEXT_ALIGN_CENTER, 0);
  20.     lv_obj_align(label_21ic, LV_ALIGN_CENTER, 0, -80);

  21.         lv_obj_t* label_artery = lv_label_create(lv_scr_act());
  22.     lv_label_set_long_mode(label_artery, LV_LABEL_LONG_WRAP);     /*Break the long lines*/
  23.     lv_label_set_recolor(label_artery, true);                      /*Enable re-coloring by commands in the text*/
  24.         lv_label_set_text(label_artery, "#00FF33 Artery# -- An Innovation leader in 32-bit microcontrollers");
  25.         lv_obj_set_width(label_artery, 280);  /*Set smaller width to make the lines wrap*/
  26.     lv_obj_set_style_text_align(label_artery, LV_TEXT_ALIGN_CENTER, 0);
  27.     lv_obj_align(label_artery, LV_ALIGN_CENTER, 0, -20);

  28.     lv_obj_t * label_url = lv_label_create(lv_scr_act());
  29.     lv_label_set_long_mode(label_url, LV_LABEL_LONG_SCROLL_CIRCULAR);     /*Circular scroll*/
  30.     lv_obj_set_width(label_url, 280);
  31.     lv_label_set_text(label_url, "https://bbs.21ic.com/icview-3375936-1-1.html");
  32.     lv_obj_align(label_url, LV_ALIGN_CENTER, 0, 40);
  33. }


LVGL 运行

86896663b676eb966b.png



代码量分析

使用 MicroLib, 优化等级 -Os balanced, Flash 占用 180KB

22062663b67b5bd3e1.png

不使用 MicroLib,优化等级 -Os balanced, Flash 占用 180KB

78585663b67beb040d.png

编译结果分析

flash 占用 180KB,占大头的都是 lvgl 源码,我自己写的应用 init_task.c 才不到 1KB。

此处 180KB ,对应前文 LVGL 推荐 Flash 占用 180KB。符合预期。


9614663b67ed10ec7.png

55986663b67f7b7bcf.png


chenqianqian 发表于 2024-5-11 07:53 来自手机 | 显示全部楼层
对于一些小容量得MCU,比如128KBFLASH,这个资源还是有点捉襟见肘。
Antecer 发表于 2024-7-1 20:27 | 显示全部楼层
Demo工程呢? 来一份啊
micoccd 发表于 2024-7-4 16:33 | 显示全部楼层
看起来挺不错的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

127

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部