| 本帖最后由 [鑫森淼焱垚] 于 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 版本下载。
 
 
   
 LVGL 目录组织
 
 把下载好的 LVGL 源码拷贝到当前工程,放在 middlewares/lvgl_v8.3.11 。
 
 LVGL 源码目录很多,文件很多,概括如下:
 
 
   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 = 320 和 MY_DISP_VER_RES = 240 ,设定屏幕水平和垂直方向分辨率;实现 disp_init() 函数,即显示屏初始化;实现 disp_flush() 函数,调用 LCD 接口并像素显示出来;在 lv_port_disp_init() 函数中选择一种缓冲模式,这里选择单缓冲;修改头文件包含,即包含 lv_port_disp.h 头文件,而不是 lv_port_disp_template.h 头文件;
 
 
 关键代码如下所示:
 
 
   
 
   
 
 /*Flush the content of the internal buffer the specific area on the display
 *You can use DMA or any hardware acceleration to do this operation in the background but
 *'lv_disp_flush_ready()' has to be called when finished.*/
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
        if (disp_flush_enabled) {
                int32_t x;
                int32_t y;
                for (y = area->y1; y <= area->y2; y++) {
                        for (x = area->x1; x <= area->x2; x++) {
                                LCD_DrawPointColor(x, y, color_p->full);
                                color_p++;
                        }
                }
        }
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}
 第四步 初始化 lvgl 并添加 lvgl 应用
 
 创建一个线程,线程代码如下:
 
 
 void lvgl_ui_entry(void* arg)
{
        lv_init();
        lv_port_disp_init();
        bbs_21ic_demo();
        while (1) {
                vTaskDelay(pdMS_TO_TICKS(3));
                lv_tick_inc(3);
                lv_task_handler();
        }
}
void bbs_21ic_demo(void)
{
    lv_obj_t * label_21ic = lv_label_create(lv_scr_act());
    lv_label_set_long_mode(label_21ic, LV_LABEL_LONG_WRAP);     /*Break the long lines*/
    lv_label_set_recolor(label_21ic, true);                      /*Enable re-coloring by commands in the text*/
        lv_label_set_text(label_21ic, "21IC -- #00FF00 Best# #FF0000 Embedded World#");
        lv_obj_set_width(label_21ic, 280);  /*Set smaller width to make the lines wrap*/
    lv_obj_set_style_text_align(label_21ic, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_align(label_21ic, LV_ALIGN_CENTER, 0, -80);
        lv_obj_t* label_artery = lv_label_create(lv_scr_act());
    lv_label_set_long_mode(label_artery, LV_LABEL_LONG_WRAP);     /*Break the long lines*/
    lv_label_set_recolor(label_artery, true);                      /*Enable re-coloring by commands in the text*/
        lv_label_set_text(label_artery, "#00FF33 Artery# -- An Innovation leader in 32-bit microcontrollers");
        lv_obj_set_width(label_artery, 280);  /*Set smaller width to make the lines wrap*/
    lv_obj_set_style_text_align(label_artery, LV_TEXT_ALIGN_CENTER, 0);
    lv_obj_align(label_artery, LV_ALIGN_CENTER, 0, -20);
    lv_obj_t * label_url = lv_label_create(lv_scr_act());
    lv_label_set_long_mode(label_url, LV_LABEL_LONG_SCROLL_CIRCULAR);     /*Circular scroll*/
    lv_obj_set_width(label_url, 280);
    lv_label_set_text(label_url, "https://bbs.21ic.com/icview-3375936-1-1.html");
    lv_obj_align(label_url, LV_ALIGN_CENTER, 0, 40);
}
 LVGL 运行
 
 
   
 
 
 代码量分析
 
 使用 MicroLib, 优化等级 -Os balanced, Flash 占用 180KB
 
 
   
 不使用 MicroLib,优化等级 -Os balanced, Flash 占用 180KB
 
 
   
 编译结果分析
 
 flash 占用 180KB,占大头的都是 lvgl 源码,我自己写的应用 init_task.c 才不到 1KB。
 
 此处 180KB ,对应前文 LVGL 推荐 Flash 占用 180KB。符合预期。
 
 
 
   
 
   
 
 
 |