基于MCU平台的HMI开发的性能优化与实战(上)

news2024/11/22 13:33:13

随着汽车座舱智能化的不断演进,车内显示设备的数量显著增加,从传统的仪表盘和中控屏扩展至空调控制、扶手、副驾驶区域以及抬头显示(HUD)等多样化的显示单元。为了有效支持这些功能单元,同时控制整车成本,越来越多的汽车制造商开始采用微控制器单元(MCU)芯片。MCU以其低功耗、高集成度和经济性,成为降低成本的优选方案。

但由于平台的计算能力和存储空间受限,如何有效利用有限的资源来实现功能丰富、页面切换平滑的HMI应用变得至关重要。资源是否被合理的使用将直接影响应用的性能和用户体验。如果计算能力或存储空间使用不当,程序可能在PC上运行流畅,但在MCU上会遇到卡顿甚至崩溃的情况,无法满足设计目标。为应对此挑战,专为资源受限设备量身定制的工具——Qt for MCUs应运而生。凭借其极小内存占用和高度优化的库,Qt for MCUs旨在为MCU和低端MPU提供高性能HMI应用程序开发工具。采用Qt for MCUs在MCU平台上可以获得极佳的开发体验以及更好性能的HMI应用。

Qt for MCUs极大地减轻了开发人员在移植和调优方面的成本,但在资源受限的MCU平台上,性能优化始终是一项不可回避的挑战。

本文将基于Qt for MCUs工具,探讨如何通过精简代码、提升运行效率以及优化内存和资源管理等策略,来提高MCU平台下的HMI开发效率和应用性能。

一、降低代码量

减少代码量不仅能够降低程序对存储空间的需求,还能简化程序结构,使代码更加清晰。这有助于系统承载更多功能,同时还可以避免因内存不足导致的系统崩溃。简化的代码逻辑减少了CPU的分支判断,从而减轻了处理器的负担。此外,减少的运行时间还能降低能耗,并且有助于编译器更有效地优化代码,生成更高效的机器码。

在Qt for MCUs平台,我们推荐从以下三个方面对代码量进行优化:

1、减少锚点的使用

锚点是一种布局方式,用于将一个元素相对于另一个元素进行定位。

通过设置元素的anchors属性,可以将元素的边缘与其父元素或其他元素的边缘对齐。锚点可以在不同大小的屏幕上自适应,并且可以根据不同的屏幕方向进行动态调整。每个项目都可以被认为有一组 6 条不可见的“锚线”:

左 | 水平中心 | 右 | 顶部 | 垂直中心 | 底部

使用锚点进行开发虽然提供了布局的灵活性,但过度依赖它们可能会带来一些弊端。特别是在界面尺寸固定的情况下,锚点的动态计算过程不仅增加了代码的复杂度,还会带来不必要的性能开销。

通过直接指定坐标位置来替代部分锚点,可以简化代码结构,降低代码行数,从而提高代码的可读性和可维护性。

让我们通过一个简单的图形示例来比较 锚点定位 和 绝对定位 两种实现方式的不同。

下表左侧代码为绝对布局实现方式,右侧代码是锚点布局实现方式

import QtQuick

Item {

    id: root

    width: 500

    height: 200

    Rectangle {

        id: rect

        x: 50

        y: 50

        width: 200

        height: 100

        color: "#ED8E00"

    }

}

import QtQuick

Item {

    id: root

    width: 500

    height: 200

    Rectangle {

        id: rect

        anchors.left: parent.left

        anchors.top: parent.top

        anchors.leftMargin: 50

        anchors.topMargin: 50

        width: 200

        height: 100

        color: "#ED8E00"

    }

}

对比可以看出锚点布局的实现方式相较于绝对布局方式代码行数要多,且从代码逻辑上看,计算逻辑要更为复杂。

  1. 使用Repeater     

Repeater是Qt for MCUs提供的一个自动重复的功能组件。通过使用Repeater可以方便的创建多个相似的控件,而无需手动编写重复的布局和逻辑代码。这不仅可以减少代码量,还可以提高界面的一致性和可维护性。

import QtQuick

