STM32F7--->使用LTDC接口驱动RGBLCD,并使用DMA2D图形加速

文章目录

基础知识简介

RGBLCD

1.RGBLCD的信号

在这里插入图片描述
一般的 RGB 屏有 24 根颜色数据线(RGB 各站 8 根,即RGB888 格式),这样可以表示最多 1600W 色,DE、VS、HS 和 DCLK,用于控制数据传输。

2.RGBLCD驱动模式

其驱动模式主要分为两种

  • DE模式
    DE 模式使用 DE 信号来确定有效数据,DE 为高/低时,数据有效
  • HV模式
    HV模式需要行同步和列同步,来表示扫描的行和列

LTDC

STM32F767xx 系列芯片都带有 TFT LCD 控制器,即 LTDC,通过这个 LTDC,STM32F767可以直接外接 RGBLCD 屏,实现液晶驱动。

1.信号线

STM32F767 核心板板载的 LCD 接口引出为了,节省 IO,并提高图片显示速度,使用 RGB565 颜色格式,这样只需要 16 个 IO 口,当使用 RGB565 格式的时候,LCD 面板的数据线,必须连接到 LTDC 数据线的 MSB
在这里插入图片描述

2.图像处理单元

 先从 AHB 接口获取显存中的图像数据,然后经过层 FIFO(有 2 个,对应 2 个层)缓存,每个层 FIFO 具有 64*32 位存储深度,然后经过像素格式转换器(PFC),把从层的所选输入像素格式转换为 ARGB8888 格式,再通过混合单元,把两层数据合并,混合得到单层要显示的数据,最后经过抖动单元处理(可选)后,输出给 LCD 显示。
 混合单元首先将第一层与背景层进行混合,随后,第二层与第一层和第二层的混合颜色结果再次混合,完成混合后,送给 LCD显示。
在这里插入图片描述

3.AHB 接口

 由于 LTDC 驱动 RGBLCD 的时候,需要有很多内存来做显存,比如一个 800480 的屏幕,按一般的 16 位 RGB565 模式,一个像素需要 2 个字节的内存,总共需要:800480*2=768K 字节内存,STM32 内部是没有这么多内存的,所以必须借助外部 SDRAM,而 SDRAM 是挂在AHB 总线上的,LTDC 的 AHB 接口,就是用来将显存数据,从 SDRAM 存储器传输到 FIFO 里面。

4.LTDC相关寄存器及使用方法

LTDC 的各种配置寄存器以及状态寄存器,用于控制整个 LTDC 的工作参数,
主要有:各信号的有效电平、垂直/水平同步时间参数、像素格式、数据使能等等。
如果 RGBLCD 使用的是 DE 模式,需要设置如下参数,然后 LTDC会根据这些设置,自动控制 DE 信号。

LTCD全局控制寄存器 LTCD_GCR

在这里插入图片描述

名称功能详细解释DE下使用
LTDCENTFT LCD 控制器使能位LTDC 的开关置1
PCPOL像素时钟极性控制像素时钟的极性,根据 LCD 面板的特性来设置,我们所用的 LCD 一般设置为 0 即可,表示低电平有效。0
DEPOL数据使能极性控制 DE 信号的极性,根据 LCD 面板的特性来设置,我们所用的 LCD 一般设置为 0 即可,表示低电平有效0
VSPOL垂直同步极性控制 VSYNC 信号的极性,根据 LCD 面板的特性来设置,我们所用的 LCD 一般设置为 0 即可,表示低电平有效0
HSPOL水平同步极性控制 HSYNC 信号的极性,根据 LCD 面板的特性来设置,我们所用的 LCD 一般设置为 0 即可,表示低电平有效0
LTCD同步大小寄存器 LTDC_SSCR

该寄存器用于设置垂直同步高度(VSH)和水平同步宽度(HSW)
在这里插入图片描述

名称功能详细解释DE下使用
AVBP累加垂直后沿以水平扫描行为单位,表示:VSW+VBP-1
AHBP累加水平后沿以像素时钟为单位,表示 HSW+HBP-1
LTDC有效宽度配置寄存器 LTDC_AWCR

这里所说的有效高度和有效宽度,是指 LCD 面板的宽度和高度,构成分辨率
在这里插入图片描述

名称功能详细解释DE下使用
AAH累加有效高度以水平扫描行为单位,表示:VSW+VBP+有效高度-1
AAW累加有效高度以像素时钟为单位,表示:HSW+HBP+有效宽度-1
LTDC 总宽度配置寄存器 LTDC_TWCR

在这里插入图片描述

