2222xb:是STM32单片机项目实战TouchGFX的智能手表2GUI界面设计基础

一、 GUI界面基础

在进行TouchGFX相关工具使用与界面开发前,对GUI界面的基础知识进行整理与学习,该节的内容主要来源TouchGFX社区(点击进入社区),社区提供了TouchGFX基础信息和安装指南、基本概念(介绍关键图形概念)、开发(如何开发TouchGFX应用,包括结构、工作流和工具)、教程(TouchGFX教程集合)等方面的文档教程。

1.1.1 嵌入式绘图系统

<嵌入式绘图系统>一词有许多种含义。首先,不同的人对<嵌入式系统>一词有不同的理解,对于有些人来说,嵌入式系统意味着以微控制器、微处理器为中心的软硬件系统。 也可能意味着功能强大的现代智能手机。

其次,“绘图系统”一词有许多种解释。 对有些人来说,它表示在喜欢的绘画程序中绘制像素。 对其他人来说,它表示游戏机上运行的3D渲染软件。

对TouchGFX而言,嵌入式系统表示STM32微控制器上的任意系统。 绘图系统表示有用户界面的运行频率为60帧每秒的交互式应用。

为了在嵌入式系统上实现绘图应用,我们考虑四个直接相关的主要组件。当然,嵌入式系统可能包含许多其他组件,但其他组件与图形显示的相关性较小。

图 2-1 MCU、RAM、闪存和显示屏

简而言之,TouchGFX使用MCU,通过对闪存中的各个部分进行组合,创建和更新RAM中的图像。组合图像会被传输到显示屏。系统会视需要尽可能多地重复此过程。

微控制器(MCU)

在这个过程中,MCU承担了所有的重要任务。它读取闪存中的图像,并将它们写入RAM。将半透明红色文本融合到图像上时,它计算得到的色彩并将其存储到RAM。 对圆的所有像素进行渲染并存储到RAM。 将图像从RAM传输到显示屏。

图 2-2 MCU提供CPU、内部闪存和内部RAM等

STM32系列MCU具有特定功能,如LTDC、Chrom-ART、Chrom-GRC等,为绘图系统的实现提供帮助。

RAM

所得计算图像(帧缓冲)存储在RAM中。 在更新图形时,MCU对RAM执行读和写操作。在将图像传输给显示屏时,再次对RAM执行读操作。

在多数情况下,所得图像被存储在MCU内部的RAM中。如果将所得图像存储在内部RAM中的方法不可行,可以添加外部RAM。

Flash

所有静态数据均存储在闪存中,例如:图像、字体和文本。闪存由MCU读取,其内容被写入RAM或与RAM内容进行组合。

在大多数情况下,由于内部闪存很少能够容纳下所有图像资源,因此设置中会增加外部闪存。对于十分简单的应用,内部闪存可以满足需求。

理想的做法是对闪存进行存储器映射(STM32U575支持存储器映射),以便从闪存直接读取像素并写入RAM。或者,如果不对闪存进行存储器映射(STM32G070采用SPI接口读写),可将闪存内容传输到RAM,然后再从RAM读取。

显示

显示屏将图像实际显示给人眼。RAM中存储的计算后的图像(帧缓冲)由MCU按固定时间间隔发送到显示屏。

1.1.2 色彩格式

色彩是由显示屏的像素呈现出的样子。这些色彩来自帧缓冲存储的值。在传统意义上,绘图系统中能够表现、使用和显示的色彩数量是有限的。这同样适用于TouchGFX和TouchGFX应用。

像素色彩数量会影响到应用的许多方面。从显示屏上看到的实际内容到帧缓冲所需的内存消耗,以及整体性能。 本节将进一步介绍TouchGFX中的色彩和可用的色彩格式,并指出其优缺点。

色彩

TouchGFX中的色彩是红、绿和蓝分量的三元组,即RGB色彩。每个色彩分量的范围为0至255。0表示该分量无作用,255表示该分量处于最大值。全黑色表示为RGB色彩 (0,0,0),全白色表示为 (255,255,255)。 亮绿色为 (0,255,0),半亮红为 (128,0,0),暗紫色为 (64, 0,64),诸如此类。

图 2-3 部分RGB色彩

灰度

灰度应用的所有色彩均为灰色,包括从黑色到白色之间的所有灰色,因此用灰色强度(而不是RGB值)表示。 可将灰度色彩理解为R = G = B的RGB色彩。

不透明度

在某些情况下,我们会考虑为色彩增加一个描述色彩不透明的分量。与色彩的其他分量一样,不透明度的范围为0至255。有不透明度的色彩称为RGBA色彩。A表示alph,是不透明度使用的传统名称。

完全不透明的黑色表示为 (0,0,0,255),有一些透明的红色表示为 (255,0,0,128),诸如此类。

图 2-4 白色和灰色之上的一些RGBA色彩

当色彩并非完全不透明时,需将它与已存在的色彩进行混合。这种色彩混合称为Alpha混合。

色深

色深是指帧缓冲存储的用于描述每种色彩的位数。我们将该值表示为每像素位数,简称bpp。使用的位数越多,可描述的色彩越多。常用的色深为24 bpp。由于每一位都可以是有或无,这表示可以呈现224 = 16777216种不同色彩。另一个较少使用得稍色深是1 bpp。此色深适用于黑白应用,只能呈现21 = 2种不同色彩。

TouchGFX支持下列色深:

32 bpp - 16777216种色彩及相应不透明度值

24 bpp - 16777216种色彩

16 bpp - 65536种色彩

6/8 bpp - 64种色彩

4 bpp - 16种灰度色彩

2 bpp - 4种灰度色彩

1 bpp - 2种灰度色彩

关于色彩分量范围的注释。当使用的色深小于24 bpp时,红、绿和蓝分量中每一个的范围并不直接取0至255。 以16 bpp的红色分量为例,范围为0至31。 我们将值31视为16 bpp色深时能够表现的最红的色彩,即24 bpp色深时的值255。 一种理解方式是16 bpp色深的色彩只是24 bpp色深可能表现的色彩的一个子集。

在6/8 bpp色系中,每个像素使用6位表示色彩信息(2位分别表示红色、绿色和蓝色)。 为了简化帧缓存访问,每个像素从6位增加至8位(1字节)。 帧缓存中多余的两位未使用。

格式

在确定表示色彩所需的位数后,我们进一步研究位的内容。色彩通过位来描述红色、绿色和蓝色,但色深本身并不能指定像素中位的顺序(格式)。 例如: 先是蓝色,再是绿色,接着是红,或者顺序相反。

像素色彩格式

根据应用的色深,可使用某些特定的色彩格式。

RGB888

在TouchGFX中,色深为24 bpp的色彩的色彩格式为RGB888。 这意味着对红、绿和蓝分量中的每一个使用8个比特位。以亮紫色RGB (255,0,255) 为例,通过将分量组合成一个色彩值来表示这种色彩。

uint32_t brightPurpleRGB888 = 255 << 16 | 0 << 8 | 255 << 0;

在这种格式中,红色位于最高的8位,然后是绿色,蓝色位于最低的8位。

RGB565

TouchGFX对16 bpp色彩使用色彩格式RGB565, 即红、绿和蓝色分别为5位、6位和5位。 由于红色有5位,完全亮起为31,因此代码中的亮紫色。

uint16_t brightPurpleRGB565=31<<11|0<<5|31<<0;

RGBx2222, xRGB2222,BGRx2222,xBGR2222

对于6 bpp色彩,TouchGFX支持4种不同色彩格式:RGBx2222、xRGB2222、BGRx2222和xBGR222。 前述格式中之所以有x,是因为6位色彩按字节的形式存储。 为了构成字节,用2个比特位填充色彩。 同时提供RGB和BGR是考虑到一些显示屏的需要,这样则无需在向显示屏发送像素前转换像素。 在RGBx2222模式下,表示亮黄色的代码如下。

uint8_t brightYellowRGBx2222 = 3 << 6 | 3 << 4 | 0 << 2;

GRAY4,GRAY2,BW

对于每种灰度色深,TouchGFX都相应的支持其对应的色彩格式。4 bpp的色彩格式表示为GRAY4,2 bpp为GRAY2,1 bpp为BW(表示黑色和白色)。对于4 bpp,全白色为。

