【LTDC】LTDC 相关寄存器
前言
此篇文章仅作笔记分享,内容来源为:
这篇文章就是为了了解 LTDC 其中的寄存器,以至于移植什么的更加清晰明了。
注意事项
- RGBLCD 其实也是 TFTLCD,只是接口不同。
- 控制 B7、G7、R7 引脚可以分辨 LCD 的模块 ID,例如:100 为 4.3 寸,800 * 480 分辨率 LCD。
- LTDC 是 STM32H7 的 TFTLCD 控制器。
- LTDC 控制器主要包含:信号线、图像处理单元、 AHB接口、配置和状态寄存器以及时钟部分,其框图如图。
- LTDC 有 24 位并行像素输出,每个像素8位数据(RGB888),但是为了节省 IO,提高速度,一般只用 RGB565,只需要16个 IO 口。
即:LCD_R[7:3]、LCD_G[7:2]、LCD_B[7:3]。 - 一个像素需要2个字节的内存,一般的 16 位 RGB565 模式,800 * 480 的屏幕,则需要 800 * 480 * 2 = 768 KB,故要使用到外部SDRAM,
而 SDRAM 是挂载在 AHB 总线上的,LTDC 的AHB 总线的功能就是将显存数据从 SDRAM 存储器传输到 FIFO 中。 - 对于 LTDC 控制器来说,屏幕的显示区域被称作为有效显示范围,即分辨率。其中一些无效显示范围包括以下部分:

寄存器
全局控制寄存器 LTDC_GCR (极性控制)

- LTDCEN TFT LCD: 控制器使能位,也就是 LTDC 的开关,该位需要设置为 1。
- PCPOL: 像素时钟极性。控制像素时钟的极性,根据 LCD 面板的特性来设置,我们所用的 LCD 一般设置为 0 即可,表示低电平有效。
- DEPOL: 数据使能极性。控制 DE 信号的极性,根据 LCD 面板的特性来设置,我们所用的 LCD 一般设置为 0 即可,表示低电平有效。
- VSPOL: 垂直同步极性。控制 VSYNC 信号的极性,根据 LCD 面板的特性来设置,我们所用的 LCD 一般设置为 0 即可,表示低电平有效。
- HSPOL: 水平同步极性。控制 HSYNC 信号的极性,根据 LCD 面板的特性来设置,我们所用的 LCD 一般设置为 0 即可,表示低电平有效。
同步大小配置寄存器 LTDC_SSCR

- VSH: 表示垂直同步高度(以水平扫描行为单位),表示垂直同步脉宽减 1 ,即 VSW-1。
- HSW: 表示水平同步宽度(以像素时钟为单位),表示 水平同步脉宽减 1,即 HSW-1。
后沿配置寄存器 LTDC_BPCR

- AVBP: 加垂直后沿(以水平扫描行为单位),表示: VSW+VBP-1。
- AHBP:累加水平后沿(以像素时钟为单位),表示 HSW+HBP-1,下同。
有效宽度配置寄存器 LTDC_AWCR

-
AAH: 累加有效高度(以水平扫描行为单位),表示: VSW+VBP+有效高度 -1。
-
AAW: 累加有效宽度(以像素时钟为单位),表示: HSW+HBP+有效宽度 -1。
这里所说的有效高度和有效宽度,是指LCD 面板的宽度和高度(构成分辨率,下同)
总宽度配置寄存器 LTDC_TWCR

- TOTALH: 总高度(以水平扫描行为单位),表示: VSW+VBP+有效高度 +VFP-1。
- TOTALW: 总宽度(以像素时钟为单位),表示: HSW+HBP+有效宽度 +HFP-1。
背景色配置寄存器 LTDC_BCC

该寄存器定义背景层的颜色(RGB888),通过低 24 位配置,我们一般设置为全 0 即可。
层颜色帧缓冲区地址寄存器 LTDC_LxCFBAR(x=1/2)

该寄存器用来定义一层显存的起始地址。STM32H743的 LTDC支持 2个层,所以总共两个寄存器,分别设置层 1和层 2的显存起始地址。
层像素格式配置寄存器 LTDC_LxPFCR(x=1/2)

该寄存器只有最低 3位有效,用于设置层颜色的像素格式:
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)
我们一般使用 RGB565 格式,即该寄存器设置为: 010 即可。
层恒定 Alpha配置寄存器 LTDC_LxCACR(x=1/2)