名称功能详细解释DE下使用
TOTALH总高度以水平扫描行为单位,表示:VSW+VBP+有效高度+VFP-1
TOTALW总宽度以像素时钟为单位,表示:HSW+HBP+有效宽度+HFP-1
LTDC 背景色配置寄存器 LTDC_BCCR

该寄存器定义背景层的颜色(RGB888),通过低 24 位配置,我们一般设置为全 0 即可。
在这里插入图片描述

LTDC当前位置状态寄存器 LTDC_CPSR

在这里插入图片描述
CXPOS[31~16]:返回当前X坐标位置
CYPOS[15~0]:返回当前Y坐标位置

LTDC当前显示状态寄存器 LTDC_CDSR

此寄存器返回由 HSYNC、VSYNC 和水平/垂直 DE 信号控制的当前显示阶段的状态
在这里插入图片描述

  • 位 31:24 保留,必须保持复位值
  • 位 3 HSYNCS:水平同步显示状态 (Horizontal Synchronization display Status)
    0:低电平有效
    1:高电平有效
  • 位 2 VSYNCS:垂直同步显示状态 (Vertical Synchronization display Status)
    0:低电平有效
    1:高电平有效
  • 位 1 HDES:水平数据使能显示状态 (Horizontal Data Enable display Status)
    0:低电平有效
    1:高电平有效
  • 位 0 VDES:垂直数据使能显示状态 (Vertical Data Enable display Status)
    0:低电平有效
    1:高电平有效
LTDC 的层颜色帧缓冲区地址寄存器 LTDC_LxCFBAR(x=1/2)

该寄存器用来定义一层显存的起始地址。STM32F767 的 LTDC 支持 2 个层,所以总共有两个寄存器,分别设置层 1 和层 2 的显存起始地址。
在这里插入图片描述

LTDC 的层像素格式配置寄存器 LTDC_LxPFCR(x=1/2)

该寄存器只有最低 3 位有效,用于设置层颜色的像素格式,一般使用 RGB565 格式,即该寄存器设置为:010 即可。

000:ARGB8888;001:RGB888;010:RGB565;
011:ARGB1555;100:ARGB4444;101:L8(8 位 Luminance);
110:AL44(4 位 Alpha,4 位 Luminance);111:AL88(8 位 Alpha,8 位 Luminance)
LTDC 的层恒定 Alpha 配置寄存器 LTDC_LxCACR(x=1/2)

该寄存器低 8 位(CONSTA)有效,这些位配置混合时使用的恒定 Alpha。恒定 Alpha 由硬件实现 255 分频。
在这里插入图片描述

LTDC 的层默认颜色配置寄存器 LTDC_LxDCCR(x=1/2)

该寄存器定义采用 ARGB8888 格式的层的默认颜色。默认颜色在定义的层窗口外使用或在层禁止时使用。一般情况下,用不到,所以该寄存器一般设置为 0 即可。
在这里插入图片描述

LTDC 层混合系数配置寄存器:LTDC_LxBFCR(x=1/2)

该寄存器用于定义混合系数:BF1 和 BF2。BF1=100 的时候,使用恒定的 Alpha 混合系数(由LTDC_LxCACR寄存器设置恒定Alpha值),BF1=110的时候,使用像素Alpha恒定Alpha。像素 Alpha 即 ARGB 格式像素的 A 值(Alpha 值),仅限 ARGB 颜色格式时使用。在 RGB565格式下,我们设置 BF1=100 即可。BF2 同 BF1 类似,BF2=101 的时候,使用恒定的 Alpha 混合系数,BF2=111 的时候,使用像素 Alpha恒定 Alpha。在 RGB565 格式下,我们设置 BF2=101即可。
通用的混合公式为:BC=BF1C+BF2Cs
其中:BC=混合后的颜色;BF1=混合系数 1;C=当前层颜色,即我们写入层显存的颜色值;BF2=混合系数 2;Cs=底层混合后的颜色,对于层 1 来说,Cs=背景层的颜色,对于层 2 来说,Cs=背景层和层 1 混合后的颜色。
在这里插入图片描述

LTDC 的层窗口水平位置配置寄存器 LTDC_LxWHPCR(x=1/2)

该寄存器定义第 1 层或第 2 层窗口的水平位置,第一个和最后一个像素
在这里插入图片描述WHSTPOS:窗口水平起始位置,定义层窗口的一行的第一个可见像素,
WHSPPOS:窗口水平停止位置,定义层窗口的一行的最后一个可见像素

LTDC 的层窗口垂直位置配置寄存器 LTDC_LxWVPCR(x=1/2)

