LVGL学习笔记1 - 准备
目录
1. 下载LVGL源代码
2. 平台
3. 导入到工程
3.1 配置头文件
3.2 src文件夹
4. 移植
4.1 显示接口部分
4.1.1 disp_init
4.1.2 lv_port_disp_init
4.1.3 disp_flush
4.2 IPA部分
4.2.1 lv_draw_gd32_ipa_init
4.2.2 lv_draw_gd32_ipa_blend_fill
4.2.3 lv_draw_gd32_ipa_blend_map
4.2.3 lv_gpu_gd32_ipa_wait_cb
4.3 tick
5. 初始化
LVGL是Light and Versatile Graphics Library(轻量级通用型图形库)的简称,遵循MIT开源许可协议。
LVGL的官网地址如下:
LVGL - Light and Versatile Embedded Graphics Library
LVGL中文资料:
http://lvgl.z.net
1. 下载LVGL源代码
源代码在Github上。
LVGL部分:
GitHub - lvgl/lvgl: Powerful and easy-to-use embedded GUI library with many widgets, advanced visual effects (opacity, antialiasing, animations) and low memory requirements (16K RAM, 64K Flash).https://github.com/lvgl/lvgl
驱动部分(这部分和外部驱动芯片有关,例如ST7565之类的,而GD32F450自带驱动,所以实际不需要):
GitHub - lvgl/lv_drivers: TFT and touch pad drivers for LVGL embedded GUI libraryhttps://github.com/lvgl/lv_drivers
2. 平台
平台1:
GD的开发板GD32450I_EVAL,即GD32GD32F450 + 4.3寸480x272。
编译环境是MDK + GCC。
平台2:
Visual Studio模拟器,下载地址:
GitHub - lvgl/lv_port_win_visual_studio: LVGL Windows Simulator Visual Studio Edition
Visual Studio的版本要求是2019版及以上,下载后打开工程LVGL.Simulator.sln,将默认的平台改为X64(根据自己的Windows配置修改),编译后可以运行看看效果。如果只用这个模拟器学习,可以不看后面的GD32F450的移植。
3. 导入到工程
3.1 配置头文件
根目录下的lv_conf_template.h和lvgl.h拷贝到工程中,并将lv_conf_template.h改名为lv_conf.h。
lv_conf.h是会随项目情况改动到的,放在项目相关的目录内,这里做个另外的lv_config.h,里面只是include真正的lv_config.h文件。而lvgl.h不会更改,而且和代码内的包含路径有关,可以保留在原来的相对路径内。
其中lv_config.h的内容:
#ifndef LV_CONF_H
#define LV_CONF_H#include "..\..\include.h"#endif
其中include.h中会include真正的配置文件。
把配置文件中的配置打开,默认有一个宏定义设置为0的,改成1。
3.2 src文件夹
把文件加入MDK的工程,draw文件夹里面还有一些文件夹,可以先不加,和平台移植有关。
4. 移植
draw文件夹中有部分代码和平台有关,这里拷贝分和平台有关的代码,例如stm32_dma2d这个文件夹并改名字为gd32_ipa,里面的文件名改为lv_gpu_gd323_ipa.c和lv_gpu_gd323_ipa.h,将所有的stm32和dma2d的字符串改为gd32和ipa。
搜索LV_USE_GPU_STM32_DMA2D,参照改一个LV_USE_GPU_GD32_IPA,将lv_gpu_gd323_ipa.c中的函数内有关STM32的部分删除。
4.1 显示接口部分
在之前下载的lvgl文件夹里面\examples\porting文件夹下有对应的硬件接口文件lv_port_disp_template.c和lv_port_disp_template.h。这个文件主要要实现函数disp_init、lv_port_disp_init和disp_flush。
4.1.1 disp_init
显示初始化,主要是硬件配置和TLI接口初始化。
要使用到SDRAM,初始化好TLI接口,并且定义好一个Layer。
定义指针变量pTFTBuf指向SDRAM,因为这里定义格式为RGB565,大小为TFT_WIDTH * TFT_HEIGHT * 2字节。
#define GUI_TFT_BUF_START EXMC_SDRAM_ADDR0
#define GUI_TFT_BUF_LEN (TFT_WIDTH * TFT_HEIGHT * sizeof(lv_color_t))
uint16_t *pTFTBuf = (uint16_t *)GUI_TFT_BUF_START;
选择Layer 0作为显示层,初始化这个层。
tliLayer_t layer;layer.alpha = 0xFF;layer.bufAddr = (uint32_t)pTFTBuf;layer.defalutColor = 0x000000FF;//0x00FFFFFF;layer.format = FORMAT_RGB565;layer.x = 0;layer.y = 0;layer.w = TFT_WIDTH;layer.h = TFT_HEIGHT;tliLayerInit(0, layer, 1);
4.1.2 lv_port_disp_init
这个函数里面需要选择1种显示缓冲,文件提供了3种方式的缓冲方式,方式1/2/3对应的刷新速度分别是慢/中/快,而RAM占用是少/中/多。这里选择方式3,分配的空间放在SDRAM中(这里注意,如果RAM不够会导致Hard Fault中断,我选择方式2会在第四次调用disp_flush后出错)。
#define GUI_DISP_BUF1_START (GUI_TFT_BUF_START + GUI_TFT_BUF_LEN)
#define GUI_DISP_BUF1_LEN GUI_TFT_BUF_LEN
#define GUI_DISP_BUF2_START (GUI_DISP_BUF1_START + GUI_DISP_BUF1_LEN)
#define GUI_DISP_BUF2_LEN GUI_TFT_BUF_LENstatic lv_disp_draw_buf_t draw_buf_dsc;
static lv_color_t *dispbuf_1 = (lv_color_t *)GUI_DISP_BUF1_START;
static lv_color_t *dispbuf_2 = (lv_color_t *)GUI_DISP_BUF2_START;lv_disp_draw_buf_init(&draw_buf_dsc, dispbuf_1, dispbuf_2, GUI_DISP_BUF1_LEN); /*Initialize the display buffer*/
4.1.3 disp_flush
对于GD32F450的TLI来说,flush就是对Layer对应的buffer更新数据。
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/int32_t x;int32_t y;uint16_t *pTFTBuf = (uint16_t *)GUI_TFT_BUF_START;//Printf("draw:(%d, %d) - (%d, %d)\n", area->x1, area->y1, area->x2, area->y2);for(y = area->y1; y <= area->y2; y++) {for(x = area->x1; x <= area->x2; x++) {/*Put a pixel to the display. For example:*//*put_px(x, y, *color_p)*/*(uint16_t *)(pTFTBuf + y * TFT_WIDTH + x) = (*color_p).full;color_p++;}}/*IMPORTANT!!!*Inform the graphics library that you are ready with the flushing*/lv_disp_flush_ready(disp_drv);
}
4.2 IPA部分
4.2.1 lv_draw_gd32_ipa_init
初始化ipa,并设置颜色模式。
void lv_draw_gd32_ipa_init(void)
{RCU_AHB1EN |= ((uint32_t)1 << 23);//IPA ResetRCU_AHB1RST |= ((uint32_t)1 << 23);RCU_AHB1RST &= ~((uint32_t)1 << 23);/*set output colour mode*/IPA_CTL |= ((uint32_t)1 << 2);IPA_DPCTL = LV_IPA_COLOR_FORMAT;
}
4.2.2 lv_draw_gd32_ipa_blend_fill
这个函数的作用是用指定的颜色刷新显存。函数原型:
static void lv_draw_gd32_ipa_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area, lv_color_t color)
参数含义:
dest_buf - 显存地址
dest_stride - 显存地址偏移量
fill_area - 填充的区域,长方形(x1,y1)- (x2, y2)
color - 填充的颜色
static void lv_draw_gd32_ipa_blend_fill(lv_color_t * dest_buf, lv_coord_t dest_stride, const lv_area_t * fill_area,lv_color_t color)
{/*Simply fill an area*/int32_t area_w = lv_area_get_width(fill_area);int32_t area_h = lv_area_get_height(fill_area);invalidate_cache();IPA_CTL |= ((uint32_t)1 << 2); //Stop IPAIPA_CTL &= ~((uint32_t)0x3 << 16);IPA_CTL |= ((uint32_t)0x3 << 16); //Specific color fillIPA_DMADDR = (uint32_t)dest_buf;IPA_DPV = color.full;IPA_DLOFF = dest_stride - area_w;IPA_IMS = (area_w << 16) | (area_h << 0);IPA_CTL |= ((uint32_t)1 << 0);
}
4.2.3 lv_draw_gd32_ipa_blend_map
这个函数的作用是指定buffer更新显存。
static void lv_draw_gd32_ipa_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa)
参数含义:
dest_buf - 显存地址
dest_area - 填充的区域
dest_stride - 显存地址偏移量
src_buf - 源数据地址
dest_stride - 源数据地址偏移量
opa - alpha值
static void lv_draw_gd32_ipa_blend_map(lv_color_t * dest_buf, const lv_area_t * dest_area, lv_coord_t dest_stride,const lv_color_t * src_buf, lv_coord_t src_stride, lv_opa_t opa)
{/*Simple copy*/int32_t dest_w = lv_area_get_width(dest_area);int32_t dest_h = lv_area_get_height(dest_area);invalidate_cache();if(opa >= LV_OPA_MAX) {IPA_CTL |= ((uint32_t)1 << 2); //Stop IPAIPA_CTL &= ~((uint32_t)0x3 << 16);IPA_CTL = ((uint32_t)0x0 << 16); IPA_FPCTL = LV_IPA_COLOR_FORMAT;IPA_FMADDR = (uint32_t)src_buf;IPA_FLOFF = src_stride - dest_w;IPA_DMADDR = (uint32_t)dest_buf;IPA_DLOFF = dest_stride - dest_w;IPA_IMS = (dest_w << 16) | (dest_h << 0);IPA_CTL |= ((uint32_t)1 << 0); //Start IPA}else {IPA_CTL |= ((uint32_t)1 << 2); //Stop IPAIPA_CTL &= ~((uint32_t)0x3 << 16);IPA_CTL |= ((uint32_t)0x2 << 16); IPA_BPCTL = LV_IPA_COLOR_FORMAT;IPA_BMADDR = (uint32_t)dest_buf;IPA_BLOFF = dest_stride - dest_w;IPA_FPCTL = (uint32_t)LV_IPA_COLOR_FORMAT/*alpha mode 2, replace with foreground * alpha value*/| (2 << 16)/*alpha value*/| (opa << 24);IPA_FMADDR = (uint32_t)src_buf;IPA_FLOFF = src_stride - dest_w;IPA_DMADDR = (uint32_t)dest_buf;IPA_DLOFF = dest_stride - dest_w;IPA_IMS = (dest_w << 16) | (dest_h << 0);IPA_CTL |= ((uint32_t)1 << 0); //Start IPA}
}
4.2.3 lv_gpu_gd32_ipa_wait_cb
这个函数的作用是等待渲染结束。
void lv_gpu_gd32_ipa_wait_cb(lv_draw_ctx_t * draw_ctx)
{lv_disp_t * disp = _lv_refr_get_disp_refreshing();if(disp->driver && disp->driver->wait_cb) {while(IPA_CTL & 0x01) {disp->driver->wait_cb(disp->driver);}}else {while(IPA_CTL & 0x01);}lv_draw_sw_wait_for_finish(draw_ctx);
}
4.3 tick
LVGL 需要一个系统滴答来了解动画和其他任务(例如输入设备读取)所用的时间,所以需要在一个定时器中调用lv_tick_inc。
lv_tick_inc(TIMER_MS);
定时调用这个函数即可,实现方式可以随意,裸奔的方式可以在system tick中调用。
5. 初始化
在使用其他LVGL的API前必须调用lv_init(),然后调用lv_port_disp_init即可。
lv_init();lv_port_disp_init();
这时候屏幕应该是没有显示(如果把pTFTBuf 的数据全部改成0xF800,即红色,可以看到屏幕为红色,LVGL并没有起作用)。
在非OS应用中,需要在主循环中添加lv_task_handler();而在OS应用中,应该是在一个任务循环中添加这个函数的调用。
这是屏幕会显示白屏,添加一段测试程序(在lv_port_disp_init()后添加即可)。
lv_obj_t *rect = lv_obj_create(lv_scr_act());
lv_obj_set_size(rect, LV_PCT(20), LV_PCT(20));
lv_obj_align(rect, LV_ALIGN_CENTER, 0, 0);
即画一个矩形。
模拟器显示效果:
LVGL学习笔记1 - 准备相关推荐
- 【LVGL学习笔记】(三)控件使用
LVGL全程LittleVGL,是一个轻量化的,开源的,用于嵌入式GUI设计的图形库.并且配合LVGL模拟器,可以在电脑对界面进行编辑显示,测试通过后再移植进嵌入式设备中,实现高效的项目开发. LVG ...
- 【LVGL学习笔记】(五)使用SquareLine Studio设计UI
LVGL全程LittleVGL,是一个轻量化的,开源的,用于嵌入式GUI设计的图形库.并且配合LVGL模拟器,可以在电脑对界面进行编辑显示,测试通过后再移植进嵌入式设备中,实现高效的项目开发. LVG ...
- LittleVGL(LVGL)学习笔记——PC 模拟器的安装和使用(CodeBlocks)
目录 一.简介 1.LittleVGL 所支持的 IDE 软件种类: 2.需要的工具: 二.安装配置软件和环境 1.littleVGL 模拟器库 2.安装CodeBlocks 三.创建工程项目 四.配 ...
- LVGL学习笔记(二):从0到1移植LVGL8.1到STM32平台上(完结篇)
目录 一:TFT-LCD屏触摸 二:STM32CubeMX配置 三:FT5206触摸芯片驱动代码移植 四:LVGL 移植 4.1 源码下载 4.2 代码移植 4.3 添加源码至工程 4.4 指定头文件 ...
- 【LVGL学习笔记】(二) 基础概念
LVGL全程LittleVGL,是一个轻量化的,开源的,用于嵌入式GUI设计的图形库.并且配合LVGL模拟器,可以在电脑对界面进行编辑显示,测试通过后再移植进嵌入式设备中,实现高效的项目开发. LVG ...
- LVGL学习笔记19 - 下拉列表dropdown
目录 1. Parts 1.1 按钮状态 1.2 列表状态 2. 设置 2.1 设置选项 2.2 设置方向 2.3 设置符号 2.4 设置字符串 2.5 手动打开或关闭列表 2.6 设置高亮效果 3. ...
- LVGL学习笔记 20 - 滚轮Roller
目录 1. Parts 2. 设置 2.1 设置选项 2.2 设置可见行 2.3 设置选中项 3. 样式 3.1 设置选项之间的间隔 3.2设置滚动效果时间 3.3 设置选中项的字体 3.4 设置选中 ...
- LVGL学习笔记7 - GD32平台优化
目录 1. 颜色深度 2. 更新disp_init 3. 更新disp_flush 4. 改为IPA更新数据 5. 死机问题 学习过程中发现GD32平台的显示效果不佳,而且会出现死机的问题,需要优化一 ...
- LVGL学习笔记14 - 线Line
目录 1. 点数组 2. 样式 2.1 宽度 2.2 颜色 2.3 末端形态 2.4 虚线 通过一组点绘制出相连的直线,通过lv_line_create创建相应的对象. 线只有LV_PART_MAIN ...
最新文章
- compass安装使用960 Grid System
- 受用一生的高效PyCharm使用技巧(二)
- linux vnc xstartup,vnc 远程桌面选择的配置 xstartup
- 安卓与ios都是linux,随便来说两句,安卓、IOS不是那么容易被取代的
- 循环结束后变回去 设置一个值_VBA掌握循环结构,包你效率提高500倍
- 一个平行四边形可以分成四个_将平行四边形分割成两个三角形还易变形么?(人教四下五单元三角形例2)...
- c++运行不出结果_fastjson 不出网利用总结
- cad2008加载 et拓展工具_生物信息工具 | 如何为网络图添加漂亮的图例?
- CLR via C# 3 读书笔记(4):第1章 CLR执行模型 — 1.4 执行程序集代码
- 如何将Linux还原为win10,技术编辑为你解说win10系统Linux Bash命令的还原步骤
- matlab详细手册,matlab详细手册
- python接口自动化代码_python接口自动化(十六)--参数关联接口后传(详解)
- Stemming and lemmatization
- 大数据笔记--Hadoop(第五篇)
- vue-学生的最爱抽签点名器
- Kaggle:入门赛Tatanic(泰坦尼克号)84.21%带你冲进前2%
- 计算机电子琴乐谱数字键,电子琴键盘与乐谱对照表.pdf
- python柱状图加百分比_【python】封装接口直接利用DataFrame绘制百分比柱状图
- matlab nlm,NLM.m · hr_yang/MatlabCode - Gitee.com
- C语言课程设计 管理系统
热门文章
- 吃糖果游戏(tyvj 1567)
- 红外光谱图解析知识大全(图文并茂)
- Python使用逻辑回归提示FutureWarning: Default solver will be changed to ‘lbfgs‘ in 0.22. Specify a solver to
- JVM:JVM常见参数配置
- 【BZOJ 1305】[CQOI2009]dance跳舞
- PHP获取唯一标识UUID
- linux车牌识别,基于嵌入式Linux的电子车牌识别系统设计与实现
- 学习java看什么论坛比较好
- linux中的文件夹压缩文件,linux将文件拷贝到目录下Linux下文件的压缩与打包详解...
- MySQL——创建存储过程和函数