Q1.SGL是什么?
SGL是一个轻量级的UI图形库,符合现代化审美设计,其设计思想来源于LVGL图形库,具有抗锯齿,圆角,边框等关键UI设置项,同时具有图层概念,不同控件有不同的层次,可设置透明度,控件同样有父子关系,子控件可继承部分父控件属性。代码采用面向对象的思想,文件结构清晰,非常适合应用于性能以及内存有限的单片机,控件有:圆角矩形、标签、开关、进度条、圆环、列表等。
SGL仓库地址:https://github.com/sgl-org/sgl
镜像仓库地址:https://gitee.com/sgl-org/sgl
Q2.有了LVGL图形库,SGL存在的意义是什么?
LVGL对内存和性能的占用仍然太大。当然,毫无疑问,LVGL是目前嵌入式领域使用率比较高的一个UI库(据官方搜索小米也在用),功能多,代码风格好,虽然也算轻量级UI库,但轻量级的程度仍然不够。对于内存小的单片机来说,运行LVGL压力非常大,那么我内存小,又想用类似LVGL的图形库有吗?有的兄弟,有的,就是我们介绍的主题SGL图形库。
Q3.SGL图形库到底解决了什么痛点?
目前LVGL图形库是好用,但是对单片机要求特别高,如果使用无UI框架的方式,性能以及内存占用确实小,但做出来的效果又特别差劲,做出来的产品够用,但缺乏竞争力。
(1)flash占用大:LVGL可以对功能进行裁剪,但由于其设计框架的原因,裁剪过后的代码对内存占用也十分大,SGL是高度可裁剪,裁剪过后的功能,一定不会被编译(直接或间接)。
(2)ram占用大:对于LVGL来说,每个控件对RAM的占用都是很大的,LVGL是为了功能的丰富,但SGL的定位是为了更加轻量级,因此,对于RAM的使用,作者严格地控制每一个字节的占用,尽可能保证功能的前提下做到最小占用。
(3)代码框架差:当不使用任何框架时,散装的代码,某宝卖家配套的代码,某SDN下载的测试代码,这类代码不考虑程序可读性,可维护性,功能可扩展性,用这种代码测试是可以,用于实际项目开发是灾难性的。SGL是完全没有这些问题的,源代码文件目录分类清晰,函数API风格统一,同样有配置文件,初始化简单,配套资料文档齐全。
Q4.为什么选择CW32L012跑SGL?
(1)主频高,96Mhz。
(2)SPI时钟可达48M。SPI时钟高,非常适合SPI屏的驱动,在同档位MCU中算比较优秀的。
(3)ram和flash大小合适(8K+64K)。SGL对于ram的要求是4K以上,flash是20k以上。
(4)性价比高。同样外设资源、封装、引脚数情况下,CW32L012算比较便宜的。
Q5.CW32L012移植SGL步骤
这里会教大家一遍流程,不会也没关系,有已经移植好的示例工程,示例工程名为“cw32l012_sgl_gui_demo”,这里可以大概了解一下有哪些步骤,需要关注哪些地方。
通过网盘分享的文件:cw32l012_sgl_gui_demo.rar链接:?https://pan.baidu.com/s/1RGcQ9_l8iK40jNl335mX0g?pwd=CW32?提取码: CW32
(1)从官网下载文件,https://github.com/sgl-org/sgl
文件夹内有很多类型的文件,我们只需要使用“source”文件夹
(2)准备好已经调通屏幕显示的工程
需要至少有以下两个函数:?屏幕初始化,矩形填充函数
(3)添加sgl源码
根据sgl对应的文件结构,在编译器中同样创建对应的文件目录并添加.c文件,.h文件包含即可
▲(keil中的工程目录结构)
▲Sgl 中的source 目录结构
▲(头文件包含)
Tips: 实际只需要将source里的所有.c文件全部添加,这里分类是为了有良好的文件结构。包含头文件需要包含source目录和include目录。
(4)修改conf文件
配置文件名为“sgl_config.h”,一般只需要修改屏幕颜色深度,内存分配大小,其他的配置项可以参考下图,不明白的可以保持默认。
(5)初始化SGL
初始化是使用该库的关键,重点关注:屏幕分辨率,屏幕缓冲区大小,刷屏函数,debug串口输出函数等
详细讲解:例如范例的配置,屏幕分辨率为320x240(宽320,高240),显示缓冲区“panel_buffer”为单行缓冲区(缓冲区大小都是屏幕宽度的倍数,最小1行即可,更大的缓冲区,渲染与刷新的速度会更加快,但考虑轻量级,单行缓冲区足够用),然后是刷屏函数,其实就是调用我们之前要求写的矩形区域填充函数,另外就是日志输出函数,该函数如果前期没有写好日志输出,不强制要求实现,“uart_put_string”可以为空函数,最后调用“sgl_init”即可完成初始化。
(6)SGL运行起来的必要调用
①初始化
②动画心跳
③SGL核心任务函数
如上图,“user_sgl_init”实际就为SGL的初始化,它位于屏幕初始化之后,然后周期性调用任务函数“sgl_task_handle”。
如上图,“sgl_anim_tick_inc”就是动画的心跳,需要在一个标准的定时器中断中调用,如systick,此处的systick配置的是1ms,动画tick函数的入参自然就是1。
看到了这里,恭喜你,已经完成了SGL的移植啦!后面就是添加自己需要的控件和功能进行测试了。
(7).编写测试代码
初始化完成以后,即可添加一些控件来看看效果了,注意,创建控件的代码一定是写在初始化之后(初始化完了才能创建控件)。
创建了一个圆角矩形,位置为0,0,大小为100x100,主题颜色为蓝色,圆角大小为20,透明度为127(满透明度为255),边框宽度为4,边框颜色为红色。
另外,我们再添加一个动画,动画的作用对象为创建的圆角矩形“rect2”,动画延时500ms,动画整个周期1500ms,动画化重复性设置-1代表一直重复,设置动画起始值0,动画结束值100,动画路径为一个函数“sgl_anim_path1”,动画算法采用“SGL_ANIM_PATH_LINEAR”,线性动画。
动画本质:动画实现的本质就是,起始设定值到结束设定值,在一段时间内的数值变化。如果设定值作用于坐标,其动画就变成控件的移动。
该demo的内存占用情况
(8).最终效果
下图gif就是我们创建的一个圆角矩形加上动画的效果,循环x轴方向移动。
效果2:下图的gif是另外一个复杂的测试demo,测试不同控件叠加渲染的能力,圆角矩形透明度设置的50%,可以透过圆角矩形看到底下的键盘。进度条和圆角矩形是同一个动画时基,都是1500ms,同步做动画。
(9).内存占用情况分析
这一部分来分析cw32l012移植sgl的内存占用情况
如上图,这是一份keil输出的map文件的截图(AC6编译,优化等级O1),图中包含了各部分部分的代码占用情况,cw32开头是官方的库文件,相比其他厂家的库来说,flash占用非常小。SGL开头是图形库,占用和你使用的控件有关,本demo只用了不到6k字节的flash空间(当然控件用的多了会占用比较多,但也不会超过32k,用LVGL是绝对不可能的事情)。
7.结语
好啦,看到这里就已经结束了,恭喜你又了解了一个GUI库,SGL是专门面向轻量级MCU开发的,它是一个长期的项目,会持续优化及更新。同时我们认为,好的代码一样是艺术品,开发这样的代码就是创造艺术品,使用这样的代码就是欣赏艺术品,人生不应得过且过,要有更高的追求。下面是一些题外话,有兴趣的读者可以继续看下去。
8.题外话
Q:这个效果也不行啊?为什么我感觉很卡?
目前的效果大家可能觉得很卡,其实主要是分配的资源问题,demo中缓冲区只用一行,320x2 = 640字节,要很流畅的话至少要10行的缓冲区,另外刷屏底层接口没有用DMA,也是慢的原因,再者,SGL核心任务调度每隔30ms调度一次,这也是不流畅的原因。
Q:为什么不把各项配置调到最好?
例如30ms调度周期降低到5ms,岂不是流畅的很?是的,的确,但是作为轻量级MCU,不应该这么做,因为你的性能有限不可能80%的性能都分配给图形库,要流畅缓冲区也可以加大,例如10行的缓冲区,光图形库RAM占用率可能就超过80%,其他的任务还跑不跑了?这里介绍的SGL库是有实际项目应用价值的,绝对不能是只能跑个demo的,停留在实验室的,博眼球的库,这样的库是没有意义的。
扫码加入QQ群,3群|?610403240
1318