该寄存器定义第 1 层或第 2 层窗口的垂直位置(第一行或最后一行)
在这里插入图片描述WVSTPOS:窗口垂直起始位置,定义层窗口的第一个可见行。
WVSPPOS:窗口垂直停止位置,定义层窗口的最后一个可见行。

LTDC 的层颜色帧缓冲区长度寄存器 LTDC_LxCFBLR(x=1/2)

该寄存器定义颜色帧缓冲区的行长和行间距。
在这里插入图片描述

  • CFBLL:这些位定义一行像素的长度(以字节为单位)+3。
    行长的计算方法为:有效宽度 * 每像素的字节数 + 3。
    比如,LCD 面板的分辨率为 800480,有效宽度为 800,采用 RGB565 格式,那么 CFBLL 需要设置为:8002+3=1603。
  • CFBP:这些位定义从像素某行的起始处到下一行的起始处的增量(以字节为单位)。
    这个设置,其实同样是一行像素的长度,对于 800480 的 LCD 面板,RGB565 格式,设置 CFBP 为:8002=1600 即可。
LTDC 的层颜色帧缓冲区行数寄存器 LTDC_LxCFBLNR(x=1/2)

该寄存器定义颜色帧缓冲区中的行数。
比如,LCD 面板的分辨率为 800*480,那么帧缓冲区的行数为 480 行,则设置 CFBLNBR=480 即可
在这里插入图片描述

5.时钟域

LTDC 有三个时钟域:AHB 时钟域(HCLK)、APB2 时钟域(PCLK2)和像素时钟域(LCD_CLK),
AHB 时钟域用于驱动 AHB 接口,读取存储器的数据到 FIFO 里面;
APB2 时钟域用于配置寄存器;
LCD_CLK像素时钟域则用于生成 LCD 接口信号,LCD_CLK 的输出应按照 LCD 面板要求进行配置。

DMA2D

  • 为了提高STM32F767的图像处理能力,ST公司设计了一个专用于图像处理的专业 DMA,通过 DMA2D 对图像进行填充和搬运,可以完全不用CPU 干预,从而提高效率,减轻 CPU 负担。

它可以执行下列操作:

  • 用特定颜色填充目标图像的一部分或全部(可用于快速单色填充)
  • 将源图像的一部分(或全部)复制到目标图像的一部分(或全部)中(可用于快速图
    像填充)
  • 通过像素格式转换将源图像的一部分(或全部)复制到目标图像的一部分(或全部)
  • 将像素格式不同的两个源图像部分和/ 或全部混合,再将结果复制到颜色格式不同的
    部分或整个目标图像中
  • DMA2D 有四种工作模式,通过 DMA2D_CR 寄存器的 MODE[1:0]位选择工作模式:
    1, 寄存器到存储器
    2, 存储器到存储器
    3, 存储器到存储器并执行 PFC
    4, 存储器到存储器并执行 PFC 和混合
  • 寄存器到储存器
    寄存器到存储器模式用于以预定义颜色填充用户自定义区域,也就是可以实现快速的单色
    填充显示,比如清屏操作。
    在该模式下:颜色格式在 DMA2D_OPFCCR 中设置,DMA2D 不从任何源获取数据,它只
    是将 DMA2D_OCOLR 寄存器中定义的颜色写入通过 DMA2D_OMA 寻址以及 DMA2D_NLR 和
    DMA2D_OOR 定义的区域
  • 储存器到储存器
    该模式下,DMA2D 不执行任何图形数据转换。前景层输入 FIFO 充当缓冲区,数据从
    DMA2D_FGMAR 中定义的源存储单元传输到 DMA2D_OMAR 寻址的目标存储单元,可用于快
    速图像填充。DMA2D_FGPFCCR 寄存器的 CM[3:0]位中编程的颜色模式决定输入和输出的每像
    素位数。对于要传输的区域大小,源区域大小由 DMA2D_NLR 和 DMA2D_FGOR 寄存器定义,
    目标区域大小则由 DMA2D_NLR 和 DMA2D_OOR 寄存器定义。
  • 以上两个工作模式,LTDC 在层帧缓存里面的开窗关系都一样的,经过如下三个寄存器的配置,就可以确定窗口的显示位置和大小。
    (1). 窗口显示区域的显存首地址由 DMA2D_OMAR 寄存器指定,
    (2).窗口宽度和高度由DMA2D_NRL 寄存器的 PL 和 NL 指定
    (3).行偏移(确定下一行的起始地址)由 DMA2D_OOR寄存器指定,
    在这里插入图片描述
    在寄存器到存储器模式下,在开窗完成后,DMA2D 可以将 DMA2D_OCOLR 指定的颜色,
    自动填充到开窗区域,完成单色填充。
    在存储器到存储器模式下,需要完成两个开窗:前景层和显示层,完成配置后,图像数据从前景层拷贝到显示层(仅限窗口范围内),从而显示到 LCD 上面。显示层的开窗如上图所示,前景层也和上图类似,只是 DMA2D_OMAR 寄存器变成了DMA2D_FGMAR,DMA2D_OOR寄存器变成了DMA2D_FGOR,DMA2D_NRL则两个层共用,然后就可以完成对前景层的开窗,确定好两个窗口后,DMA2D 就将前景层窗口内的数据,拷贝到显示层窗口,完成快速图像填充。