Item {

    .........

    //Column布局矩形元素竖向排列

    Column {

        spacing: 10 // 列元素之间的间距为10

        Repeater { // 用于重复生成元素

            model: 3 // 模型为3,生成三个矩形

            //delegate 定义了每个重复元素的模板,这里每个元素都是矩形

            delegate: Rectangle {

                id: rect

                width: 100

                height: 100

                color: getColor(index) // 使用预定义的函数获取矩形填充颜色

            }

        }

}

..........

}

通过上图的例子可以看出,创建三个矩形,我们可以通过将编辑好的矩形样式应用到Repeater内的组件中来实现,无需三次重复编写矩形控件代码和使用布局来设置它们的位置。同时还可以通过函数调用的方式为每个矩形设置不同的属性。这种方法不仅减少了代码量,还提高了代码的可维护性。

3、增加可复用组件

在UI界面开发中,经常会遇到默认的组件样式无法完全满足设计需求的情况。为了解决这一问题,我们可以将基础组件进行样式定制,以满足特定的设计要求。然后,将这些定制的组件封装到一个独立的文件中,创建为自定义组件。这样,我们就可以像使用官方组件一样,通过几行简单的代码来调用这些封装好的自定义组件。这种方法不仅提高了代码的复用性,减少了冗余,也提升了整体的代码质量,如下图所示。

除了提取重复使用的组件样式代码外,我们还可以通过将多处出现的逻辑代码抽取并封装到单独的文件中,实现代码的集中管理和统一维护。

二、提高运行效率

提升运行效率能够显著加快系统的响应速度,从而增强用户的使用体验。我们可以通过以下四种策略来提高运行效率:

1、减少动态绑定依赖次数

如图所示,当属性与其他属性绑定并形成依赖关系时,若属性值发生变化,依赖属性会被标记为“脏”状态。随后,系统会触发并处理所有标记为“脏”的事件,确保依赖属性能够及时更新其值。这种动态更新机制虽然有效,但其复杂的依赖管理和事件处理过程可能会导致性能下降。通过减少不必要的动态绑定和依赖次数,我们可以降低属性刷新的频率,进而提升系统的运行效率。

2、修改控件源代码

修改Qt for MCUs的控件源代码,可以暴露更多的控制接口,从而能够更直接地操作控件的属性和行为,减少中间层的开销,提高运行效率。

3、错峰加载与预加载

Loader是Qt for MCUs中用于加载UI资源的组件。修改Loader的加载策略可以有效平衡性能消耗,减少资源加载期间的卡顿现象。

错峰加载策略:分散资源或任务的加载时间

系统启动时可能会因资源争用而遇到性能下降或崩溃的问题。通过实施错峰加载机制,我们不是同时加载和初始化所有模块或任务,而是按计划的顺序和时间间隔分批进行。这种方法可以缓解启动时的资源竞争和高负载,确保系统的平稳运行。

预加载策略:提前加载资源或执行任务

提前加载资源

预加载策略指的是在页面实际显示给用户之前,就预先加载未显示的页面。这样做可以防止在页面加载过程中出现空白屏幕,从而提升用户体验。

为了实现系统性能的优化和用户体验的提升,我们需要根据具体状况,选择最合适的加载策略。

4、局部数据刷新

全局数据刷新会触发整个界面的重绘,造成不必要的性能损耗。通过改进刷新策略,采用局部配置数据刷新代替全局刷新,可以只更新界面中需要变化的部分,减少不必要的渲染工作,从而提高运行效率。

全局刷新

局部刷新

如上图所示,当数据发生变化时,首先进行数据对比,有数据变化的部分重新加载刷新数据,无数据变化的部分保持不变,无需再次加载,减少了渲染操作,提高了运行效率。

三、内存管理

高效的内存管理对于提升HMI的应用性能和稳定性至关重要。它有助于减少内存碎片、加快访问速度、降低分配成本、防止内存泄漏,并优化内存使用。在资源受限的MCU环境中,可以确保HMI应用的流畅运行。我们提供三种关键的内存管理策略,旨在优化内存使用。

1、单例模式