uint8_t whiteGRAY4 = 15;

TouchGFX有一项辅助功能,可返回色彩在当前色彩格式下的正确表示方法。

#include <touchgfx/Color.hpp>...aColor = Color::getColorFromRGB(255,0,128);

图像格式

图像是大多数UI应用的重要部分,图像由色彩填充而成。在TouchGFX中,图像存储在存储器中,由特定格式的色彩填充而成。在许多情况下,图像使用支持的像素色彩格式中的一种,但也可以使用其他图像格式。在绘制前,特定图像色彩格式下的图像中的像素会被转换为合适的像素格式。

图 2-5 图像色彩格式

这些图像格式中的一些格式(L8)按照色彩查找表(称为CLUT)来呈现相关图像并索引到该表中。L8图像中色彩数量的最大可能值为28 = 256。L8格式占用的空间比非L8格式少,以包含200种不同色彩的100 x 100图像为例,存储为ARGB8888格式时的空间占用量为100 x 100 x 32位 = 40000字节,存储为L8_ARGB8888格式时为100 x 100 x 8位 + 200 x 32位 = 10800字节。

图像格式BW_RLE按连续的黑色和白色存储色彩,而不是存储单一像素色彩。在许多情况下,这种格式也可以更高效地利用存储空间。其余格式与以上像素色彩格式相同。

帧缓存格式

并非所有图像格式都可用作帧缓存格式,L8格式不能用作TouchGFX中的帧缓存格式,因为无法在帧缓存中混合两个图像。

字节和像素顺序

通常使用字节指针访问24位格式RGB888和32位格式ARGB888。此时,须了解像素以小端顺序存储。

以32位色0xFFFF7700为例(alpha=0xFF,红色=0xFF,绿色=0x77,蓝色=0x00)。 当色彩位于32位变量或寄存器中时,值为0xFFFF7700。 当色彩存储在内存中时,存储的字节为{0x00、0x77、0xFF、0xFF},这与BGRA顺序对应。

同样,16位格式RGB565始终通过16位指针访问,因此字节顺序并不重要,但会在内存中交换。

对于8位格式,例如:ARGB2222,该色彩适合一个字节(两个最高位中的alpha),字节存储不变。

较小格式GRAY4、GRAY2和BW可按两种顺序存储。低位可以是最左边的像素或最右边的像素。如果低位是最左边的像素,我们称之为LSB模式,反之则为MSB模式。

图 2-6 帧缓冲格式

文本格式

文本,更准确地说是字形,也以特定色彩格式存储在存储器中。TouchGFX中可供使用的文本色彩格式为。

图 2-7 文本色彩格式

字形格式犹如小幅图像,每个色彩条目都存储了每个像素的不透明度。因此,之后不仅能应用实际色彩以及红、绿和蓝分量,还能绘制如存储字形“A”的蓝色和红色版本。

每个字形使用的位数越多,通常就会显得越平滑和美观

视觉质量

对于嵌入式图形,我们希望获得最高视觉质量,但同时也需考虑内存的消耗量。

因此,通常趋向于使用RGB565色彩格式,而不是内存消耗量更大的RGB888色彩格式,一般而言,应在考虑存储需求的同时选择视觉质量最高的色彩格式。

抖动

在不同色彩格式下呈现图像时,TouchGFX使用抖动技术来改善图像的视觉质量。抖动是一项广为人知的技术,它让图像的色彩看起来比实际色彩更丰富。 这是通过增加图像色彩的噪声来实现的。

例如,在将RGB888图像转换为RGB565图像时,不是简单地对每个色彩分量的低位进行斩波,而是在转换过程中为得到的每种色彩添加一些噪声,从而使转换后的图像看起来与原始RGB888图像相似但更丰富。

图 2-8 转换后的有和没有抖动的xRGB2222图像

由此可见,抖动可显著改善图像的感知质量。在近距离观察有和没有抖动的RGB565图像时,可以看到有抖动的图像与原图像几乎完全相似,而没有抖动的图像的一些区域则存在明显的色带。这表明在许多情况下,用16位色彩足以获得看起来不错的界面。

性能

讨论的所有图像格式均针对绘制的“易用性”进行了优化。这意味着可以将图像或多或少地复制到帧缓冲,无需进行大量转换。这是有意为之,是TouchGFX能够在微控制器上获得流畅图形的原因之一。

在用TouchGFX设计UI时可使用.png图像,在编译时,会将每一幅图像转换为上述高效的图像格式中的一种。

Alpha混合

在运行时间,图像数据的复制是通过常规CPU复制操作或使用MCU特性来完成的。如果图像包含不完全透明或不透明的像素,则需要用alpha混合技术将像素混合到背景上。 在一些STM32 MCU中,硬件支持这种混合功能。

1.1.3 帧缓冲区

帧缓冲是存储器的一部分,图形引擎通过更新帧缓冲,将需要显示的下一帧图像包含进来。帧缓冲是RAM的一个连续部分,可以根据需要设定合适的大小。

图 2-9 帧缓存空间

帧缓冲具有相应的宽度和高度。因此,我们通常将帧缓冲视为存储器的一个二维部分,可通过x、y坐标检索。

图 2-10 2D帧缓存空间

帧缓冲具有相应的色彩格式。帧缓冲中的每个条目都是该色彩格式下的色彩。我们将帧缓冲中的每一个这样的条目称为像素。通过计算帧缓冲中像素的存储地址和更新存储的色彩,可以更新帧缓冲中位置 x,y 处的像素色彩。

uint32_t pixelAddress = x + y * WIDTH;framebuffer[ pixelAddress ] = newColor;

同样地,我们可以获取帧缓冲中像素的色彩并用在计算中。例如,暗化帧缓冲中像素的色彩(假设有暗化函数可用)。

uint32_t pixelAddress = x + y * WIDTH;framebuffer[ pixelAddress ] = darken( framebuffer[ pixelAddress ] );

对于帧缓冲存储器,通常不会如前文所述逐一读写像素,而是利用系统的底层硬件功能(如Chrom-ART DMA)进行读写。

色彩

在TouchGFX中,帧缓冲的像素色彩格式可以是:

灰度1、2或4位每像素(bpp)灰度

高/真彩16、24或32 bpp色彩

每个像素使用的位数越多,帧缓冲能够呈现的颜色就越清晰,此外,每个像素使用的位数越多,帧缓冲消耗的存储空间就越多。

显示屏

帧缓冲的内容最终会被传输到并显示在物理显示屏上。因此,帧缓冲与显示屏的像素宽度和高度相同是十分常见的。

图 2-11 24bpp帧缓冲内容和显示屏显示内容

帧缓冲的位置

下面是一个基于微控制器的绘图系统的极简图。

图 2-12 绘图系统简图

帧缓冲可以位于MCU内部或外部RAM中。

图 2-13 帧缓冲的可能位置

每个可能位置都具有潜在的优势和不足。

内部RAM

如果帧缓冲位于MCU内部的RAM中,对帧缓冲的读和写访问会尽可能快地完成。这意味着TouchGFX应用的运行会非常流畅。反过来,部RAM是十分稀少的资源,被系统的许多部件使用,因此,帧缓冲大量占用内部RAM也许不可行。

如果可行,由于无需额外的RAM,在内部RAM中提供帧缓冲可以降低系统的总体成本。

外部RAM

如果系统有外部RAM,可以选择在外部RAM而不是内部RAM中提供帧缓冲。对外部RAM的读和写访问通常会比内部RAM慢,但外部RAM的空间量通常大得多。因此,有时候这是唯一可行的解决方案。MCU可能具有一些功能(如缓存),可加快外部RAM的访问速度。

自带RAM的显示屏

显示屏上可能嵌入了存储器,具体取决于系统中显示屏的类型。这段存储空间用来保存显示屏“实际”像素的内容。显示屏中保存像素的存储空间,意味着在显示屏仍活动时,MCU可能处于空闲状态。