DMA2D相关寄存器

DMA2D控制寄存器 DMA2D_CR

该寄存器,主要是MODE 和 START 这两个设置
在这里插入图片描述
MODE:表示 DMA2D 的工作模式,
00:存储器到存储器模式;01:存储器到存储器模式并执行 PFC;
10:存储器到存储器并执行混合;11,寄存器到存储器模式;
START:该位控制 DMA2D 的启动,在配置完成后,设置该位为 1,启动 DMA2D 传输。

DMA2D输出 PFC 控制寄存器 DMA2D_OPFCCR

该寄存器用于设置寄存器到存储器模式下的颜色格式
在这里插入图片描述只有最低 3 位有效(CM[2:0]),表示的颜色格式有:
000,ARGB8888;001:RGB888;010:RGB565;
011:ARGB1555;100:ARGB1444。
我们一般使用的是 RGB565 格式,所以设置 CM[2:0]=010 即可。

DMA2D前景层 PFC 控制寄存器:DMA2D_FGPFCCR

在这里插入图片描述
该寄存器,低 4 位:CM[3:0],用于设置存储器到存储器模式下的颜色格式,这四个位表示的颜色格式为:
0000:ARGB8888;0001:RGB888;0010:RGB565;
0011:ARGB1555;0100:ARGB4444;0101:L8;
0110:AL44;0111:AL88;1000:L4;1001:A8;1010:A4;
我们一般使用 RGB565 格式,所以设置 CM[3:0]=0010 即可。

DMA2D输出偏移寄存器 DMA2D_OOR

在这里插入图片描述该寄存器仅最低 14 位有效(LO[13:0]),用于设置输出行偏移,作用于显示层,以像素为
单位表示。此值用于生成地址。行偏移将添加到各行末尾,用于确定下一行的起始地址。
同样的,还有前景层偏移寄存器:DMA2D_FGOR,该寄存器同 DMA2D_OOR 一样,也是
低 14 位有效,用于控制前景层的行偏移,也是用于生成地址,添加到各行末尾,从而确定下一
行的起始地址。

DMA2D输出存储器地址寄存器 DMA2D_OMAR

在这里插入图片描述
该寄存器设置由 MA[31:0]设置输出存储器地址,也就是输出 FIFO 所存储的数据地址,该地址需要根据开窗的起始坐标来进行设置。以 800480 的 LCD 屏为例,行长度为 800 像素,假定帧缓存数组为:ltdc_framebuf,我们设置窗口的起始地址为:sx(<800),sy(<480),颜色格式为 RGB565,每个像素 2 个字节,那么 MA 的设置值应该为:
*MA[31:0]= framebuf+2(800
sy+sx)**
同样的,还有前景层偏移寄存器:DMA2D_ FGMAR,该寄存器同 DMA2D_OMAR 一样,
不过是用于控制前景层的存储器地址,计算方法同 DMA2D_OMAR。

DMA2D行数寄存器 DMA2D_NLR

在这里插入图片描述该寄存器用于控制每行的像素和行数,该寄存器的设置对前景层和显示层均有效,通过该寄存器的配置,就可以设置开窗的大小。其中:
NL[15: 0]:设置待传输区域的行数,用于确定窗口的高度。
PL[13: 0]:设置待传输区域的每行像素数,用于确定窗口的宽度

DMA2D输出颜色寄存器 DMA2D_OCOLR

在这里插入图片描述该寄存器用于配置在寄存器到存储器模式下,填充时所用的颜色值,该寄存器是一个 32位寄存器,可以支持 ARGB8888 格式,也可以支持 RGB565 格式。我们一般使用 RGB565 格式,比如要填充红色,那么直接设置 DMA2D_OCOLR=0XF800 就可以了。

DMA2D中断状态寄存器 DMA2D_ISR