单例模式是一种设计模式,它保证一个类在整个应用中只有一个实例,并且提供了一个统一的访问点。这种模式通过一个特定的类来实现,这个类负责自己的实例化,并且保证只实例化一次。它允许我们直接访问这个唯一的实例,无需通过常规的实例化过程。这有助于降低系统复杂性,提高性能,并节省宝贵的资源。

2、内部申请机制

我们采用统一且预定义的内存管理机制,有效预防出现内存泄漏、碎片化和过度分配等问题。

上图展示了FreeRTOS中pvPortMalloc的内存分配流程,这是FreeRTOS为动态内存分配特别设计的函数,与标准C库中的函数类似,但专为FreeRTOS的任务调度和内存管理机制优化。FreeRTOS提供了五种内存管理方案:

  1. heap_1:最基础的实现,不支持内存释放。
  2. heap_2:支持内存释放,采用简单的连续内存分配算法,可能产生内存碎片。
  3. heap_3:使用标准库的malloc()和free()函数,依赖于标准库的实现。
  4. heap_4:提供最佳平衡,采用首次适应算法,并通过合并空闲块减少碎片化。
  5. heap_5:最灵活,支持多个独立堆区域,适合复杂内存管理场景。

开发者可以根据设备条件和需求选择最合适的内存管理方案。

3、内存池技术

内存碎片是嵌入式系统中普遍存在的问题,尤其是在频繁申请和释放小块内存时更为明显。内存池技术通过预先分配一定数量的小块内存,并在程序运行期间循环使用这些内存块来解决这一问题。需要内存时,直接从内存池中获取;不再需要时,则将其返还给内存池,而不是释放回系统。这种方法减少了内存的频繁分配与释放,有效防止了内存碎片的产生。此外,内存池还有助于优化内存对齐,进一步提升内存的使用效率。

如上图所示,程序启动时,我们预先分配一定数量的固定大小内存块。在申请内存时,直接从这些预分配的块中获取;释放内存时,则将其放回预分配的块中,以便再次使用。每个内存池针对特定的使用场景设计,与传统的malloc/free相比,它减少了复杂的逻辑处理,可以显著提高性能。

四、资源管理

资源管理的核心在于优化图片资源的性能,我们采用以下三种策略来应对系统对图片资源的各种需求,目的是不影响用户体验的前提下,降低图片存储的开销。

1、BorderImage

BorderImage属性允许在用户界面中绘制可伸缩的边框图像,非常适合创建大小可变且边缘不失真的UI元素,例如按钮、面板和背景。当处理图像内容简单(如纯色图片)时,BorderImage可以替代传统的Image属性。它能够无损放大图像边缘,防止拉伸时的失真,同时减少了存储空间中不必要的像素数据。在某些特殊场景下,这种方法几乎可以避免图像质量损失,具体效果如下方图示。

2、ColorizedImage

ColorizedImage组件用于展示图片并应用颜色遮罩,能够将指定颜色应用于原始图像,从而生成具有不同色彩效果的图像。当面对内容相同但颜色各异的大量图像时,ColorizedImage提供了一种高效的解决方案:只需存储一张基础图片并进行动态上色,这样可以大幅减少因颜色不同而需存储的多张图片所占用的存储资源。然而,这种方法在执行效率上可能略低于直接使用Image,因此更适合于小型图标以及显示数量较少的场景,具体效果可以参考以下图示。

3、降低图片编码渲染格式

Qt for MCUs针对图片资源提供了多种格式选项,允许开发者根据不同场景和图片特性选择最合适的格式,以优化存储效率。每种图片格式都有其特点和占用空间大小,合理选择格式有助于在图片资源的存储优化和MCU的计算能力之间找到最佳平衡点。

图像格式

格式描述

清晰度描述

像素占用

ARGB8888

拥有透明度、红、绿、蓝四个通道,每个通道占用8位

可最大化保证图片质量和原图一致

32

ARGB4444

拥有透明度、红、绿、蓝四个通道,每个通道占用4

将会损失绝大部分的色彩细节,在复杂图像肉眼可明显感受到失真

16

RGB888

拥有红、绿、蓝三个通道,每个通道占用8位

