在资源受限的MCU上实现平滑的电动车面板显示

cathy的头像
cathy 发布于:周四, 10/20/2022 - 09:36 ,关键词:

众所周知,一款优秀的产品,不仅要有很高的性能,很好的稳定性,而且还要具备对用户非常友好和极具吸引力的图形交互界面。

然而,运行一个非常酷炫且极具吸引力的图形用户界面,就要求有一个高主频,高性能,存储资源丰富的MCU作为支撑。 

恩智浦拥有众多高性能,低功耗,大容量存储资源的MCU/MPU, 在这样的MCU/MPU上,流畅地运行图形元素丰富,酷炫且富于吸引力的图形用户界面完全没有压力。

但是,在实际的客户支持过程中,我发现有一些客户基于成本的考虑,会选择主频相对低一些,存储资源相对少一些的MCU。与此同时,他们仍然希望给自己的产品赋予一个精美的图形界面。

 真实案例——电动车屏幕

因此,本文通过一个运行在LPC55S06上的,基于GUI Guider和LVGL的图形界面设计项目——电动车(简称EBike)为例,说明如何在资源有限的MCU上进行图形应用设计。

先睹为快,先给大家分享电动车的界面效果。通过向右滑屏可以切换到下一个屏幕,向左滑屏可以切换到前一个屏幕,向上滑屏可以返回至第一个屏幕,下面是演示视频:

查看视频.jpg

图片与字体的存储

在设计中, 电动车的GUI使用了大小为1.18MB的26个图片和大小为35KB的2种字体,共计约为1.22MB。

但事实上,LPC55S06的片上Flash容量为256KB,其中12KB为系统保留,可以为用户使用的Flash容量只有244KB,不可能将全部图片和字体存放到片上Flash中。

因此,为了能够容纳这些图片和字体,可以考虑外扩Flash。同时,为了兼顾显示性能,可以考虑将图片存放到外部串行Flash中,而将字体存放到片上Flash中。

归纳一下,在资源有限的MCU上进行图形界面开发,首先需要考虑的因素就是如何存储图片和字体。为了提高显示性能,可以把图片和字体尽可能放到片上Flash中存储。但是,随着开发的推进,用户会不断添加非图形界面业务逻辑。这时,如果遇到片上Flash存储空间不够的情况,可以将原本存放到片上Flash中的图片和字体放到外部Flash中,从而节省片上Flash存储空间给非图形界面业务逻辑使用。

存储区域的划分与分配

那么,这里存在一个关键问题,如何为图片和字体分配存储空间呢,依据什么原则呢?换句话说,哪些图片和字体存放到外部Flash,哪些图片和字体存放到片上Flash。

第一点,就是确保片上Flash可以容纳全部用户应用逻辑。

第二点,在满足第一点的情况下,将需要频繁刷新的图片保存到片上Flash。例如,视频所示界面中仪表盘的表针扫过的区域使用的图片,随着表针的转动,这些图片会不断地从外部Flash进行读取并被显示在屏幕上。

常见优化手段

除了将消耗片上Flash资源的大户放到外部Flash上,为了进一步减少用户应用对存储资源的消耗,一些优化手段也是必要的。

常用的优化手段包括如下几点:

  • 将经常需要调用的公共代码段封装成函数 

  • 调整编译优化等级。使用不同的编译优化等级编译生成的可执行文件大小是不同的,如果所选的编译器具有优化代码大小的编译优化选项,则可以通过使用该编译优化选项压缩可执行文件的大小,从而减少对Flash和RAM存储资源的占用。不同IDE中优化代码大小的编译选项如下所示。

1.png

图1 MCUXpresso IDE中的代码大小编译优化选项

2.png

图2 Keil uVision IDE中的代码大小编译优化选项

3.png

图3 IAR Embedded Workbench IDE中的代码大小优化选项

  • 通过LVGL的配置文件lv_conf.h跳过设计中没有使用的模块的编译。例如,在我们的设计中没有用到控件,如SWICH, TABLE, TABVIEW和TILEVIEW, 就可以将相应控件的开关宏定义为0,这样没有使用的控件对应的C文件就不会编译到最终的可执行文件中,从而减少代码的大小。

4.png

图4 裁剪LVGL功能

选择合理的屏幕加载策略

了解LVGL的小伙伴都清楚,GUI上的每一个图形元素,如按钮、图片、标签、表格等,都是作为一个对象存在的,都是需要消耗一定的RAM资源。

如果我们的GUI设计包含多个屏幕,每个屏幕都包含大量的图形元素,如果一次性的创建所有的图形元素,很可能有限的RAM资源不足以容纳这些图形元素。因此,合理的选择屏幕加载策略很有必要。

基于LVGL的GUI开发工具采用不同的屏幕加载策略。目前,屏幕加载策略有两种:

第一种是以LVGL官方推出的SquareLine Studio为代表的静态加载策略,即一次性地把所有屏幕上的图形元素全部创建。这可以从其生成的代码工程看到。

以SquareLine Studio的POS机界面示例为例,其UI初始化函数如下图所示。我们可以看到其5个屏幕一次性创建,那么就意味着这种静态屏幕加载策略消耗更多的RAM资源。

5.png

图5 SquareLine Studio的UI初始化

第二种是以NXP官方推出的GUI Guider为代表的动态加载策略,即只加载在系统启动后显示的屏幕,后面如果需要显示哪一个屏幕再动态加载。

下图所示是GUI Guider的官方示例ScreenTransition。这个示例总共有两个屏幕,即screen1与screen2。函数setup_ui是UI初始化函数。

可以看到,在UI初始化函数setup_ui中只是静态加载了屏幕screen1,没有加载screen2。只有当screen1的Next Screen按钮按下时,在事件回调函数screen_btn1_event_handler中才会调用setup_scr_screen2动态加载screen2。

6.png

图6 ScreenTransition示例的第一个屏幕

7.png

图7 ScreenTransition示例的第二个屏幕

8.png

图8 GUI Guider的UI初始化

9.png

图9 Next Screen按钮的事件回调函数

由此可见,NXP的GUI Guider的动态屏幕加载策略,充分考虑了在资源有限的微控制器上从事GUI开发时,遇到的存储资源利用效率问题。

当然,如果您所选择的MCU或者MPU的存储资源丰富,可以采用第一种策略,那样的话,可以能在一定程度上提高显示性能。

总结

本篇文章以一个GUI示例——电动车为例,重点关注如何在资源有限的微控制器上进行GUI开发,给出了图片和字体的存储策略,以及若干存储资源优化方法。

有关电动车的技术细节,可以参考AN13730: How to Develop LVGL GUI Demo on Memory-constrained MCU with GUI Guider.

来源:恩智浦MCU加油站

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 324