在这里插入图片描述

  • 该寄存器表示了 DMA2D 的各种状态标识
    TCIF 位,表示 DMA2D 的传输完成中断标志。当 DMA2D 传输操作完成(仅限数据传输)时此位置 1,表示可以开始下一次 DMA2D 传输了
  • DMA2D 中断标志清零寄存器:DMA2D_IFCR,用于清除 DMA2D_ISR 寄存器对应位的标志。通过向该寄存器的第 1 位(CTCIF)写 1,可以用于清除 DMA2D_ISR 寄存器的 TCIF 位标志。

LTDC具体使用步骤

1.使能 LTDC 时钟,并配置 LTDC 相关的 IO 及其时钟使能。

使用 LTDC,当然首先得开启其时钟。
然后需要把 LCD_R/G/B 数据线、LCD_HSYNC和 LCD_VSYNC 等相关 IO 口,全部配置为复用输出,并使能各 IO 组的时钟。

//LTDC底层IO初始化和时钟使能
//此函数会被HAL_LTDC_Init()调用
//hltdc:LTDC句柄
void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc)
{
    GPIO_InitTypeDef GPIO_Initure;
    
    __HAL_RCC_LTDC_CLK_ENABLE();                //使能LTDC时钟
    __HAL_RCC_DMA2D_CLK_ENABLE();               //使能DMA2D时钟
    __HAL_RCC_GPIOB_CLK_ENABLE();               //使能GPIOB时钟
    __HAL_RCC_GPIOF_CLK_ENABLE();               //使能GPIOF时钟
    __HAL_RCC_GPIOG_CLK_ENABLE();               //使能GPIOG时钟
    __HAL_RCC_GPIOH_CLK_ENABLE();               //使能GPIOH时钟
    __HAL_RCC_GPIOI_CLK_ENABLE();               //使能GPIOI时钟
    
    //初始化PB5,背光引脚
    GPIO_Initure.Pin=GPIO_PIN_5;                //PB5推挽输出,控制背光
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;      //推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;              //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;         //高速
    HAL_GPIO_Init(GPIOB,&GPIO_Initure);
    
    //初始化PF10
    GPIO_Initure.Pin=GPIO_PIN_10; 
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;          //复用
    GPIO_Initure.Pull=GPIO_NOPULL;
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;         //高速
    GPIO_Initure.Alternate=GPIO_AF14_LTDC;      //复用为LTDC
    HAL_GPIO_Init(GPIOF,&GPIO_Initure);
    
    //初始化PG6,7,11
    GPIO_Initure.Pin=GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_11;
    HAL_GPIO_Init(GPIOG,&GPIO_Initure);
    
    //初始化PH9,10,11,12,13,14,15
    GPIO_Initure.Pin=GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|\
                     GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
    HAL_GPIO_Init(GPIOH,&GPIO_Initure);
    
    //初始化PI0,1,2,4,5,6,7,9,10
    GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|\
                     GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_10;
    HAL_GPIO_Init(GPIOI,&GPIO_Initure); 
}

2.设置LCD_CLK时钟

配置 LCD 的像素时钟,根据 LCD 的面板参数进行设置,LCD_CLK 由 PLLSAI进行配置,配置使用到的 HAL 库函数为:

	//pllsain:SAI时钟倍频系数N,取值范围:50~432.  
	//pllsair:SAI时钟的分频系数R,取值范围:2~7
	//pllsaidivr:LCD时钟分频系数,取值范围:0~3,对应分频2~16 
	//假设:外部晶振为25M,pllm=25的时候,Fin=1Mhz.
	//例如:要得到20M的LTDC时钟,则可以设置:pllsain=400,pllsair=5,pllsaidivr=1
	//Fdclk=1*396/3/2*2^1=396/12=33Mhz
    RCC_PeriphCLKInitTypeDef PeriphClkIniture;
    
    //LTDC输出像素时钟,需要根据自己所使用的LCD数据手册来配置!
    PeriphClkIniture.PeriphClockSelection=RCC_PERIPHCLK_LTDC;       //LTDC时钟
    PeriphClkIniture.PLLSAI.PLLSAIN=pllsain;
    PeriphClkIniture.PLLSAI.PLLSAIR=pllsair;
    PeriphClkIniture.PLLSAIDivR=pllsaidivr;
	HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)

3.设置RGBLCD相关参数,并使能LTDC