可最大化保证图片质量和原图一致,但无法实现显示透明像素的效果

24

RGB565

拥有红、绿、蓝三个通道,其中,红色和蓝色通道占用5位,绿色通道占用6

可在图像质量和图像大小之间取得较好的平衡,对于复杂色彩的图像可能失真,但肉眼感知不明显

16

RGB444

拥有红、绿、蓝三个通道,每个通道占用4位

将会损失绝大部分的色彩细节,在复杂图像肉眼可明显感受到失真且无法显示透明像素效果

12

通过在合适的场景下使用适合的图片存储格式可平衡显示效果和存储、加载的空间占用,如下图所示,上方图片为在RGB444下的显示效果,下方图片为在RGB888下的显示效果,在色彩丰富的情况下可明显看出两者的区别,但同大小图RGB888的存储占用是RGB444的2倍,但在图像颜色简单的情况下者区别肉眼 

本文深入探讨了使用Qt for MCUs进行HMI应用开发时,通过优化代码、提升运行效率、管理内存以及合理使用资源来提高应用性能的策略。这些优化措施使开发者能够在资源有限的MCU平台上构建高效且功能丰富的HMI应用,确保用户获得流畅、稳定的操作体验。随着技术的不断发展,我们将探索和分享更多的优化方法,进一步提升MCU平台上的HMI应用性能。

下一章,我们将结合实际案例,深入开展Qt for MCUs的实战演练,通过具体示例详细讲解HMI开发过程中的各项优化策略的应用及其效果,帮助开发者全面掌握通过Qt for MCUs来进行HMI开发的实战开发技巧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1831367.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从WWDC 2023看苹果的未来:操作系统升级与AI技术的融合

引言 在2024年的WWDC(苹果全球开发者大会)上,苹果公司展示了一系列创新技术和产品,其中最引人注目的莫过于操作系统的升级与AI技术的深度融合。作为一个备受期待的发布会,WWDC不仅向我们展示了苹果在技术上的前瞻性布…

Python发送电子邮件的步骤流程?如何设置?

Python发送电子邮件如何实现自动化?邮件发送的方法? 无论是自动化通知、日常业务沟通,还是营销活动,Python都能为我们提供强大的支持。使用Python发送电子邮件不仅方便快捷,还可以自动化日常任务。AokSend将详细介绍使…

leetcode 1355 活动参与者(postgresql)

需求 表: Friends ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | | activity | varchar | ---------------------- id 是朋友的 id 和该表的主键 name 是朋友的名字 activity 是朋友参加的活动的名字 表: Activit…

利用CNN识别英文语音数字

问题总述 任何一个数字,都是由10个基数构成的,本任务目的是借助于机器来实现英文语音数字的识别。下面,利用语音特征提取技术和卷积神经网络模型,对英文语音数字进行识别以解决上述问题。 步骤一:提取音频文件的语音…

总结之Docker(四)——镜像修改非ROOT用户权限后生成新镜像并发布

Docker拉去目标镜像 docker pull redis:6.2.5如果出现拉去过程超时,或者连接失败。 添加镜像加速器,以阿里云为例,阿里云目前推广提供镜像加速器,需要登录。 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 生成…

有没有和ai聊天的软件?介绍这三款聊天软件

有没有和ai聊天的软件?在科技飞速发展的今天,人工智能(AI)已经渗透到我们生活的方方面面,其中AI聊天软件以其独特的魅力,赢得了越来越多用户的青睐。今天,我们就来一起探索三款智能聊天软件的功…

【Java】已解决:java.lang.NoSuchMethodError异常

文章目录 一、问题背景二、可能出错的原因三、错误代码示例四、正确代码示例 已解决java.lang.NoSuchMethodError异常 一、问题背景 java.lang.NoSuchMethodError异常是Java运行时环境中一个常见的错误,它通常发生在尝试调用一个不存在的方法时。这个异常通常不是…

Unity制作背包的格子

1.新建一个面板 2.点击面板并添加这个组件 3.点击UI创建一个原始图像,这样我们就会发现图像出现在了面板的左上角。 4.多复制几个并改变 Grid Layout Group的参数就可以实现下面的效果了