由于显示屏存储器并非存储器映射,既不打算也不适合用于像素的随机读取或写入,因此不可能将TouchGFX帧缓冲放在在显示屏自带的RAM中。 相反,TouchGFX将帧缓冲置于内部或外部RAM中,并在适当的时候将其传输到显示屏RAM。

帧缓冲的数量

TouchGFX可在应用中使用一个、多个或不足一个的帧缓冲。帧缓冲的数量会影响应用的视觉表现、性能和存储空间消耗。

一个帧缓冲

一个帧缓冲足以完全容纳要传输到显示屏的所有像素。当板上的显示屏没有自带RAM时,需要(至少)一个帧缓冲。在这种情况下,如果所显示图形的复杂度不会产生任何视觉失真,则只需一个帧缓冲。

多于一个的帧缓冲

在TouchGFX中,具有多个帧缓冲表示有两个帧缓冲。一个帧缓冲用于写入下一幅需要显示的图像,另一个帧缓冲用于将图像传输到显示屏。这意味着不会发生失真(如撕裂)。

少于一个的帧缓冲

少于一个的帧缓冲通常意味着:

消耗的存储空间较少;

将执行更多绘制操作;

需要向显示屏传输更多内容;

在TouchGFX中,不足一个的帧缓冲表示部分帧缓冲。部分帧缓冲方案只适用于具有自带显示RAM的显示屏。

存储空间消耗

帧缓冲中的色彩数量和像素数量决定了帧缓冲消耗的存储空间。

帧缓冲使用的存储空间通常为:宽 * 高 * 以位数计的色深 / 8 字节数。

图 2-14 不同屏幕的存储空间

当具有一个以上的帧缓冲时,消耗的存储空间相应地较大。例如,当使用双重缓冲方案时,使用两个帧缓冲会消耗两倍的存储空间。

当帧缓冲不足一个时,由应用明确地分配和控制存储空间的量。因此,存储空间的消耗量是完全可定制的,但应注意的是,使用量过少会影响整体图形性能。

1.1.4 图形引擎

TouchGFX图形引擎的主要用途是在嵌入式设备的显示屏上绘制图形。本节将提供TouchGFX图形引擎类型的概述及其工作原理的一些背景知识。

场景模型

图形引擎主要可分为两类。

即时模式图形引擎提供一个API,使应用能够直接为显示屏绘制图像。应用负责确保在正确的时间激活正确的绘制操作。

保留模式图形引擎使用户能够操纵所显示组件的抽象模型。引擎负责在合适的时间将此组件模型转化为正确的图形绘制操作。

TouchGFX遵循保留模式绘图原则。 简而言之,TouchGFX提供用户可操纵的模型,然后TouchGFX负责将此模型转化为渲染方法调用的优化集合。

图 2-15 保留模式图形引擎

TouchGFX的保留模式图形引擎有许多优势。 主要包括:

易用性:保留图形引擎易于使用。用户通过调用内部模型上的方法直接在屏幕上对组件进行配置,而不考虑实际的绘制操作。

性能:TouchGFX分析场景模型,并优化在屏幕上实现模型所需的绘制调用。这包括特意不绘制隐藏组件,只绘制和传输组件有变化的部分,以及管理帧缓存等。

状态管理:TouchGFX持续跟踪场景模型中的活跃部分。这反过来为用户优化场景模型内容提供了便利。

TouchGFX保留模式图形方案的主要不足在于:

存储空间消耗:呈现场景模型会占用一些存储空间。TouchGFX通过分析场景模型和优化相应渲染成果达到其性能水平,通常每秒渲染60帧。为了减少TouchGFX场景模型使用的存储空间,设计者做了大量工作。在典型应用中,该模型所需的存储空间远低于1千字节。

1.1.5 主循环

许多游戏引擎和图形引擎的工作方式(特别是TouchGFX)都可以看作是无限循环。TouchGFX的主循环中有三种主要活动:

采集事件:采集触摸屏事件、物理按钮按下事件和来自后台系统的消息等。

更新场景模型:对采集的事件做出响应,更新模型的位置、动画、色彩和图像等。

渲染场景模型:重绘模型中已更新的部分,并使之显示在显示屏上。

主循环的图解版本:

图 2-16 主循环

主循环的每次执行都表示应用的一个tick。

1.1.6 操作系统

嵌入式设备越来越先进,系统的大部分设备不仅处理图形用户界面,通常还处理复杂的控制算法和任务。举例来说,这些任务可以是电机控制、数据获取或安全相关任务。许多先进设备包含用来与数据中心通信的通信协议栈(如TCP/IP)或用来与其他本地设备通信的射频协议栈(如蓝牙)。

其他任务与用户界面的交互,在具有图形用户界面并只支持几项简单任务的简单设备中,可围绕用户界面代码构建整个应用。 除了常规的用户界面升级,应用执行的任务非常少,因此可将其他任务的执行相当成功地嵌入用户界面代码。

当设备包含具有独享时序要求的更高级的“后台运行”功能(如调制电机)时,将很难将这两个任务合二为一。图形引擎必须持续绘制新帧,才能支持流畅的用户界面。 如果在运行其他任务时需要暂停图形引擎任务的运行,帧率将会下降。 同样地,如果其他任务只在帧间、空闲时间运行,那么在用户界面渲染复杂场景时,由于空闲时间较少,这些任务会受到影响。 这些影响使得UI任务与其他复杂任务的手动交替变得困难。

嵌入式实时操作系统(RTOS)是一个轻量级的系统,它通过各种服务为应用提供支持,并为应用中的任务分配计算资源。RTOS可以帮助用户在许多独立但相互协作的任务中构建应用。 然后,在要用到这些任务时,RTOS会根据任务的优先级并发执行这些任务。我们甚至可以将一项作业分割成一个高优先级任务和一个低优先级任务。

TouchGFX可以在没有操作系统的情况下运行,也可以在RTOS中运行。不使用RTOS并不会降低TouchGFX的性能。可能会增加MCU负载,并增加与TouchGFX一起运行其他任务的难度。

1.1.7内存使用

在本节中,我们将讨论TouchGFX应用的存储空间使用量。典型的TouchGFX应用使用4类存储器,但这取决于使用的硬件

图 2-17 存储器类型与作用

静态存储分配

TouchGFX只使用静态存储分配。这意味着所有存储空间都是预先分配的。TouchGFX在运行时不从存储空间中获取分配。如果应用可以一开始就分配好存储空间,则可确保永远不会使用内存时产生越界。

资源

诸如图像、文本和字体之类的资源产会被转换为C++文件并链接到应用中。 资源的数据通常存储在外部闪存中,但也可存储在内部闪存中。 这是通过链接器脚本来控制的。

在添加图像时,应用大小的增量与图像大小成正比。

在添加文本时,文本中的每个字符会导致应用大小增加两个字节。 如果同一个字符串使用了两次,应用大小只增加一次。

只有应用中使用的字符,才会从字符文件中获取。 这意味着如果应用中只使用大写字母A-Z,则应用中不包含字体中的小写字母a-z。 如果后续添加使用这些字母的文本,则应用中字体数据的量会增加。

闪存中字符的大小取决于选择的字体大小。 如果字体增大,应用大小也会增加。

Demo 1

下面是另一个示例:TouchGFX Designer中可以找到的TouchGFX Demo1的数据量。它包含5个界面和100多张图像:

图 2-18 STM32F746 Demo 1

图 2-19 STM32F746 Demo 1存储器使用情况

1.1.8 硬件选择

本部分的目的是针对硬件决策前应考虑的事项提供一些指导。每个产品都是不同的,因此有不同的标准和要求。下面的内容将针对在决策前应该考虑些什么为用户提供灵感来源。

图 2-20 硬件选择的因素

以下主题涵盖显示屏外观、系统内存需求、所需的UI性能和产品物理设计。

显示分辨率

显示屏有多种不同的分辨率和长宽比。通常,TouchGFX不依赖于这些参数中的任何一个。显示分辨率是选择合适硬件的主要考虑因素之一,一般来讲,分辨率越高,像素越多,因此要渲染和传输的数据就越多。

STM32微控制器通常支持高达16/24 bpp的XGA分辨率(1024*768),也支持非标准分辨率,如宽显示屏或圆形显示屏。对于高于XGA的分辨率,通常需要在色深、每秒帧数等方面做折衷。