typedef struct
{
 uint32_t HSPolarity; 			//水平同步极性
 uint32_t VSPolarity; 			//垂直同步极性 
 uint32_t DEPolarity; 			//数据使能极性
 uint32_t PCPolarity; 			//像素时钟极性
 uint32_t HorizontalSync; 		//水平同步宽度 
 uint32_t VerticalSync; 		//垂直同步高度
 uint32_t AccumulatedHBP; 		//水平同步后沿宽度
 uint32_t AccumulatedVBP; 		//垂直同步后沿高度 
 uint32_t AccumulatedActiveW; 	//累加有效宽度 
 uint32_t AccumulatedActiveH; 	//累加有效高度
 uint32_t TotalWidth; 			//总宽度
 uint32_t TotalHeigh; 			//总高度
 LTDC_ColorTypeDef Backcolor; 	//屏幕背景层颜色 
} LTDC_InitTypeDef;

typedef struct
{
  LTDC_TypeDef                *Instance;                /*Instance变量是LTDC_TypeDef结构体指针类型*/
  LTDC_InitTypeDef            Init;                     /*用来初始化LTDC的结构体变量*/
  LTDC_LayerCfgTypeDef        LayerCfg[MAX_LAYER];      /*保存LTDC层配置参数*/
  HAL_LockTypeDef             Lock;                     /*锁状态*/
  __IO HAL_LTDC_StateTypeDef  State;                    /*LTDC的状态*/
  __IO uint32_t               ErrorCode;                /*错误处理*/
} LTDC_HandleTypeDef;

LTDC_HandleTypeDef  LTDC_Handler;           			//LTDC句柄

LTDC_Handler.Instance=LTDC;
LTDC_Handler.Init.HSPolarity=LTDC_HSPOLARITY_AL; 		//水平同步极性
LTDC_Handler.Init.VSPolarity=LTDC_VSPOLARITY_AL; 		//垂直同步极性
LTDC_Handler.Init.DEPolarity=LTDC_DEPOLARITY_AL; 		//数据使能极性
LTDC_Handler.Init.PCPolarity=LTDC_PCPOLARITY_IPC; 		//像素时钟极性
LTDC_Handler.Init.HorizontalSync=10-1;		 			//水平同步宽度
LTDC_Handler.Init.VerticalSync=2-1; 					//垂直同步宽度
LTDC_Handler.Init.AccumulatedHBP=10+20-1; 				//水平同步后沿宽度
LTDC_Handler.Init.AccumulatedVBP=2+2-1; 				//垂直同步后沿高度
LTDC_Handler.Init.AccumulatedActiveW=10+20+480-1; 		//有效宽度
LTDC_Handler.Init.AccumulatedActiveH=2+2+272-1; 		//有效高度
LTDC_Handler.Init.TotalWidth=10+20+480+10-1; 			//总宽度
LTDC_Handler.Init.TotalHeigh=2+2+272+4-1; 				//总高度
LTDC_Handler.Init.Backcolor.Red=0; 						//屏幕背景层红色部分
LTDC_Handler.Init.Backcolor.Green=0; 					//屏幕背景层绿色部分
LTDC_Handler.Init.Backcolor.Blue=0; 					//屏幕背景色蓝色部分
HAL_LTDC_Init(&LTDC_Handler); 							//设置 RGBLCD 的相关参数,并使能 LTDC,会调用HAL_LTDC_MspInit

4.设置 LTDC层参数

//layerx:层值,0/1.
//bufaddr:层颜色帧缓存起始地址
//pixformat:颜色格式.0,ARGB8888;1,RGB888;2,RGB565;3,ARGB1555;4,ARGB4444;5,L8;6;AL44;7;AL88
//alpha:层颜色Alpha值,0,全透明;255,不透明
//alpha0:默认颜色Alpha值,0,全透明;255,不透明
//bfac1:混合系数1,4(100),恒定的Alpha;6(101),像素Alpha*恒定Alpha
//bfac2:混合系数2,5(101),恒定的Alpha;7(111),像素Alpha*恒定Alpha
//bkcolor:层默认颜色,32位,低24位有效,RGB888格式
void LTDC_Layer_Parameter_Config(u8 layerx,u32 bufaddr,u8 pixformat,u8 alpha,u8 alpha0,u8 bfac1,u8 bfac2,u32 bkcolor)
{
    LTDC_LayerCfgTypeDef pLayerCfg;
    
    pLayerCfg.WindowX0=0;                                   //窗口起始X坐标
    pLayerCfg.WindowY0=0;                                   //窗口起始Y坐标
    pLayerCfg.WindowX1=lcdltdc.pwidth;                      //窗口终止X坐标
    pLayerCfg.WindowY1=lcdltdc.pheight;                     //窗口终止Y坐标
    pLayerCfg.PixelFormat=pixformat;                        //像素格式
    pLayerCfg.Alpha=alpha;                                  //Alpha值设置,0~255,255为完全不透明
    pLayerCfg.Alpha0=alpha0;                                //默认Alpha值
    pLayerCfg.BlendingFactor1=(u32)bfac1<<8;                //设置层混合系数
    pLayerCfg.BlendingFactor2=(u32)bfac2<<8;                //设置层混合系数
    pLayerCfg.FBStartAdress=bufaddr;                        //设置层颜色帧缓存起始地址
    pLayerCfg.ImageWidth=lcdltdc.pwidth;                    //设置颜色帧缓冲区的宽度    
    pLayerCfg.ImageHeight=lcdltdc.pheight;                  //设置颜色帧缓冲区的高度
    pLayerCfg.Backcolor.Red=(u8)(bkcolor&0X00FF0000)>>16;   //背景颜色红色部分
    pLayerCfg.Backcolor.Green=(u8)(bkcolor&0X0000FF00)>>8;  //背景颜色绿色部分
    pLayerCfg.Backcolor.Blue=(u8)bkcolor&0X000000FF;        //背景颜色蓝色部分
    HAL_LTDC_ConfigLayer(&LTDC_Handler,&pLayerCfg,layerx);  //设置所选中的层
}

