引言:
相信点进这篇文章的读者对LVGL多多少少都有一些了解-主流的开源GUI库. 而通过本文的标题也可知本文核心内容就是介绍QuecPython环境下LVGL使用的.
移远无线通信模组让万物互联成为现实, QuecPython开启全新的模组开发方式, 用最简单易用的编程语言开发最前沿的无线通信产品.
自QuecPython面世以来, 以解析型; 可嵌入; 面向对象; 可交互; 简单易学这些优于传统的开发方式的优点而深受广大开发者好评.
既然QuecPython都将嵌入式开发的功能做到这了, 那UI设置这个难啃的骨头QuecPython当然也不会放过. 到此: 引言结束, 正文开始.
LVGL概述
LVGL全称Light and Versatile Graphics Library. 是一个自由的, 开源的GUI库. 界面精美, 资源消耗小, 可移植度高. 具有响应式布局等特点.
有关LVGL特征及移至的资源需求这边不做介绍. 有兴趣的小伙伴可以自行至LVGL官网(LVGL — Light and Versatile Embedded Graphics Library)了解. 这边补充说明一点: LVGL每一个大版本之间都不兼容. 目前QuecPython移植版本为v8.2版本. LVGL-API介绍参考: Welcome to the documentation of LVGL! — LVGL documentation即可.
使用指导
准备工作
LVGL是一个开源的GUI库, 可以完成常用的显示工作. 在传统嵌入式项目中使用之前需要将LVGL库移植于自己的项目之中, 移植过程较为复杂, LVGL官网也有相应内容, 我们这边不做过多介绍. 对于QuecPython用户来说使用LVGL却简单很多, 只需要烧录带有LVGL功能的固件及可完成前期准备工作.
这个过程类似于嵌入式中将LVGL的库文件添加到自己的项目之中. 当然像显示屏幕这样的硬/软件准备工作也是需要提前准备好的. 相信玩到这个程度的客户这个准备工作已经不具备难度了. 文章下述也会以ST7789驱动芯片为例进行介绍.
初始化
完成准备工作后, 也是就添加了LVGL的库文件到我们项目中后, 我们便可以正式开始编写我们的LVGL的代码了. 使用之前肯定需要先进行初始化工作.
这边小Q主要介绍屏幕显示, 不涉及到屏幕触摸反馈. 所以主要为屏幕的初始化跟LVGL显示部分的初始化. 代码如下:
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | # -*- coding: UTF-8 -*- # 导入模块 import lvgl as lv # LVGL显示模块 from machine import LCD # 屏幕显示模块 # 屏幕参数 screen_high = 240 # 屏高 screen_wide = 240 # 屏高 XSTART_H = 0xf0 # 起始点X坐标高字节寄存器 XSTART_L = 0xf1 # 起始点X坐标低字节寄存器 XEND_H = 0xE0 # 结束点X坐标高字节寄存器 XEND_L = 0xE1 # 结束点X坐标低字节寄存器 YSTART_H = 0xf2 # 起始点Y坐标高字节寄存器 YSTART_L = 0xf3 # 起始点Y坐标低字节寄存器 YEND_H = 0xE2 # 结束点Y坐标高字节寄存器 YEND_L = 0xE3 # 结束点Y坐标低字节寄存器 lcd = LCD() # 创建对象 # 屏幕初始化参数 # 类型: 0 表示命令; 1 表示数据; 2 表示延时 # 长度:若类型为 0,则长度表示命令后的数据数量;若类型为 1,则长度表示数据的长度 # 参数值: 对应值 init_data = ( 0, 0, 0x11, 0, 1, 0x36, 1, 1, 0x00, 0, 1, 0x3A, 1, 1, 0x05, 0, 0, 0x21, 0, 5, 0xB2, 1, 1, 0x05, 1, 1, 0x05, 1, 1, 0x00, 1, 1, 0x33, 1, 1, 0x33, 0, 1, 0xB7, 1, 1, 0x23, 0, 1, 0xBB, 1, 1, 0x22, 0, 1, 0xC0, 1, 1, 0x2C, 0, 1, 0xC2, 1, 1, 0x01, 0, 1, 0xC3, 1, 1, 0x13, 0, 1, 0xC4, 1, 1, 0x20, 0, 1, 0xC6, 1, 1, 0x0F, 0, 2, 0xD0, 1, 1, 0xA4, 1, 1, 0xA1, 0, 1, 0xD6, 1, 1, 0xA1, 0, 14, 0xE0, 1, 1, 0x70, 1, 1, 0x06, 1, 1, 0x0C, 1, 1, 0x08, 1, 1, 0x09, 1, 1, 0x27, 1, 1, 0x2E, 1, 1, 0x34, 1, 1, 0x46, 1, 1, 0x37, 1, 1, 0x13, 1, 1, 0x13, 1, 1, 0x25, 1, 1, 0x2A, 0, 14, 0xE1, 1, 1, 0x70, 1, 1, 0x04, 1, 1, 0x08, 1, 1, 0x09, 1, 1, 0x07, 1, 1, 0x03, 1, 1, 0x2C, 1, 1, 0x42, 1, 1, 0x42, 1, 1, 0x38, 1, 1, 0x14, 1, 1, 0x14, 1, 1, 0x27, 1, 1, 0x2C, 0, 0, 0x29, 0, 1, 0x36, 1, 1, 0x00, # 屏幕方向控制位. 0x00: 竖屏; 0x70: 横屏. 0, 4, 0x2a, 1, 1, 0x00, 1, 1, 0x00, 1, 1, 0x00, 1, 1, 0xef, 0, 4, 0x2b, 1, 1, 0x00, 1, 1, 0x00, 1, 1, 0x00, 1, 1, 0xef, 0, 0, 0x2c, ) # 屏幕区域显示参数 # 类型: 0 表示命令; 1 表示数据; 2 表示延时 # 长度:若类型为 0,则长度表示命令后的数据数量;若类型为 1,则长度表示数据的长度 # 参数值: 对应值 lcd_set_display_area = ( 0, 4, 0x2a, 1, 1, XSTART_H, 1, 1, XSTART_L, 1, 1, XEND_H, 1, 1, XEND_L, 0, 4, 0x2b, 1, 1, YSTART_H, 1, 1, YSTART_L, 1, 1, YEND_H, 1, 1, YEND_L, 0, 0, 0x2c, ) lcd_init_data = bytearray(init_data) # 转换初始化参数数组 lcd_invalid = bytearray(lcd_set_display_area) # 转换区域设定参数数组 lcd.lcd_init(lcd_init_data, screen_high, screen_wide, 6500, 1, 4, 0, lcd_invalid, None, None, None) # 初始化LCD屏 lcd.lcd_clear(colour) # 清屏 print("LCD初始化成功") # LVGL初始化部分 lv.init() # LVGL初始化 disp_buf1 = lv.disp_draw_buf_t() # 创建显示缓存区句柄 buf1_1 = bytes(screen_high * screen_wide * 2) # 申请内存大小 disp_buf1.init(buf1_1, None, len(buf1_1)) # 配置显示缓冲区大小 disp_drv = lv.disp_drv_t() # 创建显示回调句柄 disp_drv.init() # 注册一个显示器 disp_drv.draw_buf = disp_buf1 # 设置显示器BUFF大小 disp_drv.flush_cb = lcd.lcd_write # 配置回调写屏函数 disp_drv.hor_res = screen_high # 配置屏的高度 disp_drv.ver_res = screen_wide # 配置屏的宽度 disp_drv.register() # 注册驱动程序并保存创建的显示对象 lv.tick_inc(10) # 在定时器或任务中每毫秒调用一次(1到10之间) lv.task_handler() # 循环轮询函数 print("LVGL初始化成功") print("LVGL版本: {}.{}".format(lv.version_major(), lv.version_minor())) |
在初始化LVGL之前需要先对使用的显示屏进行初始化, 不同的屏幕型号初始化代码均有不同. 本示例中的显示屏为ST7789芯片驱动的240*240显示屏(如果您使用的屏幕驱动芯片是其他芯片, 按如上代码注释进行修改即可). 初始化了显示屏后边可以正式进入LVGL的初始化部分了. 值得注意的是LVGL初始化的首句必须为“lv.init()”初始化LVGL库. 进行了LVGL库初始化后, 还需要完成如下工作来完成LVGL的初始化:
- 开辟LVGL使用缓冲区;
- 传入屏幕参数(这边使用了宏定义的方式传入, 以便后期修改);
- 传入屏幕写入函数: disp_drv.flush_cb = lcd.lcd_write(此函数便连接了LVGL与屏幕)
开始使用
进行了上述的初始化工作后, 下面就能实际使用LVGL功能了. 使用LVGL功能主要有两种方式途径介绍:
GUI-Guider图形化工具生成代码
该部分内容较多, 后期专出一篇文档介绍.
LVGL官网demo
下面小Q以LVGL官网进度条为例介绍LVGL图标库的调用工作.
001 002 003 004 005 006 007 008 009 010 011 012 | lcd.lcd_clear(colour) # 清屏 # 创建基础对象, 实现底层lv.scr_act()函数的功能 lvobject = lv.obj() # 创建基础对象 lv.scr_load(lvobject) # 活跃基础对象 # bar1 = lv.bar(lv.scr_act()) # 创建一个进度条 bar1 = lv.bar(lvobject) # 创建一个进度条 bar1.set_size(220, 30) # 设置进度条尺寸 bar1.align(lv.ALIGN.TOP_LEFT, 10, 105) # 设置进度条位置 bar1.center() # 使能Bar显示 bar1.set_style_anim_time(0, 1500) # 设置进度条时间 bar1.set_value(70, lv.ANIM.ON) # 开启进度条以及设置百分比 |
我们可以直接复制LVGL官网示例进行运行查看运行效果. 有关API介绍也可直接与LVGL官网进行查看. 总的来说LVGL的使用过程其实就是配置显示参数的过程, 大体可分为通用配置与专用配置两大类. 以上述代码为例:
通用配置
- 创建(类似嵌入式定义句柄, 用于整体控制)
- 设置尺寸(设置图标显示大小)
- 设置位置(设置图标显示位置)
专用配置
- 设置进度条时间
- 进度条百分比
一个显示套件经过通用配置与专用配置后LVGL便可以正常显示我们想要的内容了. 至此基础使用介绍完毕. 其他功能套件直接按照上述流程参考使用即可.
总结:
LVGL作为一款免费开源嵌入式图形库. 可以协助我们快速完成项目中的UI界面的开发工作. 本文介绍了QuecPython环境下LVGL的基础使用过程, 实际项目中搭配上GUI-Guider图形化界面工具. 可快速完成需要专业UI界面工程师才能完成的UI界面设计工作. GUI-Guider工具的代码生成功能让QuecPython的UI开发不在繁琐复杂. 可以说是让QuecPython开发如虎添翼.
附: LVGL官网: LVGL — Light and Versatile Embedded Graphics Library
LVGL-API介绍参考: Welcome to the documentation of LVGL! — LVGL documentation
Gui-Guider工具: SquareLine Studio - Design and build UIs with ease
附言:
后期小Q也会陆续分享其他QuecPython学习心得,欢迎各位看官沟通交流。