以下是3个标准分辨率的示例:

图 2-21 显示分辨率示例

还应考虑像素密度,虽然显示屏尺寸越大,分辨率越高,显示越清晰,但像素密度越高,成本也越高。因此,在为应用选择分辨率时,应该确认以下这些问题:

最终目标用户群体是什么? 作为消费者自然期望更高的像素密度,而实际工业应用往往会综合考虑产品成本和集成度复杂性来最终选择合适的像素密度参数。

在应用中会使用到大量的文本显示吗?

常常会在屏幕上一次性显示大量不同元素吗?因为更大的显示空间可以显示更多元素,或使部分元素显示更为清晰。

色深

第二个主要考虑因素是色深(每个像素所对应的存储位数),它决定了图像中每个像素可以存储的信息量,也意味着您可以为单个像素分配的颜色数量。

图 2-22 1位像素和24位像素的应用

显示屏可以支持不同的色深,16bpp GUI应用可以在24bpp显示屏上运行,但无法在只能显示16位色深的显示屏上运行24bpp应用。

显示带有很多细微颜色差别的复杂图像往往需要更高的色深,以尽可能接近源图像。 色深的选择与显示所需内存量往往存在冲突。

不要低估在较低色深上可以实现的效果,因为许多现代UI设计理念都围绕扁平化和颜色密集程度较低的应用(例如Google的质感设计)。 通过应用某种抖动算法,TouchGFX可以有效地在较低色深条件下实现复杂图像。 下面的示例展示了可在较低色深基础上实现的效果:

图 2-23 低色深应用示例

在为应用选择色深时,应该确认以下这些问题:

应用需要显示真实生活图像吗?如果要使用真实生活图像或多层合成图像,建议在应用和显示屏中都使用24 bpp像素,因为在某些情况下,16bpp不足以显示所有需要的颜色。 16bpp在很多情况下是足够的,并且仍然是行业标准之一。

选用灰度颜色还是简单的6/8 bpp?真正需要实现的应用需求是什么?也许有些应用不需要大量颜色来正确传达其功能,因此可以选择较低色深。 这也减少了帧缓冲区大小,从而减少RAM需求。

对RAM和/或闪存容量有限制吗?限制色深将同时减少位图和帧缓冲区(RAM) 的需求。

帧缓冲区大小的计算

帧缓冲区是用来存储像素数据的地方,像素数据经过渲染后传输到显示屏。帧缓冲区大小很重要,因为更高的像素数量和更高的色深需要更高的RAM和显示接口的数据吞吐率。帧缓冲区大小以字节为单位通过以下方式计算:

显示宽度*显示高度*(每像素位数/8)

例如,一个分辨率为800x480具有16bpp色深的单帧显示帧缓冲区大小为:

800 * 480 * (16 / 8) = 768.000 b (768.000/1024 = 750 Kb)

因此,当决定分辨率和色深时,请确保有足够的RAM提供支持。某些应用需要2个帧缓冲区,因此在上面的示例中,所需的RAM为750 KB * 2 = 1500 KB。

图 2-24 缓冲区计算

显示

接口

可以选择具有不同显示接口(例如SPI、LTDC、MIPI-DSI)的显示屏,这些接口对所需的针数、带宽、支持的分辨率以及可能需要的外部RAM容量都有不同的影响。

尺寸

显示屏的物理尺寸也是重要的考虑因素之一。更大的显示屏通常更容易操作,更容易给出精确的触摸命令,但也需要更大的分辨率才能让眼睛更舒适,从而影响对更多内存和吞吐率的需求。如果显示屏上的信息在1-2米外显示,则文本、图标等需要足够大。

触控

触控显示屏主要有两种类型:

电容式:电容式触控显示屏具有更高的触控灵敏度,如果应用需要更高级的触控操作(如拖动、滑动等),这一点很重要,这种类型也是现代设备中使用最多的。然而,它们也更贵,而且通常不能戴手套操作,如果这很重要,也许电阻式是解决方案。

电阻式:这种更便宜的替代品灵敏度要低得多,在阳光下的可见性也很差,但可以戴手套操作,因为它对意外交互的敏感性较低,而且通常抗性更好。因此,如果您所有的触控操作都由简单的按按钮组成,那么也许电阻式显示屏就足够了。

动画

如果硬件的吞吐率和计算能力不足,运行复杂的动画(如全屏转换、旋转和缩放)会对性能产生重大影响。在决定应用中的动画级别时,应该确认以下这些问题:

需要高速全屏转换吗?全屏转换需要渲染完整的帧缓冲区,因此依赖于足够的MCU周期,以及足够快的像素数据访问和传输。 所需的系统性能还取决于分辨率和色深。 高分辨率全屏转换通常推荐用于STM32高性能产品。 某些转换需要额外的存储空间,因此可能需要更大内存量。

是否需要复杂的纹理映射器动画,如旋转和缩放?当涉及到计算和传输位图时,动画纹理映射器在系统上可能非常密集,因此通常需要更高的MHz和高内存吞吐率。

机械设计要求

产品的物理外壳要求会有很大差异,并且会对所选硬件产生影响。家用电器对危险工业用途有其他要求,因此,在揭示物理限制时,应该确认以下这些问题:

设计的产品需要非常小吗?例如,智能手表,它的外壳大小有限,这限制了PCB的大小,因此选择正确的组件很重要。 STM32提供多种MCU封装,例如WLCSP封装。

设计的产品会暴露于极端温度吗?电容式显示屏在极热或极冷时性能不佳。因此,如果将产品安装在如冷库等位置,则电阻式显示屏可能会提供更好的用户体验。STM32产品组合提供环境温度范围高达85、105和125度的微控制器。

设计的产品是否需要对室外环境因素(例如,水或灰尘)具有很强抗性?不同的技术提供不同的质量和功能,添加保护盖板可能是一种选择。

设计的产品在强光下可见性重要吗?显示屏的发光强度和光通量各不相同,显示屏的光通量和发光强度越高,显示屏的可读性就越高。 添加一个特殊盖板也可以改善这一点。 或者使用另一种也可以提供反射功能的显示技术。

每秒帧数

更高且稳定的每秒帧数(FPS)计数通常更好,因为这会使应用看起来更流畅。有时FPS不那么重要。 例如,在显示动画更新最少的静态GUI中。 在这种情况下,低成本硬件可能更合适。但是,根据目标用户群,拥有漂亮流畅的应用和大量华丽的动画也可以成为一个巨大的卖点,因此与硬件选择相关的任何方面都是一样,都是为了满足最终用户期望,并提供良好的用户体验。

图形用户界面的整体性能归结为系统级性能,包括如MCU、RAM、闪存、显示屏、接口吞吐率等组件,以及如STM32 Chrom-ART等硬件功能。下图描绘了一些不同参数影响的概括图。 要选择正确的硬件,需要考虑这些参数。 还考虑到STM32 Chrom-ART可降低MCU负荷,因此在某些情况下降低了高MCU频率的重要性。

图 2-25 色深、动画、频率以及吞吐量等参数对FPS对的影响

硬件组件

微控制器单元(MCU)是所有嵌入式解决方案的核心所在,在成本和特性方面有许多不同的选择。在选择图形用MCU时,应考虑支持的显示屏接口、MCU封装、尺寸和可获得的图形性能,最后一点取决于两个主要因素:

图像合成

MCU中集成的图形加速器的可用性。

系统中缓存存储器的可用性。

存储器存取和带宽

时钟频率和子系统总线频率。

对内部Flash和RAM存储器的存取。

除了图形,还必须考虑应用运行的其他方面(电机控制和无线技术等)。这些因素都可能影响MCU的选择。本页将逐一介绍不同MCU选项,以及在决定应为GUI驱动的应用选择哪种STM32 MCU时应考虑的参数。

图 2-26 STM32系列MCU应用于图形显示

频率

内核频率会极大地影响图形应用在屏幕刷新以及屏幕和动画的流畅性方面的性能。它会影响可从内部或外部存储器传输到显示屏帧缓冲的大量数据,还可能影响计算和动画。频率越高,在给定时间范围内能够传输的数据就越多,就能实现更复杂的动画。STM32产品的内核频率最高为480MHz。需要注意的是频率越高,功耗越大。