//在init时调用
LTDC_Layer_Parameter_Config(0(u32)ltdc_framebuf[0],LCD_PIXFORMAT,255,0,6,7,0X000000);  //层参数配置

5.设置LTDC层窗口

//layerx:层值,0/1.
//sx,sy:起始坐标
//width,height:宽度和高度
void LTDC_Layer_Window_Config(u8 layerx,u16 sx,u16 sy,u16 width,u16 height)
{
    HAL_LTDC_SetWindowPosition(&LTDC_Handler,sx,sy,layerx);  				//设置窗口的位置
    HAL_LTDC_SetWindowSize(&LTDC_Handler,width,height,layerx);				//设置窗口大小    
}

//在init时调用
LTDC_Layer_Window_Config(0,0,0,lcdltdc.pwidth,lcdltdc.pheight);             //层窗口配置,以LCD面板坐标系为基准

完成了 LTDC 的配置,可以控制 RGBLCD 显示了。

使用DMA2D完成颜色填充

使用官方提供的 HAL 库 DMA2D 相关库函数进行颜色填充效率极为低下,大量时间浪费在函数的入栈出栈以及过程处理,所以在项目开发中一般都不会使用 DMA2D 库函数进行颜色填充

1)使能 DMA2D 时钟,并先停止 DMA2D。

要使用 DMA2D,先得开启其时钟。然后 DMA2D 在配置其相关参数的时候,需要先停止DMA2D 传输。 使能 DMA2D 时钟和停止 DMA2D 方法为:

__HAL_RCC_DMA2D_CLK_ENABLE(); //使能 DM2D 时钟
DMA2D->CR&=~DMA2D_CR_START; //停止 DMA2D

2)设置 DMA2D 工作模式。

通过 DMA2D_CR 寄存器,配置 DMA2D 的工作模式。我们用了寄存器到存储器模式和存储器到存储器这两个模式。
寄存器到存储器模式设置:

DMA2D->CR=DMA2D_R2M; //寄存器到存储器模式

存储器到存储器模式设置:

DMA2D->CR= DMA2D_M2M; //存储器到存储器模式

3)设置 DMA2D 的相关参数。

这一步,我们需要设置:颜色格式、输出窗口、输出存储器地址、前景层地址(仅存储器到存储器模式需要设置)、颜色寄存器(仅寄存器到存储器模式需要设置)等,由:DMA2D_OPFCCR、DMA2D_FGPFCCR、DMA2D_OOR、DMA2D_FGOR 、DMA2D_OMAR、DMA2D_FGMAR 和 DMA2D_NLR 等寄存器进行配置。具体配置过程请参考实验源码。

4)启动 DMA2D 传输。

通过 DMA2D_CR 寄存器配置开启 DMA2D 传输,实现图像数据的拷贝填充,方法为:

DMA2D->CR|=DMA2D_CR_START; //启动 DMA2D

5)等待 DMA2D 传输完成,清除相关标识。

最后,在传输过程中,不要再次设置 DMA2D,否则会打乱显示,所以一般在启动 DMA2D后,需要等待 DMA2D 传输完成(判断 DMA2D_ISR),在传输完成后,清除传输完成标识(设置 DMA2D_IFCR),以便启动下一次 DMA2D 传输。

while((DMA2D->ISR&DMA2D_FLAG_TC)==0) ; //等待传输完成
DMA2D->IFCR|=DMA2D_FLAG_TC; //清除传输完成标志 

通过以上几个步骤,我们就完成了 DMA2D 填充

使用示例