战略网络优化:网络可观测性的综合方法

在网络成为运营支柱的时代,了解和优化网络性能至关重要。网络可观测性是了解网络性能的关键,它以一种全面、主动的方式超越了传统监控。本文说明了网络可观测性的变革力量,详细介绍了其优势、差异化因素及其在现代网络管理中的关键作用。 什…

2024年下一个风口是什么?萤领优选 轻资产创业项目全国诚招合伙人

2024年,全球经济与科技发展的步伐不断加快,各行各业都在探寻新的增长点与风口。在这样的时代背景下,萤领优选作为一个轻资产创业项目,正以其独特的商业模式和前瞻的市场洞察力,吸引着众多创业者的目光。(领取&#xff…

专业酒窖的布局与设计:为红酒提供理想保存条件

对于云仓酒庄雷盛红酒的爱好者而言,拥有一个专业的酒窖是保存和欣赏这些珍贵佳酿的方式。一个布局合理、设计精良的专业酒窖不仅能提供稳定的保存条件,还能确保红酒在理想状态下陈年,释放其深邃的香气和口感。 首先,酒窖的位置选择…

40、基于深度学习的线性预测设计(matlab)

1、原理及流程 深度学习的线性预测是一种利用深度神经网络模型进行线性回归预测的方法。其设计原理主要基于神经网络的层次化特性,利用多层感知器(MLP)等模型进行特征学习和非线性变换,从而提高线性预测的准确性。 设计流程如下…

HTTP/2 协议学习

HTTP/2 协议介绍 ​ HTTP/2 (原名HTTP/2.0)即超文本传输协议 2.0,是下一代HTTP协议。是由互联网工程任务组(IETF)的Hypertext Transfer Protocol Bis (httpbis)工作小组进行开发。是自1999年http1.1发布后的首个更新。…

第04章:IDEA的安装与使用

第04章:随堂复习与企业真题(IDEA安装与使用) 一、随堂复习 1. IDEA的认识 IDEA(集成功能强大、符合人体工程学(设置人性化))Eclipse 2. IDEA的下载、安装、卸载 卸载:使用控制面板进行卸载,…

Vue 使用setInterval定时器导致前端页面卡死(解决方法)

Vue 使用setInterval定时器导致前端页面卡死 原因 setinterval不会清除定时器队列,每重复执行1次都会导致定时器叠加,最终卡死你的网页。 其原因与JS引擎线程有关(需深入研究JS引擎线程) ,但是setTimeout是自带清除定…

深度学习网络结构之---Inception

目录 一、Inception名称的由来 二、Inception结构 三、Inception v2 四、Inception v3 1、深度网络的通用设计原则 2.卷积分解(Factorizing Convolutions) 3.对称卷积分解 3.非对称卷积分解 五、Inception v4 一、Inception名称的由来 Inception网…

Python MongoDB 基本操作

本文内容主要为使用Python 对Mongodb数据库的一些基本操作整理。 目录 安装类库 操作实例 引用类库 连接服务器 连接数据库 添加文档 添加单条 批量添加 查询文档 查询所有文档 查询部分文档 使用id查询 统计查询 排序 分页查询 更新文档 update_one方法 upd…

Spring IoC【控制反转】DI【依赖注入】

文章目录 控制反转(IoC)依赖注入(DI)IoC原理及解耦IoC 容器的两种实现BeanFactoryApplicationContext IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想&…

碉堡了!云原生大佬撰写的K8s学习指南,有点炸裂,建议运维都收藏!

在这个数字化转型的时代,容器化和云原生技术已成为软件开发的重要趋势。【Kubernetes】作为云原生领域的旗舰项目,不仅是一种容器编排工具,更是构建现代、弹性和可扩展应用程序的基础平台。 因此,对于运维人员来说,学…

裁剪图片的最简单方法?这四种裁剪方法真的超级简单!

裁剪图片的最简单方法?在丰富多彩的现代生活中,图片成为了我们表达、沟通甚至展示身份的重要媒介,然而,无论是出于个人审美还是专业需求,图片的格式和尺寸往往成为了我们不得不面对的问题,特别是那些未经雕…