图形子系统频率

必须将内核CPU频率与图形子系统频率区别开来。图形子系统频率包括内部总线频率和图形计数器频率,以及内部和外部存储器的存取速度。图形子系统频率还会极大地影响整体图形性能。

示例

下面是从STM32H7上的内部RAM运行时,从理论上评估内核和子系统性能的示例:

CPU内核的运行频率为480MHz。

64位AXI总线频率为240MHz。

LCD-TFT显示屏控制器(LTDC)使用64位AXI总线,在10个周期内执行8次传输。

内部RAM不会导致明显延迟,即0等待状态。

因此,LTDC外设访问时内部RAM的带宽为:

带宽 = 240 MHz x 8/10 x 8 字节 = 1,536 MB/s。

有了这样的带宽,当分辨率为800x480且色深为32bpp时,内部RAM可确保1000帧/秒(fps)的刷新率。通常会将对显示屏的传输限制在每秒60帧(通过调整像素时钟、边沿等),以免LTDC和内部RAM的带宽成为瓶颈。

嵌入式硬件加速功能

不同的STM32 MCU具有不同的内置硬件加速功能,有助于获得高性能的图形应用。

Chrom-ART

Chrom-ART是一种先进的DMA,可以为执行图形操作提供辅助。 它也被称为DMA2D。许多STM32平台中集成了Chrom-ART加速器,它能够控制和传输图像,而不会增加CPU负载。 它能够加快大多数图形操作的速度,如颜色填充、图像复制、混合和像素格式转换。

Chrom-ART加速器能够在一项操作中执行两个图层的混合,将初始像素格式转换为需要的输出像素格式,并将结果传输到存储器目标位置。Chrom-ART加速器还支持有颜色查找表(CLUT)的颜色模式。 这有助于节省存储空间。

以在STM32F496-EVAL板上运行的应用为例,当启用Chrom-ART时,CPU负载从82%降至4%。此外,STM32H7产品为Chrom-ART外设增加了从YCbCr模式转换至RGB模式的能力。此特性结合JPEG硬件编解码器,可减轻JPEG图像编码和解码时的CPU负载。

图 2-27 YCbCr转RGB硬件性能

具有上述特性的Chrom-ART加速器为图形应用提供了巨大优势。 TouchGFX(若选择的MCU中有提供)处理所有Chrom-ART特性,并将所有可能的绘图操作重定向至Chrom-ART外设而非CPU。

JPEG硬件编解码器

STM32H7和STM32F7系列提供硬件JPEG编解码器,用于图像和视频的编码和解码。如果UI应用需要播放视频文件或显示JPEG图像,则此特性十分重要。JPEG图像占用的存储空间通常较小。 JPEG硬件编解码器确保在运行时间解码图像,而不会发生CPU超负载。一些TouchGFX演示利用JPEG硬件编解码器,减轻播放MJPEG视频时的CPU负载。

图 2-28 硬件JPEG编解码器性能

Chrom-GRC

在一些STM32微控制器中,外设STM32 Chrom-GRC™(GFXMMU)旨在为向非矩形显示屏发展的新趋势提供高效支持。在寻址非矩形显示屏时,Chrom-GRC™外设可帮助应用减少存储帧缓冲所需的RAM空间。

对于圆形显示屏,外设可将存储空间要求降低20%。在控制非方形屏幕时,建议但不强制使用Chrom-GRC™外设。

图 2-29 通过Chrom-GRC外设优化存储器

内部Flash

使用位图资源的图形用户界面应用需要使用非易失性存储器来存储数据。 在某些情况下,从内部闪存执行和访问内部Flash会比外部Flash快最多两倍。

由于内部Flash的大小有限,很多时候会用内部Flash来存储TouchGFX框架、屏幕定义和UI逻辑,而位图数据则存储在外部Flash中。

对图形应用使用的STM32产品组合的内部Flash大小介于几KB和几MB之间。当位图数据量与内部Flash不匹配时,可能需要用到外部存储器。

TouchGFX闪存要求:

框架:60 KB至100 KB。

屏幕定义和GUI逻辑:1至100 KB。

这些数字取决于使用的框架特性,以及应用的大小和复杂度。

内部RAM

内部RAM可用于存储帧缓冲的前提是帧缓冲的大小使之能够放入可用存储器。 或者,也可以为设置增加外部存储器。根据宽度、高度和色深计算帧缓冲的大小。 例如,对于具有HVGA分辨率(480x320)和16位色的显示屏,一个帧缓冲所需的存储空间为:

1个帧缓冲的大小 = 480 x 320 x 2 = 307.200字节

对图形应用使用的STM32产品的内部RAM大小介于几KB和几MB之间。TouchGFX RAM要求:

框架:10 KB至30 KB

控件:1 KB至15 KB

不同应用的存储空间要求可能不同。

u LCD控制器

MCU的选择还取决于要使用的显示屏接口和分辨率。以800x480的分辨率为例,只能通过数据传输足够高效的接口来实现。 RGB-TFT和MPI-DSI接口通常用于更高分辨率,原因是在许多情况下,带宽高于SPI或并行8080/6800。低分辨率显示屏通常内置控制器和GRAM,可通过简单的SPI或8080/6800接口进行连接。

高分辨率显示屏(WQVGA及以上)通常没有内置控制器和GRAM,因此控制器需位于微控制器侧。 STM32 MCU内置了RGB-TFT和MIPI DSI接口的控制器。

图 2-30 图中显示了有/没有GRAM和显示屏控制器的不同显示屏接口的4个示例。

封装& I/O

需要的I/O数量取决于选择的显示屏和外部存储器。 运行具有并行RAM/Flash的并行显示屏可能需要大量I/O,导致封装尺寸变大。

存储器接口

当微控制器中的内部闪存和RAM不够用时,选择具有最合适外部存储器接口的合适MCU就变得十分重要。 STM32产品提供了不同的存储器控制器外设,用于连接NOR、NAND、SRAM、SDRAM、LPSDR SDRAM和PSRAM存储器。

可变存储控制器& 可变静态存储控制器(FMC/FSMC)

除了支持静态RAM,FMC还为FSMC增加了动态RAM支持(SDRAM)。 可变存储控制器(FMC)具有很高的外部存取速率和8、16特别是32位数据总线,可实现与外部RAM之间的更高吞吐率,从而更好地支持更高分辨率。 FMC的每个存储区有独立的芯片选择。 FMC可以控制用于数据的外部Flash、用于帧缓冲的外部RAM存储器和用于图形栈的堆扩展。

串行存储器接口

根据选择的STM32产品,可能有内置串行存储器接口,除了QSPI、PSRAM、OPI PSRAM和Hyper RAM存储器,还可以连接单线、双线、四线、八线和hyperBus闪存。 当处于存储器映射模式时,串行高速存储器接口可控制最大256 MB的存储器;当处于间接模式时,为4 GB。相比于并行接口,串行存储器接口可将成本较低的外部闪存连接到小型封装,同时减少使用的引脚数。

STM32超值系列产品

为了优化价格,STM32H7和STM32F7平台提供了具有有限内部Flash的超值系列产品。 使用这些产品时,图形资源将保存在外部Flash中。

Cortex®-M Core

STM32 MCU采用不同的ARC Cortex®-M架构。 下面是STM32上运行图形时最常用的内核。

Cortex®-M0+

Cortex®-M0+的特点在于它架构简单且价格低廉。 建议将其应用于以较低分辨率运行的较小的静态图形应用。

Cortex®-M4

与M0+相比,Cortex®-M4包含更多功能,并加快了计算速度。 它包含DSP指令集和单精度FPU单元。 这些指令可减轻CPU负载并提高计算速度。

图 2-31 不同核心的特性概述

Cortex®-M7

Cortex®-M7包含更复杂的架构,也包含DSP指令集,并具有更高效的双精度FPU单元,以及可容纳最多16KB的数据和指令的一级缓冲存储器。 缓冲存储器提供了使数据和指令紧邻计算单元以便优化提取时间的可能性。