//LCD LTDC重要参数集
typedef struct  
{
    u32 pwidth;         //LCD面板的宽度,固定参数,不随显示方向改变,如果为0,说明没有任何RGB屏接入
    u32 pheight;        //LCD面板的高度,固定参数,不随显示方向改变
    u16 hsw;            //水平同步宽度 Horizontal synchronization width
    u16 vsw;            //垂直同步宽度 Vertical synchronization width
    u16 hbp;            //水平后廊
    u16 vbp;            //垂直后廊
    u16 hfp;            //水平前廊
    u16 vfp;            //垂直前廊
    u8 activelayer;     //当前层编号:0/1
    u8 dir;             //0,竖屏;1,横屏;
    u16 width;          //LCD宽度
    u16 height;         //LCD高度
    u32 pixsize;        //每个像素所占字节数
}_ltdc_dev;

_ltdc_dev lcdltdc;		//管理LCD LTDC的重要参数

//LTDC填充矩形,DMA2D填充
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
//注意:sx,ex,不能大于lcddev.width-1;sy,ey,不能大于lcddev.height-1!!!
//color:要填充的颜色
void LTDC_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u32 color)
{ 
    u32 psx,psy,pex,pey;                        //以LCD面板为基准的坐标系,不随横竖屏变化而变化
    u32 timeout=0; 
    u16 offline;
    u32 addr; 
    //坐标系转换
    if(lcdltdc.dir)                             //横屏
    {
        psx=sx;psy=sy;
        pex=ex;pey=ey;
    }else                                       //竖屏
    {
        psx=sy;psy=lcdltdc.pheight-ex-1;
        pex=ey;pey=lcdltdc.pheight-sx-1;
    } 
    offline=lcdltdc.pwidth-(pex-psx+1);
    addr=((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*psy+psx));
    RCC->AHB1ENR|=1<<23;                        //使能DM2D时钟
    DMA2D->CR=3<<16;                            //寄存器到存储器模式
    DMA2D->OPFCCR=LCD_PIXFORMAT;                //设置颜色格式
    DMA2D->OOR=offline;                         //设置行偏移 
    DMA2D->CR&=~(1<<0);                         //先停止DMA2D
    DMA2D->OMAR=addr;                           //输出存储器地址
    DMA2D->NLR=(pey-psy+1)|((pex-psx+1)<<16);   //设定行数寄存器
    DMA2D->OCOLR=color;                         //设定输出颜色寄存器 
    DMA2D->CR|=1<<0;                            //启动DMA2D
    while((DMA2D->ISR&(1<<1))==0)               //等待传输完成
    {
        timeout++;
        if(timeout>0X1FFFFF)break;              //超时退出
    }  
    DMA2D->IFCR|=1<<1;                          //清除传输完成标志
}

//LCD清屏
//color:颜色值
void LTDC_Clear(u32 color)
{
    LTDC_Fill(0,0,lcdltdc.width-1,lcdltdc.height-1,color);
}
  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
使用STM32F103ZETB和STM32Cube配置TFT LCD显示屏,您可以按照以下步骤进行操作: 1. 配置引脚:使用STM32CubeMX工具,打开您的项目。在"Pinout & Configuration"选项卡中,选择合适的引脚用于连接TFT LCD显示屏的控制信号和数据线。根据您的具体显示屏规格,选择相应的引脚并进行配置。 2. 配置时钟:在"Configuration"选项卡中,选择合适的系统时钟源,并进行配置。确保时钟频率与TFT LCD显示屏的要求相匹配。 3. 配置LCD控制器:在"Configuration"选项卡中,选择"LCD-TFT Display Controller (LTDC)",并进行相应的配置。这将包括设置显示屏分辨率、像素格式、时序等参数。 4. 配置显示层:在"Configuration"选项卡中,选择"Layers",并进行图层配置。您可以设置背景图层和前景图层的属性,包括像素格式、颜色深度、帧缓冲区等。 5. 生成代码:点击"Project"菜单,选择"Generate Code",生成初始化代码。 6. 编写应用程序:在生成的初始化代码基础上,编写您的应用程序。这可能涉及到显示图像、文本、图形等操作。您可以使用STM32Cube提供的相关库函数和API来实现这些功能。 7. 编译和烧录:使用合适的开发环境(如Keil、IAR等)进行编译,并将生成的可执行文件烧录到STM32F103ZETB开发板上。 请注意,具体的配置和编程细节可能会因您使用的TFT LCD显示屏型号和供应商而有所不同。建议参考您的TFT LCD显示屏的数据手册和STM32Cube相关文档,以获得更具体的指导和支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值