像素是组成图像的最基本单元要素,显示器的像素指它成像最小的点,液晶原理中提到的一个显示单元。
一些嵌入式设备的显示器常常以“行像素值 x 列像素值”表示屏幕的分辨率。如分辨率800x480 表示该显示器的每一行有 800 个像素点,每一列有 480 个像素点,也可理解为有 800 列,480行。
色彩深度指显示器的每个像素点能表示多少种颜色,一般用“位”(bit)来表示。如单色屏的每个像素点能表示亮或灭两种状态(即实际上能显示 2 种颜色),用 1 个数据位就可以表示像素点的所有状态,所以它的色彩深度为 1bit,其它常见的显示屏色深为16bit、24bit。
显示器的大小一般以英寸表示,如 5 英寸、21 英寸、24 英寸等,这个长度是指屏幕对角线的长度, 通过显示器的对角线长度及长宽比可确定显示器的实际长宽尺寸。
点距指两个相邻像素点之间的距离,它会影响画质的细腻度及观看距离,相同尺寸的屏幕,若分辨率越高,则点距越小,画质越细腻。如现在有些手机的屏幕分辨率比电脑显示器的还大,这是手机屏幕点距小的原因;LED 点阵显示屏的点距一般都比较大,所以适合远距离观看。
完整的显示屏由液晶显示面板、电容触摸面板以及 PCB 底板构成。
触摸面板带有触摸控制芯片,该芯片处理触摸信号并通过引出的信号线与外部器件通讯。面板中间是透明的,它贴在液晶面板上面,一起构成屏幕的主体,触摸面板与液晶面板引出的排线连接到 PCB 底板上,根据实际需要,PCB 底板上可能会带有“液晶控制器芯片”。
因为控制液晶面板需要比较多的资源,所以大部分低级微控制器都不能直接控制液晶面板,需要额外配套一个专用液晶控制器来处理显示过程,外部微控制器只要把它希望显示的数据直接交给液晶控制器即可。而不带液晶控制器的 PCB 底板 ,只有小部分的电源管理电路,液晶面板的信号线与外部微控制器相连,直接控制。
STM32F429 系列的芯片不需要额外的液晶控制器,也就是说它把专用液晶控制器的功能集成到 STM32F429 芯片内部了,节约了额外的控制器成本。
RGB 信号线各有 8 根,分别用于表示液晶屏一个像素点的红、绿、蓝颜色分量。
所以它支持 RGB888 格式,一共 24 位数据线,可表示的颜色为 224种。
液晶屏与外部使用同步通讯方式,以 CLK 信号作为同步时钟,在同步时钟的驱动下,每个时钟传输一个像素点数据。
水平同步信号 HSYNC(Horizontal Sync)用于表示液晶屏一行像素数据的传输结束,每传输完成液晶屏的一行像素数据时,HSYNC 会发生电平跳变,如分辨率为 800x480 的显示屏(800 列,480 行),传输一帧的图像 HSYNC 的电平会跳变 480 次。
垂直同步信号 VSYNC(Vertical Sync)用于表示液晶屏一帧像素数据的传输结束,每传输完成一帧像素数据时,VSYNC 会发生电平跳变。其中“帧”是图像的单位,一幅图像称为一帧,在液晶屏中,一帧指一个完整屏液晶像素点。人们常常用“帧/秒”来表示液晶屏的刷新特性,即液晶屏每秒可以显示多少帧图像,如液晶屏以 60 帧/秒的速率运行时,VSYNC 每秒钟电平会跳变 60 次。
数据使能信号 DE(Data Enable)用于表示数据的有效性,当 DE 信号线为高电平时,RGB 信号线表示的数据有效。
通过上述信号线向液晶屏传输像素数据时,各信号线的时序见图。图中表示的是向液晶屏传输一帧图像数据的时序,中间省略了多行及多个像素点。
液晶屏显示的图像可看作一个矩形,结合下图来理解。液晶屏有一个显示指针,它指向将要显示的像素。显示指针的扫描方向方向从左到右、从上到下,一个像素点一个像素点地描绘图形。这些像素点的数据通过 RGB 数据线传输至液晶屏,它们在同步时钟CLK 的驱动下一个一个地传输到液晶屏中,交给显示指针,传输完成一行时,水平同步信号 HSYNC 电平跳变一次,而传输完一帧时 VSYNC 电平跳变一次。
但是,液晶显示指针在行与行之间,帧与帧之间切换时需要延时,而且 HSYNC 及VSYNC 信号本身也有宽度,这些时间参数说明见表:
在这些时间参数控制的区域,数据使能信号线“DE”都为低电平,RGB 数据线的信号无效,当“DE”为高电平时,表示的数据有效,传输的数据会直接影响液晶屏的显示区域。
液晶屏中的每个像素点都是数据,在实际应用中需要把每个像素点的数据缓存起来,再传输给液晶屏,这种存储显示数据的存储器被称为显存。
显存一般至少要能存储液晶屏的一帧显示数据,如分辨率为 800x480 的液晶屏,使用 RGB888 格式显示,它的一帧显示数据大小为:3x800x480=1152000 字节;若使用 RGB565 格式显示,一帧显示数据大小为:
2x800x480=768000 字节。
STM32F429 系列芯片内部自带一个 LTDC 液晶控制器,使用 SDRAM 的部分空间作为显存,可直接控制液晶面板,无需额外增加液晶控制器芯片。
LTDC 外设支持 2 层数据混合,混合前使用 2 层数据源,分别为前景层和背景层,见下图。
在输出时,实际上液晶屏只能显示一层图像,所以 LTDC 在输出数据到液晶屏前需要把 2 层图像混合成一层,跟 Photoshop 软件的分层合成图片过程类似。
混合时,直接用前景层中的不透明像素替换相同位置的背景像素;而前景层中透明像素的位置,则使用背景的像素数据,即显示背景层的像素。
如果想使用图像混合功能,前景层必须使用包含透明的像素格式,如 ARGB1555 或ARGB8888。其中 ARGB1555 使用 1 个数据位表示透明元素,它只能表示像素是透明或不透明,当最高位(即“A”位)为 1 时,表示这是一个不透明的像素,具体颜色值为 RGB 位表示的颜色,而当最高位为 0 时,表示这是一个完全透明的像素,RGB 位的数据无效;而ARGB8888 的像素格式使用 8 个数据位表示透明元素,它使用高 8 位表示“透明度”(即代表“A”的 8 个数据位),若 A 的值为“0xFF”,则表示这个像素完全不透明,若 A 的值为“0x00”则表示这个像素完全透明,介于它们之间的值表示其 RGB 颜色不同程度的透明度,即混合后背景像素根据这个值按比例来表示。
注意液晶屏本身是没有透明度概念的,如 24 位液晶屏的像素数据格式是 RGB888,RGB 颜色各有对应的 8 根数据线,不存在用于表示透明度的数据线,所以实际上 ARGB 只是针对内部分层数据处理的格式,最终经过混合运算得出直接颜色数据 RGB888 才能交给液晶屏显示。
下图是 LTDC 控制器的结构框图,它主要包含信号线、图像处理单元、寄存器及时钟信号。
LTDC 的控制信号线与液晶显示面板的数据线一一对应,包含有 HSYNC、VSYNC、DE、CLK 及 RGB 数据线各 8 根。
LTDC 框图标号②表示的是图像处理单元,它通过“AHB 接口”获取显存中的数据,然后按分层把数据分别发送到两个“层 FIFO”缓存,每个 FIFO 可缓存 64x32 位的数据,接着从缓存中获取数据交给“PFC”(像素格式转换器),它把数据从像素格式转换成字(ARGB8888)的格式,再经过“混合单元”把两层数据合并起来,最终混合得到的是单层要显示的数据,通过信号线输出到液晶面板。这部分结构与 DMA2D 的很类似,我们在下一小节详细讲解。
在输出前混合单元的数据还经过一个“抖动单元”,它的作用是当像素数据格式的色深大于液晶面板实际色深时,对像素数据颜色进行舍入操作,如向 18 位显示器上显示 24位数据时,抖动单元把像素数据的低 6 位与阈值比较,若大于阈值,则向数据的第 7 位进1,否则直接舍掉低 6 位。
框图中标号③表示的是 LTDC 的控制逻辑,它包含了 LTDC 的各种配置和状态寄存器。
如配置与液晶面板通讯时信号线的有效电平、各种时间参数、有效数据宽度、像素格式及显存址等等,LTDC 外设根据这些配置控制数据输出,使用 AHB 接口从显存地址中搬运数据到液晶面板。还有一系列用于指示当前显示状态和位置的状态寄存器,通过读取这些寄存器可以了解 LTDC 的工作状态。
LTDC 外设使用 3 种时钟信号,包括 AHB 时钟、APB2 时钟及像素时钟 LCD_CLK。
见图,LCD_CLK 的来源是 HSE(高速外部晶振),经过“/M”分频因子分频输出到“PLLSAI”分频器,信号由“PLLSAI”中的倍频因子 N 倍频得到“PLLSAIN”时钟、然后由“/R”因子分频得到“PLLCDCLK”时钟,再经过“DIV”因子得到“LCD-TFT clock”,“LCD-TFT clock”即通讯中的同步时钟LCD_CLK,它使用 LCD_CLK 引脚输出。
在实际使用 LTDC 控制器控制液晶屏时,使 LTDC 正常工作后,往配置好的显存地址写入要显示的像素数据,LTDC 就会把这些数据从显存搬运到液晶面板进行显示,而显示数据的容量非常大,所以我们希望能用 DMA 来操作,针对这个需求,STM32 专门定制了DMA2D 外设,它可用于快速绘制矩形、直线、分层数据混合、数据复制以及进行图像数据格式转换,可以把它理解为图形专用的 DMA。
下图是 DMA2D 的结构框图,它与前面 LTDC 结构里的图像处理单元很类似,主要为分层 FIFO、PFC 及彩色混合器。
FG FIFO(Foreground FIFO)与 BG FIFO(Backgroun FIFO)是两个 64x32 位大小的缓冲区,它们用于缓存从 AHB 总线获取的像素数据,分别专用于缓冲前景层和背景层的数据源。
FG PFC(FG Pixel Format Convertor)与 BG PFC(BG Pixel Format Convertor)是两个像素格式转换器,分别用于前景层和背景层的像素格式转换,不管从 FIFO 的数据源格式如何,都把它转化成字的格式(即 32 位),ARGB8888。
图中的“ɑ”表示 Alpha,即透明度,经过 PFC,透明度会被扩展成 8 位的格式。
图中的“CLUT”表示颜色查找表(Color Lookup Table),颜色查找表是一种间接的颜色表示方式,它使用一个 256x32 位的空间缓存 256 种颜色,颜色的格式是 ARGB8888 或RGB888。
见下图,利用颜色查找表,实际的图像只使用这 256 种颜色,而图像的每个像素使用 8 位的数据来表示,该数据并不是直接的 RGB 颜色数据,而是指向颜色查找表的地址偏移,即表示这个像素点应该显示颜色查找表中的哪一种颜色。在图像大小不变的情况下,利用颜色查找表可以扩展颜色显示的能力,其特点是用 8 位的数据表示了一个 24 或32 位的颜色,但整个图像颜色的种类局限于颜色表中的 256 种。DMA2D 的颜色查找表可以由 CPU 自动加载或编程手动加载。
FIFO 中的数据源经过 PFC 像素格式转换器后,前景层和背景层的图像都输入到混合器中运算,运算公式见图:
从公式可以了解到混合器的运算主要是使用前景和背景的透明度作为因子,对像素RGB 颜色值进行加权运算。经过混合器后,两层数据合成为一层 ARGB8888 格式的图像。
OUT PFC 是输出像素格式转换器,它把混合器转换得到的图像转换成目标格式,如ARGB8888、RGB888、RGB565、ARGB1555 或 ARGB4444,具体的格式可根据需要在输出 PFC 控制寄存器 DMA2D_OPFCCR 中选择。
STM32F429 芯片使用 LTDC、DMA2D 及 RAM 存储器,构成了一个完整的液晶控制器。LTDC 负责不断刷新液晶屏,DMA2D 用于图像数据搬运、混合及格式转换,RAM 存储器作为显存。其中显存可以使用 STM32 芯片内部的 SRAM 或外扩 SDRAM/SRAM,只要容量足够大即可(至少要能存储一帧图像数据)。
这个结构体大部分成员都是用于定义 LTDC 的时序参数的,包括信号有效电平及各种时间参数的宽度。
LTDC 初始化结构体只是配置好了与液晶屏通讯的基本时序,还有像素格式、显存地址等诸多参数需要使用 LTDC 层级初始化结构体完成。
公式中的参数见下表:
参数 | 说明 | CA | PAxCA |
---|---|---|---|
BC | 混合后的颜色(混合结果) | / | / |
C | 当前层颜色 | / | / |
Cs | 底层混合后的颜色 | / | / |
BF1 | 混合系数 1 | 等 于 ( 恒 定 Alpha 值) | 等于(恒定 Alpha x 像素 Alpha 值) |
BF2 | 混合系数 2 | 等于(1-恒定 Alpha) | 等于(1-恒定 Alpha x 像素 Alpha值) |
本结构体成员可以设置 BF1/BF2 参数使用 CA 配置(LTDC_BlendingFactor1/2_CA)还是PAxCA 配置(LTDC_BlendingFactor1/2_PAxCA)。配置成 CA 表示混合系数中只包含恒定的 Alpha 值,即像素本身的 Alpha 不会影响混合效果,若配置成 PAxCA,则混合系数中包含有像素本身的 Alpha 值,即把像素本身的 Alpha 加入到混合运算中。其中的恒定Alpha 值即前面“LTDC_ConstantAlpha”结构体配置参数的透明度百分比:(配置的Alpha 值/0xFF)。
见上图,数据源混合时,由下至上,如果使用了 2 层,则先将第 1 层与 LTDC 背景混合,随后再使用该混合颜色与第 2 层混合得到最终结果。例如,当只使用第 1 层数据源时,且 BF1 及 BF2 都配置为使用恒定 Alpha,该 Alpha 值在 LTDC_ConstantAlpha结构体成员值中被配置为 240(0xF0)。因此,恒定 Alpha 值为 240/255=0.94。若当前层颜色 C=128,背景色 Cs=48,那么第 1 层与背景色的混合结果为:
BC=恒定 Alpha x C + (1- 恒定 Alpha) x Cs=0.94 x Cs +(1-0.94)x 48=123
LTDC_CFBStartAdress
本成员用于设置该层的显存首地址,该层的像素数据保存在从这个地址开始的存储空间内。
LTDC_CFBLineLength
本成员用于设置当前层的行数据长度,即每行的有效像素点个数 x 每个像素的字节数,实际配置该参数时应写入值(行有效像素个数 x 每个像素的字节数+3),每个像素的字节数跟像素格式有关,如 RGB565 为 2 字节,RGB888 为 3 字节,ARGB8888 为 4 字节。
LTDC_CFBPitch
本成员用于设置从某行的有效像素起始位置到下一行起始位置处的数据增量,无特殊情况的话,它一般就直接等于行的有效像素个数 x 每个像素的字节数。
LTDC_CFBLineNumber
本成员用于设置当前层的显示行数。
配置完 LTDC_Layer_InitTypeDef 层级初始化结构体后,调用库函数 LTDC_LayerInit可把这些配置写入到 LTDC 的层级控制寄存器中,完成初始化。
初始化完成后 LTDC 会不断把显存空间的数据传输到液晶屏进行显示,我们可以直接修改或使用 DMA2D 修改显存中的数据,从而改变显示的内容。
在实际显示时,我们常常采用 DMA2D 描绘直线和矩形,这个时候会用到 DMA2D 结构体。
DMA2D_Mode
本成员用于配置 DMA2D 的工作模式:
这几种工作模式主要区分数据的来源、是否使能 PFC 以及是否使能混合器。使用DMA2D 时,可把数据从某个位置搬运到显存,该位置可以是 DMA2D 本身的寄存器,也可以是设置好的 DMA2D 前景地址、背景地址(即从存储器到存储器)。若使能了PFC,则存储器中的数据源会经过转换再传输到显存。若使能了混合器,DMA2D 会把两个数据源中的数据混合后再输出到显存。
若使用存储器到存储器模式,需要调用库函数 DMA2D_FGConfig,使用初始化结构体 DMA2D_FG_InitTypeDef 配置数据源的格式、地址等参数。(背景层使用函数DMA2D_BGConfig 和结构体 DMA2D_BG_InitTypeDef)
DMA2D_CMode
本成员用于配置 DMA2D 的输出 PFC 颜色格式,即它将要传输给显存的格式。
DMA2D_OutputBlue/ Green/ Red/ Alpha
这几个成员用于配置 DMA2D 的寄存器颜色值,若 DMA2D 工作在“寄存器到存储器”(DMA2D_R2M)模式时,这个颜色值作为数据源,被 DMA2D 复制到显存空间,即目标空间都会被填入这一种色彩。
DMA2D_OutputMemoryAdd
本成员用于配置 DMA2D 的输出 FIFO 的地址, DMA2D 的数据会被搬运到该空间,一般把它设置为本次传输显示位置的起始地址。
DMA2D_OutputOffset
本成员用于配置行偏移(以像素为单位),行偏移会被添加到各行的结尾,用于确定下一行的起始地址。如下表中的黄色格子表示行偏移,绿色格子表示要显示的数据。左表中显示的是一条垂直的线,且线的宽度为 1 像素,所以行偏移的值=7-1=6,即“行偏移的值=行宽度-线的宽度”,右表中的线宽度为 2 像素,行偏移的值=7-2=5。
DMA2D_NumberOfLine
本成员用于配置 DMA2D 一共要传输多少行数据,如上表中一共有 5 行数据。
DMA2D_PixelPerLine
本成员用于配置每行有多少个像素点,如表 27-7 左侧表示每行有 1 个像素点,右侧表示每行有 2 个像素点。
配置完这些结构体成员,调用库函数 DMA2D_Init 即可把这些参数写入到 DMA2D 的控制寄存器中,然后再调用 DMA2D_StartTransfer 函数开启数据传输及转换。