STM32H7和STM32F7系列包含最大16 KB的一级缓存,用于指令和数据缓存。 一级缓存在CPU附近保存了数据或指令集,因此CPU无需不断地提取重复使用的同一数据。

双核

STM32H7系列包含双核系列:Arm® Cortex®-M7和Cortex®-M4内核的运行频率分别可达到480 MHz和240 MHz,可以支持更多的处理和应用程序分区。 双核STM32H7产品系列可与嵌入式SMPS一起使用,以提高动态电源效率。第二个Cortex®-M4可以减轻计算量,以便开放M7内核用于绘图/图形操作。

总线架构

大多数STM32微控制器提供32位多AHB总线矩阵,用于互连所有主设备(CPU、DMA等)和从设备(Flash、RAM、FSMC、AHB和APB外设)。 这样一来,即使多个高速外设同时工作,也能确保无缝、高效的操作。除了多AHB互连,一些STM32(Cortex®-M7)产品还内置64位AXI,用于扩展带宽。 因此,在性能和功耗之间实现了最佳平衡。

价格

内部Flash和内部RAM的大小以及封装中的可用引脚数都会影响MCU的价格。 用户可以根据接口、分辨率和性能等方面的要求,最终找到合适的MCU和估价。

显示屏

目前的趋势是产品越来越丰富,用户体验增强,嵌入新的更大的显示屏,而老式的分段式显示屏正在被各种显示屏取代。本节将重点在介绍嵌入式GUI产品时选择合适的显示屏应考虑的一些注意事项。总体而言,TouchGFX可以在任何类型的显示屏上运行,不受显示技术、接口、视角、亮度等因素的影响。

图 2-32显示屏的不同类型

显示屏示例

由于每种显示屏的关键因素不同,选择合适的显示技术可能并不那么容易。每一种显示屏都包含像素行和像素列(它们的驱动方式可能不同),都具有内部和/或外部显示控制器和帧缓冲RAM。与其他技术相比,有些技术需要频繁地更新每个像素,而这种技术只在GUI中发生变化时才更新,因此并没有必要更新每个像素。目前有大量不同的显示技术,下面将介绍一些最常用的显示技术。

LCD-TFT

TFT是指薄膜晶体管,是LCD显示屏的一种变型,采用有源矩阵。 LCD-TFT有各种不同的分辨率、尺寸、接口和价格区间等,被广泛应用在嵌入式产品中。

TFT-LCD的一些变型包括TN和IPS面板。 IPS TFT-LCD的例子有STM32F769 DISCO板和STM32H747 DISCO板,二者都搭配800*480 MIPI-DSI TFT IPS LCD显示屏。 TFT-LCD TN显示屏的例子有STM32F746G DISCO板和STM32H7B3I-DK板。 两种技术带来不同画质,有些差异可能来源于颜色呈现和视角,IPS面板通常是最好的。

图 2-33 LCD-TFT图层示例

MIP

MIP表示像素存储,它使用的像素技术只在屏幕图像发生变化时才需要电源/数据。MIP显示屏是一种低功耗显示屏,功耗小于全彩GUI。

ePaper/eInk

eInk显示屏是低彩显示屏,它是低功耗、宽视角和易读型应用的理想选择。 TouchGFX Implementer SDATAWAY演示了在STM32F412上运行TouchGFX应用的eInk显示屏,详情见网址:https://www.touchgfx.com/cases/e-ink/

图 2-34 E-Ink

显示屏接口总览

显示屏通过不同类型的接口连接到MCU。 显示屏接口的参数各不相同,下一节将介绍图像相关参数,例如需要的引脚数和支持不同分辨率的最大带宽。

TouchGFX可使用任何显示接口,STM32微控制器提供可连接Motorola 6800、Intel 8080、SPI、RGB-TFT和MIPI-DSI的各种显示接口。

图 2-35 显示屏接口特性

亮度和背光

亮度单位通常使用堪德拉/每平米(cd/m²)。亮度是显示屏最耗电的部分。 在阳光下,显示屏需要约600 cd/m²的亮度。 更高的亮度通常会使温度上升,从而缩短LED的使用寿命。

观看位置和颜色反转

在将显示屏嵌入产品时,必须预见并了解用户可能处于的观看位置。一些显示屏在从特定位置观看时,可能发生颜色反转。 这意味着,想要将显示屏安装在合适位置,并使用户能够在操作和体验GUI的同时还能看到画面设计师设计的正确颜色,并没有那么容易。

TN面板可能发生颜色反转。 添加一层SWV膜有助于增大视角。

图 2-36 从不同观看位置看到的颜色

显示屏使用寿命

使用寿命的定义是显示屏在25℃条件下降至一半亮度所经历的时间。 如果产品的生命周期长,则必须考虑此参数。

像素密度

像素密度定义了每英寸或平方英寸显示的像素数。 可根据最终用户、环境和设计需求等因素选择合适的像素密度。 具体来说,一部高端手机的2340 x 1080像素6.1英寸屏幕的像素密度为每平方英寸178,500个像素,而常用的800 x 480像素5英寸TFT显示屏的像素密度为每平方英寸34,816个像素。

图 2-37 低、中、高像素密度

一些标准分辨率、显示屏尺寸和像素密度是用每平方英寸像素数(PPI2) 来衡量的:

图 2-38 不同显示屏的像素数

就某些应用而言,除非观看时与显示屏之间的距离非常近,否则,可能难以看出任何差异。 像素密度示例:STM32F476DISCO为16,462 PPI2,STM32F769DISCO为54,400 PPI2。

某些情况下,上述示例中的不同像素密度可能会影响动态色域和抗锯齿效果:

动态色域:动态色域是指两种对比色(如黑色和白色)之比。 在上面的示例中,蓝色和白色包含不同层次的白色和蓝色。 图像左侧的像素密度较低,而图像右侧为了显示所有颜色,包含的像素更多,因此不同颜色与边缘之间的过渡更平滑。

抗锯齿:当像素密度过低时,可能产生阶梯效应。 在应用中使用抗锯齿技术可使图像中的这些阶梯边缘变得平滑。 可以看到,前两个蓝色圆圈显示出阶梯效应,这是因为像素密度不允许显示屏显示足够多的像素,以致没有足够高的色域来实现足够高的反锯齿效果。

图 2-39 抗锯齿

在决定使用哪种显示屏时,必须考虑环境因素。 思考以下问题:

是否显示屏受到阳光直射?

是否用在需要抗冲击的恶劣环境下?

是否操作员会戴手套操作?

是否需要防止恶意破坏?

是否只通过物理按钮操作?

思考这些问题将有助于更好地理解要选择哪种触控技术,甚至是否需要触控。TouchGFX在触控和非触控显示屏上运行,TouchGFX GUI可通过按钮、手势和声音进行控制。

触控/非触控显示屏

目前市场上有不同的触控技术,例如:电阻式、电容式(表面、投影)、SAW(表面声波式)触控和红外触控。 本节将只介绍其中的某些技术:

电容式触控

这是最流行的触控技术之一。 它有两种感应技术:

自容式用于单指触控。

互电容式允许多指触控,但暴露在水/潮湿环境中时会面临困难(TouchGFX不支持多指触控)。

大多数STM32 探索板使用电容式触控,如STM32H7B3I 探索板、STM32H750 探索板和STM32F746G 探索板。

电阻式触控

电阻式触控是一种通过机械压力激活的简单技术,只需要ADC或简单的触摸控制器。 由于技术成熟,价格通常较低。 加强了表面的防刮擦和防撕裂保护,但防止恶意破坏的能力较差。 此外,在阳光下的可读性较低。 STM32F429 DISCO板使用电阻式触控,提供可用的TouchGFX应用示例。

非触控

一般情况下,如果通过按钮控制GUI,只需显示图像/视频,而如果通过另一个设备进行外部控制,是否为产品添加触控功能甚至都无关紧要。 不为显示屏增加触控层可以降低显示屏价格。

具有RAM的显示屏

采用Motorla 6800、Intel 8080、SPI或MIPI-DSI接口的显示屏通常内置RAM(GRAM),其大小为1个完整的帧缓冲。这些类型的显示屏可通过SPI、FMC或DSI主机(LTDC)连接到MCU。 显示屏RAM需要另一个外部RAM(帧缓冲),它可以位于MCU中或外部RAM中。