该寄存器低 8 位(CONSTA)有效,这些位配置混合时使用的恒定 Alpha。恒定 Alpha 由硬件实现 255分频。关于这个恒定 Alpha 的使用,我们将在介绍 LTDC_LxBFCR 寄存器的时候进行讲解。
层默认颜色配置寄存器 LTDC_LxDCCR(x=1/2)

该寄存器定义采用 ARGB8888 格式的层的默认颜色。默认颜色在定义的层窗口外使用或在层禁止时使用。一般情况下,用不到,所以该寄存器一般设置为 0即可。
层混合系数配置寄存器 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 = BF1 * C + BF2 * Cs
BC: 混合后的颜色
BF1: 混合系数 1
C: 当前层颜色,即我们写入层显存的颜色值
BF2: 混合系数 2
Cs: 底层混合后的颜色,对于层 1 来说, Cs=背景层的颜色,对于层 2 来说, Cs=背景层和层 1 混合后的颜色。
举例
假设 Alpha 的值由 LTDC_LxCACR 寄存器设置,恒定 ALpha = LTDC_LxCACR 设置值 / 255。假设 LTDC_LxCACR 设置值= 240;C = 128;Cs = 48;那么计算得 恒定 Alpha = LTDC_LxCACR 设置值 / 255 = 0.94。通过以上混合公式:BC = BF1 * C + BF2 * Cs 计算得,BC = 122。
注意
- BF1 和 BF2 的恒定 Alpha 值互补,他们之和为 1。
- 且 BF1 使用的是恒定 Alpha 值, BF2 使用的是互补值。
- 一般情况下,我们设置 LTDC_LxCACR 的值为 255,这样,在使用恒定 Alpha 值的时候,BF1 = 1、BF2 = 0,这样就可以得到 BC=C,即混合后的颜色,就是显存里面的颜色(不进行混色)。
层窗口水平位置配置寄存器 LTDC_LxWHPCR(x=1/2)

该寄存器定义第 1 层或第 2 层窗口的水平位置(第一个和最后一个像素),其中:
- WHSTPOS:窗口水平起始位置,定义层窗口的一行的第一个可见像素。
- WHSPPOS:窗口水平停止位置,定义层窗口的一行的最后一个可见像素。
层窗口垂直位置配置寄存器 LTDC_LxWVPCR(x=1/2)

该寄存器定义第 1 层或第 2 层窗口的垂直位置(第一行或最后一行),其中:
- WVSTPOS:窗口垂直起始位置,定义层窗口的第一个可见行,见图 27.1.2.15。
- WVSPPOS:窗口垂直停止位置,定义层窗口的最后一个可见行,见图 27.1.2.15。
LTDC 的层支持窗口设置功能,通过 LTDC_LxWHPCR 和 LTDC_LxWVPCR 这上面两个寄存器设置,可以调整显示区域的大小,如图:

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

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

该寄存器定义颜色帧缓冲区中的行数。
CFBLNBR: 用于定义帧缓冲区行数,比如, LCD 面板的分辨率为 800*480,那么帧缓冲区的行数为 480 行,则设置 CFBLNBR=480 即可。
时钟域
LTDC 有三个时钟域: AXI 时钟域( ltdc_aclk) 、 APB3 时钟域( ltdc_plck)和像素时钟域( ltdc_ker_ck)。
AXI 时钟域( ltdc_aclk):用于驱动接口读取寄存器的数据到FIFO中。
APB3 时钟域( ltdc_plck):配置寄存器。
像素时钟域( ltdc_ker_ck):生成LCD接口信号( LCD_HSYNC、 LCD_VSYNC和 LCD_CLK等),这些时钟信号需根据 LCD面板的要求进行配置。
LCD_CLK配置过程
LCD_CLK的时钟 源来自 ltdc_ker_ck 而 ltdc_ker_ck 则来自 PLL3的 R分频。下图则是配置过程:

由图可知,ltdc_ker_ck 的来源 为 clk_in 一般 为外部晶振(假定外部晶振作为系统时钟源),经过 DIVM3分频器分频, 输入锁相环进行倍频( DIVN3)和分频 DIVR3),输出 pll3_r_ck 然后通过 PKSU和 PKEU得到 ltdc_ker_ck,最终输出到 LTDC,产生 LCD_CK,驱动液晶面板。
配置 LTDC
点击查看代码
/* LTDC 配置 */
#define LTDC_PIXFORMAT LTDC_PIXEL_FORMAT_RGB565
/**
* @brief LTDC初始化函数
* @param 无
* @retval 无
*/
void ltdc_init(void)
{
uint16_t lcdid = 0;
lcdid = ltdc_panelid_read(); /* 读取LCD面板ID */
if (lcdid == 0X4342)
{
lcdltdc.pwidth = 480; /* 面板宽度,单位:像素 */
lcdltdc.pheight = 272; /* 面板高度,单位:像素 */
lcdltdc.hsw = 1; /* 水平同步宽度 */
lcdltdc.vsw = 1; /* 垂直同步宽度 */
lcdltdc.hbp = 40; /* 水平后廊 */
lcdltdc.vbp = 8; /* 垂直后廊 */
lcdltdc.hfp = 5; /* 水平前廊 */
lcdltdc.vfp = 8; /* 垂直前廊 */
ltdc_clk_set(300, 25, 33); /* 设置像素时钟 9Mhz */
/* 其他参数待定. */
}
else if (lcdid == 0X7084)
{
lcdltdc.pwidth = 800; /* 面板宽度,单位:像素 */
lcdltdc.pheight = 480; /* 面板高度,单位:像素 */
lcdltdc.hsw = 1; /* 水平同步宽度 */
lcdltdc.vsw = 1; /* 垂直同步宽度 */
lcdltdc.hbp = 46; /* 水平后廊 */
lcdltdc.vbp = 23; /* 垂直后廊 */
lcdltdc.hfp = 210; /* 水平前廊 */
lcdltdc.vfp = 22; /* 垂直前廊 */
ltdc_clk_set(300, 25, 9); /* 设置像素时钟 33M(如果开双显,需要降低DCLK到:18.75Mhz 300/4/4,才会比较好) */
}
else if (lcdid == 0X7016)
{
lcdltdc.pwidth = 1024; /* 面板宽度,单位:像素 */
lcdltdc.pheight = 600; /* 面板高度,单位:像素 */
lcdltdc.hsw = 20; /* 水平同步宽度 */
lcdltdc.vsw = 3; /* 垂直同步宽度 */
lcdltdc.hbp = 140; /* 水平后廊 */
lcdltdc.vbp = 20; /* 垂直后廊 */
lcdltdc.hfp = 160; /* 水平前廊 */
lcdltdc.vfp = 12; /* 垂直前廊 */
ltdc_clk_set(300, 25, 6); /* 设置像素时钟 40Mhz 6 */
/* 其他参数待定.*/
}
else if (lcdid == 0X7018)
{
lcdltdc.pwidth = 1280; /* 面板宽度,单位:像素 */
lcdltdc.pheight = 800; /* 面板高度,单位:像素 */
/* 其他参数待定.*/
}
else if (lcdid == 0X4384)
{
lcdltdc.pwidth = 800; /* 面板宽度,单位:像素 */
lcdltdc.pheight = 480; /* 面板高度,单位:像素 */
lcdltdc.hbp = 88; /* 水平后廊 */
lcdltdc.hfp = 40; /* 水平前廊 */
lcdltdc.hsw = 48; /* 水平同步宽度 */
lcdltdc.vbp = 32; /* 垂直后廊 */
lcdltdc.vfp = 13; /* 垂直前廊 */
lcdltdc.vsw = 3; /* 垂直同步宽度 */
ltdc_clk_set(300, 25, 9); /* 设置像素时钟 33M */
/* 其他参数待定. */
}
else if (lcdid == 0X1018)
{
lcdltdc.pwidth = 1280; /* 面板宽度,单位:像素 */
lcdltdc.pheight = 800; /* 面板高度,单位:像素 */
lcdltdc.hbp = 140; /* 水平后廊 */
lcdltdc.hfp = 10; /* 水平前廊 */
lcdltdc.hsw = 10; /* 水平同步宽度 */
lcdltdc.vbp = 10; /* 垂直后廊 */
lcdltdc.vfp = 10; /* 垂直前廊 */
lcdltdc.vsw = 3; /* 垂直同步宽度 */
ltdc_clk_set(300, 25, 6); /* 设置像素时钟 45Mhz */
}
lcddev.width = lcdltdc.pwidth;
lcddev.height = lcdltdc.pheight;
#if LTDC_PIXFORMAT == LTDC_PIXFORMAT_ARGB8888 || LTDC_PIXFORMAT == LTDC_PIXFORMAT_RGB888
g_ltdc_framebuf[0] = (uint32_t*) <dc_lcd_framebuf;
lcdltdc.pixsize = 4; /* 每个像素占4个字节 */
#else
lcdltdc.pixsize = 2; /* 每个像素占2个字节 */
g_ltdc_framebuf[0] = (uint32_t*)<dc_lcd_framebuf;
// g_ltdc_framebuf[1] = (uint32_t*)<dc_lcd_framebuf1;
#endif
/* LTDC配置 */
g_ltdc_handle.Instance = LTDC;
g_ltdc_handle.Init.HSPolarity = LTDC_HSPOLARITY_AL; /* 水平同步极性 */
g_ltdc_handle.Init.VSPolarity = LTDC_VSPOLARITY_AL; /* 垂直同步极性 */
g_ltdc_handle.Init.DEPolarity = LTDC_DEPOLARITY_AL; /* 数据使能极性 */
g_ltdc_handle.State = HAL_LTDC_STATE_RESET;
if (lcdid == 0X1018)
{
g_ltdc_handle.Init.PCPolarity = LTDC_PCPOLARITY_IIPC; /* 像素时钟极性 */
}
else
{
g_ltdc_handle.Init.PCPolarity = LTDC_PCPOLARITY_IPC; /* 像素时钟极性 */
}
g_ltdc_handle.Init.HorizontalSync = lcdltdc.hsw - 1; /* 水平同步宽度 */
g_ltdc_handle.Init.VerticalSync = lcdltdc.vsw - 1; /* 垂直同步宽度 */
g_ltdc_handle.Init.AccumulatedHBP = lcdltdc.hsw + lcdltdc.hbp - 1; /* 水平同步后沿宽度 */
g_ltdc_handle.Init.AccumulatedVBP = lcdltdc.vsw + lcdltdc.vbp - 1; /* 垂直同步后沿高度 */
g_ltdc_handle.Init.AccumulatedActiveW = lcdltdc.hsw + lcdltdc.hbp + lcdltdc.pwidth - 1; /* 有效宽度 */
g_ltdc_handle.Init.AccumulatedActiveH = lcdltdc.vsw + lcdltdc.vbp + lcdltdc.pheight - 1; /* 有效高度 */
g_ltdc_handle.Init.TotalWidth = lcdltdc.hsw + lcdltdc.hbp + lcdltdc.pwidth + lcdltdc.hfp - 1; /* 总宽度 */
g_ltdc_handle.Init.TotalHeigh = lcdltdc.vsw + lcdltdc.vbp + lcdltdc.pheight + lcdltdc.vfp - 1; /* 总高度 */
g_ltdc_handle.Init.Backcolor.Red = 0; /* 屏幕背景层红色部分 */
g_ltdc_handle.Init.Backcolor.Green = 0; /* 屏幕背景层绿色部分 */
g_ltdc_handle.Init.Backcolor.Blue = 0; /* 屏幕背景色蓝色部分 */
HAL_LTDC_Init(&g_ltdc_handle);
/* 层配置:LTDC(LCD-TFT显示控制器)支持多层显示,通过配置不同层实现图像叠加等效果 */
/*
* 配置LTDC第0层的参数
* 参数说明:
* 第一个参数:0 - 层索引,指定配置第0层(LTDC通常支持多层,此处配置第1层)
* 第二个参数:(uint32_t)g_ltdc_framebuf[0] - 该层的帧缓冲区地址,g_ltdc_framebuf[0]为存储第0层图像数据的数组
* 第三个参数:LTDC_PIXFORMAT - 像素格式(如RGB565、ARGB8888等,由宏定义具体指定)
* 第四个参数:255 - 图层透明度(0-255,255表示完全不透明,0表示完全透明)
* 第五个参数:0 - 混合因子(通常用于图层叠加计算,0表示不使用特殊混合规则)
* 第六个参数:6 - 水平同步后沿(HSYNC之后的无效像素数,根据LCD时序特性配置)
* 第七个参数:7 - 垂直同步后沿(VSYNC之后的无效行数,根据LCD时序特性配置)
* 第八个参数:0X000000 - 背景色(当图层无有效数据时显示的颜色,此处为黑色)
*/
ltdc_layer_parameter_config(0, (uint32_t)g_ltdc_framebuf[0], LTDC_PIXFORMAT, 255, 0, 6, 7, 0X000000); /* 层参数配置 */
/*
* 配置LTDC第0层的显示窗口
* 参数说明:
* 第一个参数:0 - 层索引,指定配置第0层
* 第二个参数:0 - 窗口左上角X坐标(以LCD面板坐标系为原点,横向起始位置)
* 第三个参数:0 - 窗口左上角Y坐标(以LCD面板坐标系为原点,纵向起始位置)
* 第四个参数:lcdltdc.pwidth - 窗口宽度(等于LCD面板的实际宽度,确保全屏显示)
* 第五个参数:lcdltdc.pheight - 窗口高度(等于LCD面板的实际高度,确保全屏显示)
* 注意:窗口坐标以LCD面板原生坐标系为基准,直接影响图像在屏幕上的显示位置,非特殊需求请勿修改
*/
ltdc_layer_window_config(0, 0, 0, lcdltdc.pwidth, lcdltdc.pheight); /* 层窗口配置,以LCD面板坐标系为基准,不要随便修改! */
/*
* 以下为第1层的配置示例(当前被注释禁用)
* 第1层可用于叠加在第0层上方显示额外内容(如UI控件、状态信息等)
*/
// /*
// * 配置LTDC第1层的参数
// * 与第0层相比,主要差异在于透明度设为127(半透明),帧缓冲区使用g_ltdc_framebuf[1]
// */
// ltdc_layer_parameter_config(1,(uint32_t)g_ltdc_framebuf[1],LTDC_PIXFORMAT,127,0,6,7,0X000000); /* 层参数配置 */
//
// /*
// * 配置LTDC第1层的显示窗口
// * 窗口大小与第0层一致,默认全屏叠加(可根据需求修改为局部区域显示)
// */
// ltdc_layer_window_config(1,0,0,lcdltdc.pwidth,lcdltdc.pheight); /* 层窗口配置,以LCD面板坐标系为基准,不要随便修改! */
// ltdc_display_dir(0); /* 默认竖屏 */
ltdc_select_layer(0); /* 选择第1层 */
LTDC_BL(1); /* 点亮背光 */
ltdc_clear(0XFFFFFFFF); /* 清屏 */
}
/**
* @brief LTDC层基本参数设置
* @note 此函数,必须在ltdc_layer_window_config之前设置.
* @param layerx : 0,第一层; 1,第二层;
* @param bufaddr : 层颜色帧缓存起始地址
* @param pixformat : 颜色格式. 0,ARGB8888; 1,RGB888; 2,RGB565; 3,ARGB1555; 4,ARGB4444; 5,L8; 6;AL44; 7;AL88
* @param alpha : 层颜色Alpha值, 0,全透明;255,不透明
* @param alpha0 : 默认颜色Alpha值, 0,全透明;255,不透明
* @param bfac1 : 混合系数1, 4(100),恒定的Alpha; 6(101),像素Alpha*恒定Alpha
* @param bfac2 : 混合系数2, 5(101),恒定的Alpha; 7(111),像素Alpha*恒定Alpha
* @param bkcolor : 层默认颜色,32位,低24位有效,RGB888格式
* @retval 无
*/
void ltdc_layer_parameter_config(uint8_t layerx, uint32_t bufaddr, uint8_t pixformat, uint8_t alpha, uint8_t alpha0, uint8_t bfac1, uint8_t bfac2, uint32_t 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 = (uint32_t)bfac1 << 8; /* 设置层混合系数 */
playercfg.BlendingFactor2 = (uint32_t)bfac2; /* 设置层混合系数 */
playercfg.FBStartAdress = bufaddr; /* 设置层颜色帧缓存起始地址 */
playercfg.ImageWidth = lcdltdc.pwidth; /* 设置颜色帧缓冲区的宽度 */
playercfg.ImageHeight = lcdltdc.pheight; /* 设置颜色帧缓冲区的高度 */
playercfg.Backcolor.Red = (uint8_t)(bkcolor & 0X00FF0000) >> 16; /* 背景颜色红色部分 */
playercfg.Backcolor.Green = (uint8_t)(bkcolor & 0X0000FF00) >> 8; /* 背景颜色绿色部分 */
playercfg.Backcolor.Blue = (uint8_t)bkcolor & 0X000000FF; /* 背景颜色蓝色部分 */
HAL_LTDC_ConfigLayer(&g_ltdc_handle, &playercfg, layerx); /* 设置所选中的层 */
}
/**
* @brief LTDC层窗口设置, 窗口以LCD面板坐标系为基准
* @note 此函数必须在ltdc_layer_parameter_config之后再设置.另外,当设置的窗口值不等于面板的尺
* 寸时,GRAM的操作(读/写点函数),也要根据窗口的宽高来进行修改,否则显示不正常(本例程就未做修改).
* @param layerx : 0,第一层; 1,第二层;
* @param sx, sy : 起始坐标
* @param width,height: 宽度和高度
* @retval 无
*/
void ltdc_layer_window_config(uint8_t layerx, uint16_t sx, uint16_t sy, uint16_t width, uint16_t height)
{
HAL_LTDC_SetWindowPosition(&g_ltdc_handle, sx, sy, layerx); /* 设置窗口的位置 */
HAL_LTDC_SetWindowSize(&g_ltdc_handle, width, height, layerx); /* 设置窗口大小 */
}
/**
* @brief LTDC底层IO初始化和时钟使能
* @note 此函数会被HAL_LTDC_Init()调用
* @param hltdc:LTDC句柄
* @retval 无
*/
void HAL_LTDC_MspInit(LTDC_HandleTypeDef *hltdc)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_LTDC_CLK_ENABLE(); /* 使能LTDC时钟 */
__HAL_RCC_DMA2D_CLK_ENABLE(); /* 使能DMA2D时钟 */
/* 以下是LTDC信号控制引脚 BL/DE/VSYNC/HSYNC/CLK等的配置 */
LTDC_BL_GPIO_CLK_ENABLE(); /* LTDC_BL脚时钟使能 */
LTDC_DE_GPIO_CLK_ENABLE(); /* LTDC_DE脚时钟使能 */
LTDC_VSYNC_GPIO_CLK_ENABLE(); /* LTDC_VSYNC脚时钟使能 */
LTDC_HSYNC_GPIO_CLK_ENABLE(); /* LTDC_HSYNC脚时钟使能 */
LTDC_CLK_GPIO_CLK_ENABLE(); /* LTDC_CLK脚时钟使能 */
__HAL_RCC_GPIOH_CLK_ENABLE(); /* GPIOH时钟使能 */
/* 初始化PB5,背光引脚 */
gpio_init_struct.Pin = LTDC_BL_GPIO_PIN; /* LTDC_BL引脚模式设置 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_HIGH; /* 高速 */
HAL_GPIO_Init(LTDC_BL_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = LTDC_DE_GPIO_PIN; /* LTDC_DE引脚模式设置 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用 */
gpio_init_struct.Pull = GPIO_NOPULL;
gpio_init_struct.Speed = GPIO_SPEED_HIGH;
gpio_init_struct.Alternate = GPIO_AF14_LTDC; /* 复用为LTDC */
HAL_GPIO_Init(LTDC_DE_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = LTDC_VSYNC_GPIO_PIN; /* LTDC_VSYNC引脚模式设置 */
HAL_GPIO_Init(LTDC_VSYNC_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = LTDC_HSYNC_GPIO_PIN; /* LTDC_HSYNC引脚模式设置 */
HAL_GPIO_Init(LTDC_HSYNC_GPIO_PORT, &gpio_init_struct);
gpio_init_struct.Pin = LTDC_CLK_GPIO_PIN; /* LTDC_CLK引脚模式设置 */
HAL_GPIO_Init(LTDC_CLK_GPIO_PORT, &gpio_init_struct);
/* 初始化PG6,11 */
gpio_init_struct.Pin = GPIO_PIN_6 | GPIO_PIN_11;
HAL_GPIO_Init(GPIOG, &gpio_init_struct);
/* 初始化PH9,10,11,12,13,14,15 */
gpio_init_struct.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_init_struct);
/* 初始化PI0,1,2,4,5,6,7 */
gpio_init_struct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5| \
GPIO_PIN_6 | GPIO_PIN_7;
HAL_GPIO_Init(GPIOI, &gpio_init_struct);
}
通过以上几个步骤,我们就完成了 LTDC 的配置,可以控制 RGBLCD 显示了。
博客导航
本文来自博客园,作者:膝盖中箭卫兵,转载请注明原文链接:https://www.cnblogs.com/Skyrim-sssuuu/p/19163545

浙公网安备 33010602011771号
https://orcid.org/0000-0001-5102-772X