图 2-40 MIPI-DSI显示屏

在某些情况下,不需要外部RAM(MCU以外)来存储帧缓冲,因此使用MCU中可用的内部RAM。

如果MCU RAM小于1个完整的帧缓冲,则可以使用TouchGFX部分帧缓冲特性,这样可使帧缓冲的空间占用量维持在极低水平。

图 2-41 SPI显示屏

非正方形像素/像素宽高比

最常见的像素形状是正方形,但某些显示屏使用非正方形像素。 像素宽高比是像素宽度与像素高度之比。 因此,像素宽度和高度均为100的正方形像素的宽高比为1/1。 非正方形像素则有不同的像素宽高比。 如果画面设计师不考虑这一点,则显示的位图可能被拉伸,如下图所示。

图 2-42 被拉伸的位图

盖板玻璃

由于显示屏是嵌入式图形用户界面产品的表层,增加盖板玻璃可以改善外观和触感。盖板玻璃可以改善设计效果、抗刮擦性、抗冲击性和颜色等。

外部存储器

本节内容旨在帮助用户为嵌入式图形界面选择外部存储器。 在阅读本节内容之前,建议先阅读初步考虑 和MCU,以便了解在选择合适的外部存储器时要注意的一些重要依赖关系。

运行TouchGFX GUI应用时,有时需要使用外部存储器来存储帧缓冲、位图、字体和转换信息等。 TouchGFX GUI的运行不依赖外部存储器,但需要使用内部RAM(在MCU中)或外部RAM来存储帧缓冲,并用内部和/或外部Flash来存储数据。下面的存储器总览展示了一些可与STM32 MCU一起使用的外部存储器。 一些不同的存储器示例同时提供了串行和并行接口。

图 2-43 存储器总览

不同的STM32微控制器具有不同的外部存储器接口,可以连接不同的外部存储器。

非易失性存储器

在GUI应用中,非易失性存储(Flash)主要用于存储一些或全部图形数据资源,如位图、字体、转换信息和TouchGFX应用代码。 STM32产品支持非易失性存储器,可使用并行或串行存储器和不同配置,通过不同类型的MCU接口进行连接。

图 2-44 非易失性存储器

根据以下要素选择非易失性存储:

密度

性能

接口类型(并行/串行)

材料清单

NOR Flash

NOR Flash是一种非易失性存储器,允许对存储器中的任何区域进行随机存取。NOR Flash的大小通常介于128 Mbits和2 Gbits之间。

例如,当分辨率为480x320、色深为16位每像素时,用户界面需要的全屏背景图像约为300 kB。其中不包括使用的按钮、滑动条、图标和字体以及语言数量等所需的额外位图。256 Mbits (32 MB) NOR Flash可存储最多约100张全屏图像,如果加上需要的其他图形资源,将少于这个数量。

可在存储器映射模式下使用NOR Flash,在这种情况下,外部FLASH被视为读操作的内部存储器。 该模式允许系统主机(如DMA、LTDC、DMA2D、GFXMMU或SDMMC)自主访问存储器,即使在CPU停止时的低功耗模式下,是移动和可穿戴应用的理想选择。

NOR Flash存储器有不同的接口选项:

并行NOR Flash(具有x8或x16接口);

串行NOR Flash(串行存储器的单、双、四和八数据线,以及HyperBus闪存);

串行NOR Flash存储器

串行NOR Flash存储器被广泛用作图形应用中的存储器,这类存储器具有诸如以下优势:

高频率;

简化并缩小了印刷电路板(PCB)区;

存储器映射模式的可寻址区为最大256 MB;

需要的引脚数介于4和 <12个之间;

NOR Flash存储器有不同的数据线配置,接口可分为单线、双线、四线、八线。切换至配备更多数据线的串行NOR Flash存储器可以提高性能和存储器接口带宽,但也需要更多引脚来连接单片机。下面是根据数据线数量列出的不同SPI存储器总览:

图 2-45 串行接口总览

并行NOR Flash存储器

在性能和配置方面,并行NOR Flash存储器具有与串行闪存相同的优势。 并行NOR Flash可配置为存储器映射模式,并能像内部存储器一样进行存取。 并行和串行NOR Flash之间的差异在于引脚数和印刷电路板(PCB)的复杂度。NOR Flash存储器需要最多47个引脚,包括最多24个地址引脚和16个数据引脚。

NAND Flash存储器

NAND Flash存储器是需要大量图形资产和更快写入与擦除操作的图形应用的理想选择。 NAND Flash存储器不能配置为存储器映射模式,因此,不建议将其用于代码执行。NAND Flash的大小介于1 Gbit和512 Gbits之间。

在使用NAND Flash时,通常必须使用RAM中的缓存。 如此一来,可以将当前使用的图形资产移动到RAM,并从缓存中获取它们。

图 2-46 NAND Flash存储器

eMMC存储器

eMMC(嵌入式多媒体卡)由MMC协会订立,相当于一个NAND Flash加一个主集成控制器。 eMMC的一个明显优势是在封装中集成了控制器,从而提供了标准接口和闪存管理,使制造商能够将精力集中在产品开发的其他部份,进而缩短上市时间。eMMC Flash的大小介于2 Gbits和128 Gbits之间。

相比于NAND和NOR,eMMC的随机读取性能相对较低。 eMMC可能需要添加缓存来克服随机读取速度缓慢的问题。eMMC Flash存储器需要最多10个引脚,包括8个数据引脚和2个控制引脚。

图 2-47 eMMC存储器

易失性存储器

外部易失性存储器主要用于存储帧缓冲(若内部MCU RAM不够用),在某些情况下,用于缓存来自非存储器映射闪存的数据。 本节主要介绍SRAM、SDRAM和PSRAM,它们通常用在运行GUI的嵌入式系统中。 但还有其他可用的变型,存储器制造商对其存储器使用不同命名模式,如“hyper RAM”、“IoT RAM”和“octal RAM”。

图 2-48 易失性存储器

在选择合适的外部RAM时,建议注意以下要素:

密度

性能

功耗

接口/引脚尺寸

帧缓存策略

SRAM

SRAM是静态随机存取存储器,只要有供电,就能保存位数据。一般而言,SRAM的存取速度更快,但价格高于DRAM,并且密度更小。相比于DRAM,SRAM的存取时间通常更短,因此更适合需要更多动画、缩放和旋转等操作的GUI。SRAM具有同步和异步模式,同步模式提供更高的带宽能力,但接口更复杂。

SDRAM

SDRAM是一种动态随机存取存储器,它保存电容上的每一个数据位。相比于SRAM,SDRAM能用更小的物理空间存储相同数量的数据。 为了保存数据,SDRAM需要不断刷新,因此其能耗高于SRAM。SDRAM的密度通常为16 Mbits至512 Mbits,通过8、16和32位接口提供,运行频率为100-200 MHz。

双帧缓冲策略需要约18 Mbits的RAM,因此,适用于保存两个运行24bpp 800*480分辨率的帧缓冲的SDRAM是32 Mbits SDRAM。

PSRAM

PSRAM是伪静态随机存取存储器,具有DRAM(控制逻辑)的内部结构和SRAM接口。它的密度通常为8-256 Mbits。相比于传统的SDRAM和SRAM,PSRAM的优势在于速度更快且功耗更低。

其他存储器

新的octal RAM和Hyper RAM存储器在单和双数据率模式下使用串行8位接口,可实现高吞吐率和良好的集成度。

外部RAM密度的选择

如果设计的策略是将帧缓冲放在外部RAM中,下图是市面上提供的不同RAM密度的总览。它还提供了以1、2、4、8、16和24位每像素的密度(除以2可得出单个帧缓冲所需密度)运行双帧缓冲设置所需RAM的总览。在某些情况下,单帧缓冲设置已经足够,并且在某些STM32微控制器中,会有足够的内部RAM用于容纳帧缓冲。

图 2-49 SDRAM和OctoSPI密度

图 2-50 双帧缓冲设置所需RAM

1.1.9 软件架构

Model-View-Presenter设计模式

TouchGFX用户接口遵循Model-View-Presenter(MVP)架构模式,它是Model-View-Controller(MVC)模式的派生模式。 两者都广泛用于构建用户接口应用。MVP模式的主要优势是:

关注点分离:将代码分成不同的部分提供,每部分有自己的任务。 这使得代码更简单、可重复使用性更高且更易于维护。

单元测试:由于UI的逻辑(Presenter)独立于视图(View),因此,单独测试这些部分会容易很多。

MVP中定义了下列三个类:

Model是一种接口,用于定义要在用户界面上显示或有其他形式操作的数据。

View是一种被动接口,用于显示数据(来自Model),并将用户指令(事件)传给Presenter以便根据该数据进行操作。

Presenter的操作取决于Model和View。 它从存储库(Model)检索数据,并将其格式化以便在视图中显示。

图 2-51 Model-View-Presenter设计模式

在TouchGFX中,从Model类执行与应用非UI部分(这里称为后端系统)的通信。后端系统是从UI接收事件和将事件输入UI的软件组件,例如采集传感器的新测量值。后端系统可作为单独的任务在同一MCU、单独的处理器、云模块或其他硬件上运行。从TouchGFX的角度来看,这并不十分重要,只要它是能够与之通信的组件。

使用的特定通信协议不受TouchGFX管理。它只提供一个在每个TouchGFX嘀嗒时间调用一次的函数,可以在其中处理需要的通信。

图 2-52 Model-View-Presenter和外部通信

屏幕概念

在TouchGFX应用中,可以有任意数量的“屏幕”。 TouchGFX中的屏幕是UI元素(小工具)及其相关业务逻辑的逻辑分组。 屏幕包含两个类:包含该屏幕上显示的所有小工具的View类,以及包含该屏幕的业务逻辑的Presenter类。

可以选择在单个屏幕的背景下实现整个应用(意味着只有一个View和一个Presenter),建议将UI的不相关部分分割成不同屏幕,原因有两个:

1. TouchGFX包含存储器分配方案,可自动分配大多数RAM占用量大的屏幕所需的必要RAM。 只会分配必要的量,此RAM块将在应用中的所有屏幕之间重复使用。

2. 有多个屏幕会使UI代码的维护容易得多。

定义屏幕

关于应如何将应用划分成多个屏幕,并没有具体的规则,但有特定的指南,也许能帮助您决定应当用哪些屏幕构成您的特定应用。 在视觉和功能上无关的UI区域应保存在不同屏幕中。

如果是十分简单的有主温度读出显示屏和配置菜单的恒温器应用,建议创建“主屏幕”用于温度读出,并创建“设置屏幕”用于显示配置菜单。

主屏幕的视图将包含用于背景图像的小工具,几个显示温度的文本区和一个用于切换至配置菜单的按钮。 另一方面,用于配置的视图可能包含显示配置选项列表和不同背景图像的小工具。 如果配置菜单能够编辑许多不同类型的设置(日期、名称和键盘、温度、单位等),此屏幕的复杂性将大幅提升。

当前活动屏幕

由于 TouchGFX 为屏幕分配内存的方式(只为最大的 View 和最大的 Presenter 分配),一次只能有一个 View 和一个 Presenter 处于活动状态。 因此,如果您的恒温器应用程序正在显示温度读数,那么配置菜单屏幕不会在任何地方运行,实际上甚至没有分配。

如果从“后端”(所有执行恒温器实际工作的非UI代码)或硬件外设接收到事件,则可以将这些事件传递给当前活动屏幕。

由于一些事件将只与应用中的特定屏幕有关,因此这提供了有效的隔离方式。 例如,只有主屏幕才能处理通知当前温度变化的已接收事件(将更新显示当前温度的文本区),而由于当前温度未显示在配置屏幕上,配置屏幕可以直接丢弃此无关事件

由于一些事件将只与应用中的特定屏幕有关,因此这提供了有效的隔离方式。 例如,只有主屏幕才能处理通知当前温度变化的已接收事件(将更新显示当前温度的文本区),而由于当前温度未显示在配置屏幕上,配置屏幕可以直接丢弃此无关事件。

TouchGFX中的Model-View-Presenter

TouchGFX 遵循 Model-View-Presenter Design Pattern描述的Model-View-Presenter 设计模式。 TouchGFX 屏幕概念通过继承自 TouchGFX 中的 View 和 Presenter 类的类与整个 Model-View-Presenter 架构联系在一起。 因此,在TouchGFX Designer中将新屏幕添加到应用时,会创建新的特定View类和Presenter类以代表该特定屏幕。

TouchGFX应用中MVP类的内容和责任如下

Model

Model 类是一个永远存在的单类,它有两个用途:

1. 保存UI的状态信息。 在切换屏幕时,View和Presenter的分配会被清除,因此它们不能用于存储在屏幕转换时应当保留的信息。 为此,使用Model保存信息。

2. 作为面向后端系统的接口,向/从当前活动屏幕发送事件。

Model类是自动设置的,具有指向当前活动Presenter的指针。当Model中发生变化时,将变化通知当前活动Presenter。这是通过应用中ModelListener接口中的方法来完成的。

TouchGFX Designer生成的新应用将自动拥有可直接供UI使用的Model类。

View

View类(或者更具体地说,派生自TouchGFX View类的类)包含了该视图中显示的控件作为成员对象。 它还包含setupScreen和tearDownScreen函数,当进入/退出该屏幕时,会自动调用它们。 通常会在setupScreen函数中配置控件。

View还将包含指向相关Presenter的指针。 该指针通过框架自动设置。 使用此指针,您可以将 UI 事件(如按钮单击)传达给 Presenter。

Presenter

Presenter 类(同样,一个派生自 TouchGFX Presenter 类的类)负责当前活动屏幕的业务逻辑。 它将接收来自模型的“后端”事件,以及来自视图的 UI 事件,并决定采取何种行动。 例如,如果从 Model 接收到警报事件,Presenter 可能决定告诉 View 应该显示警报弹出对话框。

代码结构

本节介绍了TouchGFX项目的结构—从TouchGFX Designer生成的代码到用户编写的扩展代码。

生成的代码和用户代码

TouchGFX Designer生成的代码将与用户编写的代码完全分离。 事实上,生成的代码位于generated/gui_generated文件夹中,而手写代码位于gui文件夹中。

gui_generated代码充当用户代码类的基类。 基类包含在TouchGFX Designer中配置的所有设置代码。 下面的类示意图显示了类的关系:

图 2-53 引擎类、生成类和用户类的类层次结构

如上图所示,TouchGFX Designer应用包含3个不同代码层:

引擎:这些类是TouchGFX提供的标准类。 它们充当生成类的基类。

生成:当TouchGFX Designer生成代码时,将生成这些类和相应文件。 因此,不应手动编辑这些类和文件,因为任何手动修改都会在下一次运行代码生成器时被重写。 这些类是用户类的基类。

用户:这些类预定供手写代码使用。 用户可以自由地将任何代码放入该层。 如果没有用户类,将生成用户类,并且永远不会被TouchGFX Designer修改。 它们属于用户。

TouchGFX Designer生成的应用的架构是开放式的,在某种意义上,对创建内容应当没有任何限制。 如果TouchGFX Designer不支持某些对象(如小工具、动画或效果),可以将它们添加到用户类。 TouchGFX Designer生成的代码在设计上不会对制作TouchGFX应用的方式加以限制。

TouchGFX Designer生成的文件

根据规则,TouchGFX Designer将只在TouchGFX项目的generated文件夹中重新生成文件,因此不得在该文件进行手动编辑,因为会被覆盖。 然而,TouchGFX设计器也可以生成编译所需的缺失文件,例如application.config, simulator/main.cpp, 、皮肤图片(位于assets/images/__designer中)、以及示例视频(位于 assets/videos/__designer中)。 事实上,TouchGFX Designer只需要下列文件就能生成、编译和运行项目:

描述项目的.touchgfx文件。

位于gui文件夹的用户代码(如果有)。

位于assets/images文件夹的用户图像(如果有)。

assets/texts/texts.xml文件中的文本(如果有)。

位于assets/fonts文件夹的字体(如果有)。

assets/videos文件夹中的视频(如果有)。