专栏首页安富莱嵌入式技术分享【STM32H7教程】第50章 STM32H7的LCD控制器LTDC基础知识和HAL库API

【STM32H7教程】第50章 STM32H7的LCD控制器LTDC基础知识和HAL库API

完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980

第50章       STM32H7的LCD控制器LTDC基础知识和HAL库API

本章节为大家讲解LCD控制器LTDC(LCD-TFT display controller),实际项目中用到显示屏的地方全靠它了,而且性能也比较给力。

50.1 初学者重要提示

50.2 LTDC基础知识

50.3 LTDC的HAL库用法

50.4 源文件stm32h7xx_hal_ltdc.c

50.5 总结

50.1 初学者重要提示

  1.   本章50.2小节中的几个知识点比较重要,比如DE同步模式和HV同步模式的区别,Alpha混合,水平消隐和垂直消隐等知识点尤其重要,需要大家理解透彻。
  2.   测评STM32H7的LTDC+DMA2D性能,100Hz以上无压力,刷800*480图片和色块仅需2.6ms一张:http://www.armbbs.cn/forum.php?mod=viewthread&tid=91489

50.2 LTDC基础知识

LTDC的几个关键知识点放在开头说:

  1.   STM32H7的LTDC最大支持1024*768分辨率,且支持硬件双图层。实际支持的分辨率可能比1024*768要高一点,因为最终可以支持的最大分辨率是芯片后期定标的。
  2.   支持32位色,24位色,16位色和8位色。
  3.   可编程窗口位置和大小,可编程行同步,场同步和数据使能信号的极性。
  4.   查色表 (CLUT,Color look-up table),每个图层最高可记录256种24位色。
  5.   支持如下8种颜色格式:
  •   ARGB8888

32位颜色格式,一个像素点占用4字节,其中低位 3 字节用于颜色分量,高位字节用于 Alpha 混合。红、绿、蓝和 Alpha通道(0x00表示完全透明,0xFF表示完全不透明)都是 8 位表示。颜色格式:AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB。

  •   RGB888

24位颜色格式,一个像素点占用3字节,分别用于红、绿、蓝。

颜色格式:RRRRRRRRGGGGGGGGBBBBBBBB。

  •   RGB565

16位颜色格式,一个像素点占用2字节,分别用于红、绿、蓝。

颜色格式:RRRRRGGGGGGBBBBB。

  •   ARGB1555

16位颜色格式,一个像素点占用2字节,Alpha通道使用1个位表示,等于0的时候表示完全透明,等于1的时候表示完全不透明。红、绿、蓝都是用5个位表示。

颜色格式:ARRRRRGGGGGBBBBB。

  •   ARGB4444

16位颜色格式,一个像素点占用2字节,Alpha通道使用2个位表示(0x0表示完全透明,0x3表示完全不透明)。红、绿、蓝都是用4个位表示。

颜色格式:ARRRRRGGGGGBBBBB。

  •   L8 (8-bit luminance or CLUT)

8位颜色格式,实际上仅仅是8位索引值,范围0–255,而每个索引值的具体颜色值在查色表CLUT里面存储。

  •   AL44 (4-bit alpha + 4-bit luminance)

8位颜色格式,实际上是4位Alpha通道(0x0表示完全透明,0xF表示完全不透明)和4位的索引值,索引范围0–15,而每个索引值的具体颜色值在查色表CLUT里面存储。

  •   AL88 (8-bit alpha + 8-bit luminance)

16位颜色格式,实际上是8位Alpha通道(0x00表示完全透明,0xFF表示完全不透明)和8位的索引值,索引范围0–255,而每个索引值的具体颜色值在查色表CLUT里面存储。

50.2.1 LTDC硬件框图

认识一个外设,最好的方式就是看它的框图,方便我们快速地了解LTDC的基本功能,然后再看手册了解细节。框图如下所示:

通过这个框图,我们可以得到如下信息:

  •   ltdc_aclk

为LTDC寄存器提供时钟,时钟来自AXI时钟域。

  •   ltdc_pclk

LTDC寄存器接口时钟。

  •   ltdc_ker_ck

用于生成LCD_CLK(像素时钟输出)的LTDC内核时钟。

  •   ltdc_li_it

LTDC行中断,用于触发MDMA。

  •   ltdc_it

LTDC全局中断请求。

  •   ltdc_err_it

LTDC全局错误中断请求。

下面是LCD接口引脚,用于外接显示屏:

  •   LCD_CLK

像素时钟输出。

  •   LCD_HSYNC

水平同步信号。

  •   LCD_VSYN

垂直同步信号。

  •   LCD_DE

数据使能信号。

  •   LCD_R[7:0]

8位红色数据。

  •   LCD_G[7:0]

8 位绿色数据。

  •   LCD_B[7:0]

8位蓝色数据。

50.2.2 LTDC时钟源选择

LTDC仅有一个时钟源可供选择,即PLL3R。

50.2.3 LCD的DE同步模式和HV同步模式的区别

 一般情况下,STM32H7都是用SDRAM作为LCD的显存,LTDC控制器会从SDRAM读取数据刷新到LCD显示屏上,具体如何刷新呢?这就涉及到DE同步模式和HV同步模式。

具体支持哪种模式是由裸屏自带的Driver IC决定,比如V7板子7寸裸屏的Source Driver IC OTA7001支持DE和HV两种模式。现在的大分辨率显示屏一般都是DE同步模式,小分辨率的HV同步模式多。

  •   DE同步模式

DE模式需要LCD_DE和LCD_CLK信号来控制刷新。比如一个800x480分辨率的裸屏,在DE有效信号的时候(高电平或低电平),就有800个LCD_CLK输出时钟来确认行中800个点。每个时钟有效的时候,从显存读取一次RGB数据。因为存在回扫信号,所以DE是个方波。一个周期的LCD_DE信号,裸屏就扫描一行。扫描480行后,又从第一行扫描开始。这个规律由裸屏的驱动IC所决定的。

  •   HV同步模式

HV模式需要LCD_CLK时钟信号,行同步信号LCD_HSYNC和场同步信号LCD_VSYNC来控制刷新。比如一个480x272分辨率的裸屏,有一个行同步信号LCD_HSYNC产生时(高电平或者低电平脉冲),就有480个LCD_CLK输出时钟来确认行中480个点。每个时钟有效的时候,从显存读取一次RGB数据。再来一个行同步信号LCD_HSYNC产生时(高电平或者低电平脉冲),切换到下一行,继续行同步和时钟输出,扫描272行后,发送一个场同步信号LCD_VSYNC,又重新从第一行扫描开始。

具体的时序效果可以看第51章的内容。

50.2.4 LTDC的时序配置

 LTDC的时序控制就是下面几个参数的设置,这几个参数都可以通过寄存器进行配置。

  •   HSYNC width

水平同步宽度设置,以LCD_CLK的像素时钟输出为单位。

  •   HBP(horizontal back porch period)

水平后沿周期设置,以LCD_CLK的像素时钟输出为单位。

  •   Active width

有效宽度设置,以LCD_CLK的像素时钟输出为单位。以800*480分辨率为例,Active width = 800。

  •   HFP(horizontal front porch period)

水平前沿周期设置,以LCD_CLK的像素时钟输出为单位。

  •   VSYNC width

垂直同步宽度设置,以LCD_CLK的像素时钟输出为单位。

  •   VBP(vertical back porch period)

垂直后沿周期设置,以LCD_CLK的像素时钟输出为单位。

  •   Active height

有效高度设置,以LCD_CLK的像素时钟输出为单位。以800*480分辨率为例,Active height = 480。

  •   VFP(vertical front porch period)

垂直前沿周期设置,以LCD_CLK的像素时钟输出为单位。

50.2.5 LTDC背景层,图层1,图层2和Alpha混合

LTDC除了图层1和图层2两个硬件图层以外,还有一个背景层。由于背景层的刷新不需要显存空间,所以可以用这个图层验证LTDC时序配置是否有问题。

  •   对于背景层来说,仅支持单色设置,固定颜色格式RGB888(LTDC_HandleTypeDef hltdc_F)hltdc_F.Init.Backcolor.Blue = 0

hltdc_F.Init.Backcolor.Green = 0

hltdc_F.Init.Backcolor.Red = 0

  •   对于图层1和图层2来说,支持如下8种颜色格式:

– ARGB8888

– RGB888

– RGB565

– ARGB1555

– ARGB4444

– L8(8 位 Luminance 或 CLUT)

– AL44(4 位 alpha + 4 位 luminance)

– AL88(8 位 alpha + 8 位 luminance)

  •   实现Alpha混合的关键是要有一个变量可以设置各种透明度。对此,STM32H7准备了两个Alpha供使用:
    •   一个是常数Alpha(0x00表示完全透明,0xFF表示完全不透明),所有颜色格式都可以使用。
    •   另一个是像素Alpha,也就是ARGB8888,ARGB1555,ARGB4444等颜色格式的Alpha通道数值,也就是我们为图层每个位置绘制的实际颜色值。

==================================

了解了这点后就是具体的实现了。STM32H7的参考手册给出了具体的混合公式

BC          =  BF1       x     C     +   BF2      x    Cs

混合后的颜色= 混合系数1 x 当前层颜色 + 混合系数2 x 底层混合后的颜色

  •   混合系数1可以选择:

(1)常数 Alpha

(2)像素 Alpha x 常数 Alpha

  •   混合系数2可以选择:

(1)1 - 常数 Alpha

(2)1 - 像素 Alpha x 常数 Alpha

  •   底层混合后的颜色:

(1)可以是背景层。

(2)可以是背景层与图层1混合后的颜色。

  •   那么公式就变成如下形式(主要是如下两种):

混合后的颜色 = 常数 Alpha x 当前层颜色 + (1 - 常数 Alpha) x 底层混合后的颜色。

混合后的颜色 = 像素 Alpha x 常数 Alpha x 当前层颜色 +(1 - 像素 Alpha x 常数 Alpha) x 底层混合后的颜色。

  •   再进一步简化,代入HAL库参数(LTDC_LayerCfgTypeDef  pLayerCfg):

像素Alpha是ARGB8888,ARGB1555等颜色格式的Alpha数值,也就是我们为图层每个位置绘制的实际颜色值,我们这里用AlphaValue表示。

混合后的颜色 = (pLayerCfg.Alpha /255 ) x 当前层颜色 +(1 - pLayerCfg.Alpha /255 ) x 底层混合后的颜色。

混合后的颜色 = (AlphaValue/255)x (pLayerCfg.Alpha /255 ) x 当前层颜色 +(1 - (AlphaValue/255)x (pLayerCfg.Alpha /255 )) x 底层混合后的颜色。

注,Alpha值要做归一化,Alpha的范围是0 - 255,比如Alpha = 100,那么代入公式的时候就是100/255。

  •   举例:

(1)混合因数1选择像素 Alpha x 常数 Alpha。

(2)混合因数2选择像素 Alpha x 常数 Alpha。

(3)使用图层1和背景层,图层1使用ARGB8888颜色格式。

(4)背景色 = 0xFF0000,图层1位置坐标(0,0)颜色值0x5500FF00。

(5)Alpha常数 = 0x77

混合后的颜色 = (AlphaValue/255)x (pLayerCfg.Alpha /255 ) x 当前层颜色 +(1 - (AlphaValue/255)x (pLayerCfg.Alpha /255 )) x 底层混合后的颜色。

             = (0x55/255)x (0x77/255) x 0x00FF00 +(1 - (0x55/255)x (0x77/255)) x 0xFF0000

             =  0xD7809C

  •   最后注意一点:

如果大家设置的图层显示区没有显示满整个显示屏,且使用的ARGB颜色格式,那么未覆盖的区域会使用图层默认颜色。对此HAL库有专门的配置:

LTDC_LayerCfgTypeDef      pLayerCfg

pLayerCfg.Alpha0 = 0;

pLayerCfg.Backcolor.Blue = 0;

pLayerCfg.Backcolor.Green = 0;

pLayerCfg.Backcolor.Red = 0;

50.2.6 LTDC的水平消隐和垂直消隐

正常情况下,LCD的刷新就是从左到右,从上到下进行逐个像素点刷新。但仅刷新有效的显示区是不够的,比如800*480分辨率,我们不仅仅要刷800*480这段有效区域,边界区也是要刷新的,即下图总宽度以内,有效宽度以外的区域。

水平消隐就是LCD扫描一行结束到另一行开始的时间,这段消失的时间就是水平消隐,即HSYNC宽度+ HBP + HFP这段消失的时间。

垂直消隐就是LCD扫描最后一行结束到第一行开始的时间,这段消失的时间就是垂直消隐,即VSYNC宽度+ VBP + VFP这段消失的时间。

50.2.7 区分FPS帧率和刷新率

FPS帧率是对STM32H7刷到显存,也就是SDRAM里面来说的,而是刷新率是实际LCD显示的速度。

刷新率 = LTDC输出时钟 /((Width + HSYNC_W  + HBP  + HFP )*(Height + VSYNC_W +  VBP  +VFP  ))

一般情况下,帧率是远高于刷新率的,但帧数高于刷新率有没有意义?网上普遍的看法是高于刷新率的帧数都是浪费,比如H7刷800*480分辨率显示屏,帧数可以达到300多,而刷新率估计才108Hz,多出来的不是都浪费了吗(对于那种FPS类的游戏,我们不讨论)。

对于这种观点,在一定情况下是成立的。但是有一点,即使是帧数和刷新率都是108Hz,能保证显示没有撕裂感吗?能保证没有帧延迟吗?能保证流畅的画面吗?这个时候,我们使用emWin支持的三缓冲,多余的帧数完全可以输出到其它缓冲区,有效降低撕裂感和帧延迟,保证流畅输出。

50.2.8 避免 LTDC刷新撕裂感的解决办法

如果用户快速刷新颜色差异比较大的两种界面,容易遇到这种撕裂问题。

  •   出现这个问题的原因

用户更新显存数据期间,LTDC也在不断的读取显存的数据到显示屏上,如果用户才更新了部分界面数据,后面部分还没有更新,LTDC刷新到显示屏的界面效果出现撕裂感,即下面这种现象:

  •   解决这个问题的办法

LTDC刷新还在垂直消隐期间就将整个界面刷新完成,而我们如何只知道LTDC在垂直消隐期,通过函数HAL_LTDC_ProgramLineEvent设置刷新到指定行时进入中断即可,一般设置为第0行进入中断,然后设置个标志即可。

一旦检测到这个标志,就通过DMA2D快速将界面刷新好,这样就有效的避免了撕裂感。

50.3 LTDC的HAL库用法

LTDC的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置GPIO、时钟,并根据需要配置NVIC、中断和DMA。下面我们逐一展开为大家做个说明。

50.3.1 LTDC寄存器结构体LTDC_TypeDef

LTDC相关的寄存器是通过HAL库中的结构体LTDC_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:

typedef struct
{
  uint32_t      RESERVED0[2];/*!< Reserved,                                                    0x00-0x04 */
  __IO uint32_t SSCR;     /*!< LTDC Synchronization Size Configuration Register,    Address offset: 0x08 */
  __IO uint32_t BPCR;     /*!< LTDC Back Porch Configuration Register,              Address offset: 0x0C */
  __IO uint32_t AWCR;     /*!< LTDC Active Width Configuration Register,            Address offset: 0x10 */
  __IO uint32_t TWCR;     /*!< LTDC Total Width Configuration Register,             Address offset: 0x14 */
  __IO uint32_t GCR;      /*!< LTDC Global Control Register,                        Address offset: 0x18 */
  uint32_t      RESERVED1[2]; /*!< Reserved,                                                   0x1C-0x20 */
  __IO uint32_t SRCR;     /*!< LTDC Shadow Reload Configuration Register,            Address offset: 0x24 */
  uint32_t      RESERVED2[1]; /*!< Reserved,                                                        0x28 */
  __IO uint32_t BCCR;     /*!< LTDC Background Color Configuration Register,        Address offset: 0x2C */
  uint32_t      RESERVED3[1];  /*!< Reserved,                                                       0x30 */
  __IO uint32_t IER;      /*!< LTDC Interrupt Enable Register,                      Address offset: 0x34 */
  __IO uint32_t ISR;      /*!< LTDC Interrupt Status Register,                      Address offset: 0x38 */
  __IO uint32_t ICR;      /*!< LTDC Interrupt Clear Register,                       Address offset: 0x3C */
  __IO uint32_t LIPCR;    /*!< LTDC Line Interrupt Position Configuration Register, Address offset: 0x40 */
  __IO uint32_t CPSR;     /*!< LTDC Current Position Status Register,               Address offset: 0x44 */
  __IO uint32_t CDSR;     /*!< LTDC Current Display Status Register,                 Address offset: 0x48 */
} LTDC_TypeDef; 

__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:

#define     __O     volatile             /*!< Defines 'write only' permissions */
#define     __IO    volatile             /*!< Defines 'read / write' permissions */

下面我们再看LTDC的定义,在stm32h743xx.h文件。

#define PERIPH_BASE           ((uint32_t)0x40000000)              
#define D1_APB1PERIPH_BASE    (PERIPH_BASE + 0x10000000)

#define LTDC_BASE             (D1_APB1PERIPH_BASE + 0x1000)
#define LTDC                  ((LTDC_TypeDef *)LTDC_BASE) <----- 展开这个宏,(LTDC_TypeDef *) 0x50001000

我们访问LTDC的ISR寄存器可以采用这种形式:LTDC->ISR = 0。

50.3.2 LTDC参数初始化结构体LTDC_InitTypeDef

此结构体用于配置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;

下面将这几个参数逐一为大家做个说明:

  •  uint32_t   HSPolarity

此参数用于设置水平同步信号极性,具体支持的参数如下:

#define LTDC_HSPOLARITY_AL  (0x00000000U)            /* 水平同步极性低电平有效 */
#define LTDC_HSPOLARITY_AH   LTDC_GCR_HSPOL          /* 水平同步极性高电平有效 */
  •   uint32_t   VSPolarity

此参数用于设置垂直同步信号极性,具体支持的参数如下:

#define LTDC_VSPOLARITY_AL   (0x00000000U)           /* 垂直同步极性低电平有效 */
#define LTDC_VSPOLARITY_AH   LTDC_GCR_VSPOL          /* 垂直同步极性高电平有效 */
  •   uint32_t   DEPolarity

此参数用于设置数据使能极性,具体支持的参数如下:

#define LTDC_DEPOLARITY_AL   (0x00000000U)           /* 数据使能极性低电平有效 */
#define LTDC_DEPOLARITY_AH    LTDC_GCR_DEPOL         /* 数据使能极性高电平有效 */
  •   uint32_t   PCPolarity

此参数用于设置像素时钟极性,具体支持的参数如下:     

#define LTDC_PCPOLARITY_IPC    (0x00000000U)       /* 像素时钟极性低电平有效 */
#define LTDC_PCPOLARITY_IIPC   LTDC_GCR_PCPOL      /* 像素时钟极性告电平有效 */
  •   uint32_t   HorizontalSync

此参数用于设置水平同步宽度,范围0x000 – 0xFFF,单位像素时钟个数。

  •   uint32_t   VerticalSync

此参数用于设置垂直同步宽度,范围0x000 – 0x7FF,单位像素时钟个数。

  •   uint32_t   AccumulatedHBP

此参数用于设置HSYNC水平同步宽度 + HBP水平后沿之和,范围HSYNC水平同步宽度到0xFFF,单位像素时钟个数。

  •   uint32_t   AccumulatedVBP

此参数用于设置VSYNC垂直同步宽度 + VBP垂直后沿之和,范围VSYNC垂直同步宽度到0x7FF,单位像素时钟个数。

  •   uint32_t   AccumulatedActiveW

此参数用于设置HSYNC水平同步宽度 + HBP水平后沿 + 有效宽度之和,范围AccumulatedHBP到0xFFF,单位像素时钟个数。

  •   uint32_t   AccumulatedActiveH

此参数用于设置VSYNC垂直同步宽度 + VBP垂直后沿 + 有效高度之和,范围AccumulatedVBP到0x7FF,单位像素时钟个数。

  •   uint32_t   TotalWidth

此参数用于设置HSYNC水平同步宽度 + HBP水平后沿 + 有效宽度 + HFP水平前沿之和,范围AccumulatedActiveW到0xFFF,单位像素时钟个数。

  •   uint32_t   TotalHeigh

此参数用于设置VSYNC垂直同步宽度 + VBP垂直后沿 + 有效高度 +VFP垂直前沿之和,范围AccumulatedActiveH到0x7FF,单位像素时钟个数。

  •   LTDC_ColorTypeDef   Backcolor

此参数用于设置背景层颜色,结构体LTDC_ColorTypeDef的定义如下:

typedef struct
{
  uint8_t Blue;                   
  uint8_t Green;                  
  uint8_t Red;                     
  uint8_t Reserved;                
} LTDC_ColorTypeDef;

Bule用于设置蓝色值,范围0x00到0xFF。

Green用于设置绿色值,范围0x00到0xFF。

Red用于设置红色值,范围0x00到0xFF。

50.3.3 LTDC图层配置结构体LTDC_LayerCfgTypeDef

此结构体用于配置LTDC的图层,图层1和图层2均通过此结构体配置。

typedef struct
{
  uint32_t WindowX0;                                                       
  uint32_t WindowX1;                 
  uint32_t WindowY0;                 
  uint32_t WindowY1;                   
  uint32_t PixelFormat;                
  uint32_t Alpha;                     
  uint32_t Alpha0;                     
  uint32_t BlendingFactor1;            
  uint32_t BlendingFactor2;            
  uint32_t FBStartAdress;             
  uint32_t ImageWidth;                
  uint32_t ImageHeight;               
  LTDC_ColorTypeDef   Backcolor;      
} LTDC_LayerCfgTypeDef;

下面将这几个参数逐一为大家做个说明。

  •   uint32_t WindowX0

设置图层水平起始位置,范围0x000到0xFFF。

  •   uint32_t WindowX1

设置图层水平结束位置,范围0x000到0xFFF。

  •   uint32_t WindowY0

设置图层垂直起始位置,范围0x000到0x7FF。

  •   uint32_t WindowY1

设置图层垂直结束位置,范围0x000到0x7FF。

  •   uint32_t PixelFormat

设置图层所使用的颜色格式。

  •   uint32_t Alpha

设置常数Alpha,范围0x00 – 0xFF。

  •   uint32_t Alpha0

设置图层默认Alpha值,范围0x00 – 0xFF,与结构体成员Backcolor一起使用,组成ARGB颜色格式用于图层背景色。

  •   uint32_t BlendingFactor1

设置混合因数1,具体支持的参数如下:

#define LTDC_BLENDING_FACTOR1_CA     (0x00000400U)   /* 常数Alpha */
#define LTDC_BLENDING_FACTOR1_PAxCA  (0x00000600U)   /* 常数Alpha * 像素Alpha */
  •   uint32_t BlendingFactor2

设置混合因数2,具体支持的参数如下:

#define LTDC_BLENDING_FACTOR2_CA     (0x00000400U)   /* 常数Alpha */
#define LTDC_BLENDING_FACTOR2_PAxCA  (0x00000600U)   /* 常数Alpha * 像素Alpha */
  •   uint32_t FBStartAdress

设置颜色帧缓冲区地址,即图层的显存地址。

  •   uint32_t ImageWidth

设置颜色帧缓冲区行长,即要从显存读取一行的长度,范围0x0000到0x1FFF。

  •   uint32_t ImageHeight

设置颜色帧缓冲区行数,即要从显存读取的行数,范围0x000到0xFFF。

  •   LTDC_ColorTypeDef   Backcolor

此参数用于设置图层默认色,结构体LTDC_ColorTypeDef的定义如下:

typedef struct
{
  uint8_t Blue;                   
  uint8_t Green;                  
  uint8_t Red;                     
  uint8_t Reserved;                
} LTDC_ColorTypeDef;

Bule用于设置蓝色值,范围0x00到0xFF。

Green用于设置绿色值,范围0x00到0xFF。

Red用于设置红色值,范围0x00到0xFF。

注:如果大家设置的图层显示区没有显示满整个显示屏,且使用的ARGB颜色格式,那么未覆盖的区域会使用图层默认颜色。

50.3.4 LTDC句柄结构体LTDC_HandleTypeDef

HAL库在LTDC_TypeDef, LTDC_InitTypeDef和LTDC_LayerCfgTypeDef的基础上封装了一个结构体LTDC_HandleTypeDef,定义如下:

typedef struct
{
  LTDC_TypeDef                *Instance;               
  LTDC_InitTypeDef            Init;                   
  LTDC_LayerCfgTypeDef        LayerCfg[MAX_LAYER];    
  HAL_LockTypeDef             Lock;                  
  __IO HAL_LTDC_StateTypeDef  State;                 
  __IO uint32_t               ErrorCode;           
} LTDC_HandleTypeDef;

下面将这几个参数逐一做个说明。

  • LTDC_TypeDef  *Instance

这个参数是寄存器的例化,方便操作寄存器,详见本章3.1小节。

  • LTDC_InitTypeDef  Init;  

这个参数是用户接触较多的,用于配置LTDC的时序参数配置,详见本章3.2小节。

  • LTDC_LayerCfgTypeDef   LayerCfg[MAX_LAYER]

这个参数用于LTDC的图层配置,对于STM32H7来说,支持双图层,MAX_LAYER=2。详见本章3.3小节。

  • HAL_LockTypeDef   Lock

__IO uint32_t    State;

__IO uint32_t    ErrorCode

这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置LTDC通信状态,而ErrorCode用于配置代码错误。

50.3.5 LTDC初始化流程总结

在下章的51.4小节给出了详细的设计步骤。

50.4 源文件stm32h7xx_hal_ltdc.c

这里把我们把如下几个常用到的函数做个说明:

  •   HAL_LTDC_Init
  •   HAL_LTDC_ConfigLayer
  •   HAL_LTDC_SetAlpha
  •   HAL_LTDC_Reload
  •   HAL_LTDC_SetPixelFormat
  •   HAL_LTDC_SetWindowPosition
  •   HAL_LTDC_SetWindowSize_NoReload

LTDC的API函数主要分为两类:

  •   一类是以_NoReload作为后缀

带后缀_NoReload的函数没有对重装寄存器进行配置。如果要配置的话,可以通过函数HAL_LTDC_Reload来立即更新配置或者在垂直消隐期间更新。

  •   另一类是没有此后缀

不带后缀_NoReload的函数会立即更新配置。

===========================================================

能够实现这种操作的关键是LTDC外设有影子寄存器。如果选择不立即更新,可以将用户配置先放到影子寄存器,等垂直消隐期间再更新,这样做的好处是可以整体更新这些寄存器。下面是部分函数:

HAL_StatusTypeDef HAL_LTDC_ConfigLayer(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_ConfigLayer_NoReload(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_SetWindowSize(LTDC_HandleTypeDef *hltdc, uint32_t XSize, uint32_t YSize, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_SetWindowSize_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t XSize, uint32_t YSize, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_SetWindowPosition(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_SetWindowPosition_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_SetPixelFormat(LTDC_HandleTypeDef *hltdc, uint32_t Pixelformat, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_SetPixelFormat_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Pixelformat, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_SetAlpha(LTDC_HandleTypeDef *hltdc, uint32_t Alpha, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_SetAlpha_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Alpha, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_SetAddress(LTDC_HandleTypeDef *hltdc, uint32_t Address, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_SetAddress_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t Address, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_SetPitch(LTDC_HandleTypeDef *hltdc, uint32_t LinePitchInPixels, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_SetPitch_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LinePitchInPixels, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_ConfigColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t RGBValue, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_ConfigColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t RGBValue, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_EnableColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_EnableColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_DisableColorKeying(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_DisableColorKeying_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_EnableCLUT(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_EnableCLUT_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx);

HAL_StatusTypeDef HAL_LTDC_DisableCLUT(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx);
HAL_StatusTypeDef HAL_LTDC_DisableCLUT_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t LayerIdx);

50.4.1 函数HAL_LTDC_Init

函数原型:

HAL_StatusTypeDef HAL_LTDC_Init(LTDC_HandleTypeDef *hltdc)
{
  uint32_t tmp = 0, tmp1 = 0;

  /* 检测参数是否有效 */
  if(hltdc == NULL)
  {
    return HAL_ERROR;
  }

  /* 检查函数参数 */
  assert_param(IS_LTDC_ALL_INSTANCE(hltdc->Instance));
  assert_param(IS_LTDC_HSYNC(hltdc->Init.HorizontalSync));
  assert_param(IS_LTDC_VSYNC(hltdc->Init.VerticalSync));
  assert_param(IS_LTDC_AHBP(hltdc->Init.AccumulatedHBP));
  assert_param(IS_LTDC_AVBP(hltdc->Init.AccumulatedVBP));
  assert_param(IS_LTDC_AAH(hltdc->Init.AccumulatedActiveH));
  assert_param(IS_LTDC_AAW(hltdc->Init.AccumulatedActiveW));
  assert_param(IS_LTDC_TOTALH(hltdc->Init.TotalHeigh));
  assert_param(IS_LTDC_TOTALW(hltdc->Init.TotalWidth));
  assert_param(IS_LTDC_HSPOL(hltdc->Init.HSPolarity));
  assert_param(IS_LTDC_VSPOL(hltdc->Init.VSPolarity));
  assert_param(IS_LTDC_DEPOL(hltdc->Init.DEPolarity));
  assert_param(IS_LTDC_PCPOL(hltdc->Init.PCPolarity));

  if(hltdc->State == HAL_LTDC_STATE_RESET)
  {
    hltdc->Lock = HAL_UNLOCKED;
    /* 初始化GPIO,NVIC等 */
    HAL_LTDC_MspInit(hltdc);
  }
  
  /* 设置LTDC外设状态 */
  hltdc->State = HAL_LTDC_STATE_BUSY;

  /* 配置HSE,VS,DE和PC极性 */
  hltdc->Instance->GCR &= ~(LTDC_GCR_HSPOL | LTDC_GCR_VSPOL | LTDC_GCR_DEPOL | LTDC_GCR_PCPOL);
  hltdc->Instance->GCR |=  (uint32_t)(hltdc->Init.HSPolarity | hltdc->Init.VSPolarity | \
  hltdc->Init.DEPolarity | hltdc->Init.PCPolarity);

  /* 设置水平同步宽度和垂直同步宽度 */
  hltdc->Instance->SSCR &= ~(LTDC_SSCR_VSH | LTDC_SSCR_HSW);
  tmp = (hltdc->Init.HorizontalSync << 16);
  hltdc->Instance->SSCR |= (tmp | hltdc->Init.VerticalSync);

  /* 设置HSYNC水平同步宽度 + HBP水平后沿之和
设置VSYNC垂直同步宽度 + VBP垂直后沿之和 */
  hltdc->Instance->BPCR &= ~(LTDC_BPCR_AVBP | LTDC_BPCR_AHBP);
  tmp = (hltdc->Init.AccumulatedHBP << 16);
  hltdc->Instance->BPCR |= (tmp | hltdc->Init.AccumulatedVBP);

  /* 设置HSYNC水平同步宽度 + HBP水平后沿 + 有效宽度之和
     设置VSYNC垂直同步宽度 + VBP垂直后沿 + 有效高度之和 */
  hltdc->Instance->AWCR &= ~(LTDC_AWCR_AAH | LTDC_AWCR_AAW);
  tmp = (hltdc->Init.AccumulatedActiveW << 16);
  hltdc->Instance->AWCR |= (tmp | hltdc->Init.AccumulatedActiveH);

  /* 设置总宽度 */
  hltdc->Instance->TWCR &= ~(LTDC_TWCR_TOTALH | LTDC_TWCR_TOTALW);
  tmp = (hltdc->Init.TotalWidth << 16);
  hltdc->Instance->TWCR |= (tmp | hltdc->Init.TotalHeigh);

  /* 设置背景层颜色 */
  tmp = ((uint32_t)(hltdc->Init.Backcolor.Green) << 8);
  tmp1 = ((uint32_t)(hltdc->Init.Backcolor.Red) << 16);
  hltdc->Instance->BCCR &= ~(LTDC_BCCR_BCBLUE | LTDC_BCCR_BCGREEN | LTDC_BCCR_BCRED);
  hltdc->Instance->BCCR |= (tmp1 | tmp | hltdc->Init.Backcolor.Blue);

  /* 使能传输错误中断和FIFO下溢中断 */
  __HAL_LTDC_ENABLE_IT(hltdc, LTDC_IT_TE | LTDC_IT_FU);

  /* 使能LTDC */
  __HAL_LTDC_ENABLE(hltdc);

  /* 无错误 Initialize the error code */
  hltdc->ErrorCode = HAL_LTDC_ERROR_NONE;  

  /* 设置LTDC状态 */
  hltdc->State = HAL_LTDC_STATE_READY;

  return HAL_OK;
}

函数描述:

此函数用于初始化LTDC的基本参数。

函数参数:

  •   第1个参数是LTDC_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。
  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

注意事项:

  1. 如果配置了LTDC的NVIC,那么此函数会开启LTDC的传输错误中断和FIFO下溢中断,所以LTDC的中断服务程序别忘了写。
  2. 函数HAL_LTDC_MspInit用于初始化LTDC的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
  3. 如果形参ltdc的结构体成员gState没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量LTDC_HandleTypeDef LtdcHandle。

对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_LTDC_STATE_RESET  = 0x00U。

解决办法有三

方法1:用户自己初始LTDC和涉及到的GPIO等。

方法2:定义LTDC_HandleTypeDef LtdcHandle为全局变量。

方法3:下面的方法

if(HAL_LTDC_DeInit(&LtdcHandle) != HAL_OK)
{
    Error_Handler();
}  
if(HAL_LTDC_Init(&LtdcHandle) != HAL_OK)
{
    Error_Handler();
}

使用举例:

static LTDC_HandleTypeDef   hltdc_F;
uint16_t Width, Height, HSYNC_W, HBP, HFP, VSYNC_W, VBP, VFP;

/* 配置信号极性 */    
hltdc_F.Init.HSPolarity = LTDC_HSPOLARITY_AL;    /* HSYNC 低电平有效 */
hltdc_F.Init.VSPolarity = LTDC_VSPOLARITY_AL;     /* VSYNC 低电平有效 */
hltdc_F.Init.DEPolarity = LTDC_DEPOLARITY_AL;     /* DE 低电平有效 */
hltdc_F.Init.PCPolarity = LTDC_PCPOLARITY_IPC;

/* 时序配置 */    
hltdc_F.Init.HorizontalSync = (HSYNC_W - 1);
hltdc_F.Init.VerticalSync = (VSYNC_W - 1);
hltdc_F.Init.AccumulatedHBP = (HSYNC_W + HBP - 1);
hltdc_F.Init.AccumulatedVBP = (VSYNC_W + VBP - 1);  
hltdc_F.Init.AccumulatedActiveH = (Height + VSYNC_W + VBP - 1);
hltdc_F.Init.AccumulatedActiveW = (Width + HSYNC_W + HBP - 1);
hltdc_F.Init.TotalHeigh = (Height + VSYNC_W + VBP + VFP - 1);
hltdc_F.Init.TotalWidth = (Width + HSYNC_W + HBP + HFP - 1); 

/* 配置背景层颜色 */
hltdc_F.Init.Backcolor.Blue = 0;
hltdc_F.Init.Backcolor.Green = 0;
hltdc_F.Init.Backcolor.Red = 0;

hltdc_F.Instance = LTDC;

/* 配置LTDC  */  
if (HAL_LTDC_Init(&hltdc_F) != HAL_OK)
{
    /* 初始化错误 */
    Error_Handler(__FILE__, __LINE__);
}

50.4.2 函数HAL_LTDC_ConfigLayer

函数原型:

HAL_StatusTypeDef HAL_LTDC_ConfigLayer(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx)
{   
  /* 检测参数 */
  assert_param(IS_LTDC_LAYER(LayerIdx));
  assert_param(IS_LTDC_HCONFIGST(pLayerCfg->WindowX0));
  assert_param(IS_LTDC_HCONFIGSP(pLayerCfg->WindowX1));
  assert_param(IS_LTDC_VCONFIGST(pLayerCfg->WindowY0));
  assert_param(IS_LTDC_VCONFIGSP(pLayerCfg->WindowY1));
  assert_param(IS_LTDC_PIXEL_FORMAT(pLayerCfg->PixelFormat));
  assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha));
  assert_param(IS_LTDC_ALPHA(pLayerCfg->Alpha0));
  assert_param(IS_LTDC_BLENDING_FACTOR1(pLayerCfg->BlendingFactor1));
  assert_param(IS_LTDC_BLENDING_FACTOR2(pLayerCfg->BlendingFactor2));
  assert_param(IS_LTDC_CFBLL(pLayerCfg->ImageWidth));  
  assert_param(IS_LTDC_CFBLNBR(pLayerCfg->ImageHeight));

  /* 上锁 */
  __HAL_LOCK(hltdc);
  
  /* 设置LTDC外设状态 */
  hltdc->State = HAL_LTDC_STATE_BUSY;

  /* 结构体之间直接赋值 */
  hltdc->LayerCfg[LayerIdx] = *pLayerCfg;  

  /* 配置LTDC图层 */  
  LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);

  /* 设置立即更新 */
  hltdc->Instance->SRCR = LTDC_SRCR_IMR;

  /* 设置LTDC就绪 */
  hltdc->State  = HAL_LTDC_STATE_READY;

  /* 解锁 */
  __HAL_UNLOCK(hltdc);

  return HAL_OK;
}

函数描述:

此函数主要用于配置LTDC的图层。

函数参数:

  •   第1个参数是LTDC_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。
  •   第2个参数是LTDC_LayerCfgTypeDef类型的结构体指针变量,用于图层配置,结构体变量成员的详细介绍看本章3.3小节。
  •   第3个参数用于要配置的图层,LTDC_LAYER_1表示配置图层1,LTDC_LAYER_2表示配置图层2。
  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

使用举例:

static LTDC_HandleTypeDef   hltdc_F;
uint16_t Width, Height, HSYNC_W, HBP, HFP, VSYNC_W, VBP, VFP;
LTDC_LayerCfgTypeDef      pLayerCfg;

* 配置信号极性 */    
hltdc_F.Init.HSPolarity = LTDC_HSPOLARITY_AL;    /* HSYNC 低电平有效 */
hltdc_F.Init.VSPolarity = LTDC_VSPOLARITY_AL;     /* VSYNC 低电平有效 */
hltdc_F.Init.DEPolarity = LTDC_DEPOLARITY_AL;     /* DE 低电平有效 */
hltdc_F.Init.PCPolarity = LTDC_PCPOLARITY_IPC;

/* 时序配置 */    
hltdc_F.Init.HorizontalSync = (HSYNC_W - 1);
hltdc_F.Init.VerticalSync = (VSYNC_W - 1);
hltdc_F.Init.AccumulatedHBP = (HSYNC_W + HBP - 1);
hltdc_F.Init.AccumulatedVBP = (VSYNC_W + VBP - 1);  
hltdc_F.Init.AccumulatedActiveH = (Height + VSYNC_W + VBP - 1);
hltdc_F.Init.AccumulatedActiveW = (Width + HSYNC_W + HBP - 1);
hltdc_F.Init.TotalHeigh = (Height + VSYNC_W + VBP + VFP - 1);
hltdc_F.Init.TotalWidth = (Width + HSYNC_W + HBP + HFP - 1); 

/* 配置背景层颜色 */
hltdc_F.Init.Backcolor.Blue = 0;
hltdc_F.Init.Backcolor.Green = 0;
hltdc_F.Init.Backcolor.Red = 0;

hltdc_F.Instance = LTDC;

/* 开始配置图层 ------------------------------------------------------*/
/* 窗口显示区设置 */ 
pLayerCfg.WindowX0 = 0;
pLayerCfg.WindowX1 = Width;
pLayerCfg.WindowY0 = 0;
pLayerCfg.WindowY1 = Height;

/* 配置颜色格式 */ 
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;

/* 显存地址 */
pLayerCfg.FBStartAdress = LCDH7_FRAME_BUFFER;    

/* Alpha常数 (255 表示完全不透明) */
pLayerCfg.Alpha = 255;

/* 无背景色 */
pLayerCfg.Alpha0 = 0;     /* 完全透明 */
pLayerCfg.Backcolor.Blue = 0;
pLayerCfg.Backcolor.Green = 0;
pLayerCfg.Backcolor.Red = 0;

/* 配置图层混合因数 */
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;

/* 配置行列大小 */
pLayerCfg.ImageWidth  = Width;
pLayerCfg.ImageHeight = Height;

/* 配置LTDC  */  
if (HAL_LTDC_Init(&hltdc_F) != HAL_OK)
{
    /* 初始化错误 */
    Error_Handler(__FILE__, __LINE__);
}

/* 配置图层1 */
if (HAL_LTDC_ConfigLayer(&hltdc_F, &pLayerCfg, LTDC_LAYER_1) != HAL_OK)
{
    /* 初始化错误 */
    Error_Handler(__FILE__, __LINE__);
} 

50.4.3 函数HAL_LTDC_SetAlpha

函数原型:

HAL_StatusTypeDef HAL_LTDC_SetAlpha(LTDC_HandleTypeDef *hltdc, uint32_t Alpha, uint32_t LayerIdx)
{
  LTDC_LayerCfgTypeDef *pLayerCfg;

  /* 检查参数 */
  assert_param(IS_LTDC_ALPHA(Alpha));
  assert_param(IS_LTDC_LAYER(LayerIdx));

  /* 上锁 */
  __HAL_LOCK(hltdc);

  /* 设置LTDC状态 */
  hltdc->State = HAL_LTDC_STATE_BUSY;

  /* 获取图层配置 */
  pLayerCfg = &hltdc->LayerCfg[LayerIdx];

  /* 配置图层Alpha值 */
  pLayerCfg->Alpha = Alpha;

  /* 重新配置LTDC */
  LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);

  /* 设置立即更新 */
  hltdc->Instance->SRCR = LTDC_SRCR_IMR;

  /* 设置LTDC状态就绪 */
  hltdc->State = HAL_LTDC_STATE_READY;

  /* 解锁 */
  __HAL_UNLOCK(hltdc);

  return HAL_OK;
}

函数描述:

此函数用于设置图层的常数Alpha。

函数参数:

  •   第1个参数是LTDC_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。
  •   第2个参数是Alpha值设置,0x00表示完全透明,0xFF表示完全不透明。
  •   第3个参数用于要配置的图层,LTDC_LAYER_1表示配置图层1,LTDC_LAYER_2表示配置图层2。
  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

使用举例:

此函数的使用相对比较简单,直接调用即可。

50.4.4 函数HAL_LTDC_Reload

函数原型:

HAL_StatusTypeDef  HAL_LTDC_Reload(LTDC_HandleTypeDef *hltdc, uint32_t ReloadType)
{
  /* 检测参数 */
  assert_param(IS_LTDC_RELOAD(ReloadType));

  /* 上锁 */
  __HAL_LOCK(hltdc);

  /* 设置LTDC状态 Change LTDC peripheral state */
  hltdc->State = HAL_LTDC_STATE_BUSY;  
  
  /* 使能LTDC重装中断 */  
  __HAL_LTDC_ENABLE_IT(hltdc, LTDC_IT_RR);
       
  /* 设置立即更新或者下一个垂直消隐期更新Apply Reload type */
  hltdc->Instance->SRCR = ReloadType;        

  /* 设置LTDC就绪 */
  hltdc->State = HAL_LTDC_STATE_READY;
  
  /* 解锁 */
  __HAL_UNLOCK(hltdc);
  
  return HAL_OK;
}

函数描述:

此函数主要用于配合其它以_NoReload结尾的函数,可以设置立即更新配置或者下一个垂直消隐期更新。

函数参数:

  •   第1个参数是LTDC_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。
  •   第2个参数设置为LTDC_RELOAD_IMMEDIATE表示立即更新。

设置为LTDC_RELOAD_VERTICAL_BLANKING表示下一个垂直消隐期更新。

  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

使用举例:

此函数的使用相对比较简单,直接调用即可。

50.4.5 函数HAL_LTDC_SetPixelFormat

函数原型:

HAL_StatusTypeDef HAL_LTDC_SetPixelFormat(LTDC_HandleTypeDef *hltdc, uint32_t Pixelformat, uint32_t LayerIdx)
{
  LTDC_LayerCfgTypeDef *pLayerCfg;

  /* 检测参数 */
  assert_param(IS_LTDC_PIXEL_FORMAT(Pixelformat));
  assert_param(IS_LTDC_LAYER(LayerIdx));

  /* 上锁 */
  __HAL_LOCK(hltdc);

  /* 设置LTDC状态 */
  hltdc->State = HAL_LTDC_STATE_BUSY;

  /* 获取图层配置 */
  pLayerCfg = &hltdc->LayerCfg[LayerIdx];  

  /* 重新配置图层颜色格式 */
  pLayerCfg->PixelFormat = Pixelformat;

  /* 配置LTDC */
  LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);   

  /* 设置立即更新 */
  hltdc->Instance->SRCR = LTDC_SRCR_IMR;

  /* 设置LTDC就绪 */
  hltdc->State = HAL_LTDC_STATE_READY;

  /* 解锁 */
  __HAL_UNLOCK(hltdc);

  return HAL_OK;
}

函数描述:

此函数用于设置图层的颜色格式。

函数参数:

  •   第1个参数是LTDC_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。
  •   第2个参数是STM32H7支持的颜色格式,具体有如下8种:
#define LTDC_PIXEL_FORMAT_ARGB8888                  (0x00000000U)      /*!< ARGB8888 LTDC pixel format */
#define LTDC_PIXEL_FORMAT_RGB888                    (0x00000001U)      /*!< RGB888 LTDC pixel format   */
#define LTDC_PIXEL_FORMAT_RGB565                    (0x00000002U)      /*!< RGB565 LTDC pixel format   */
#define LTDC_PIXEL_FORMAT_ARGB1555                  (0x00000003U)      /*!< ARGB1555 LTDC pixel format */
#define LTDC_PIXEL_FORMAT_ARGB4444                  (0x00000004U)      /*!< ARGB4444 LTDC pixel format */
#define LTDC_PIXEL_FORMAT_L8                        (0x00000005U)      /*!< L8 LTDC pixel format       */
#define LTDC_PIXEL_FORMAT_AL44                      (0x00000006U)      /*!< AL44 LTDC pixel format     */
#define LTDC_PIXEL_FORMAT_AL88                      (0x00000007U)      /*!< AL88 LTDC pixel format     */
  •   第3个参数用于要配置的图层,LTDC_LAYER_1表示配置图层1,LTDC_LAYER_2表示配置图层2。
  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

使用举例:

此函数的使用相对比较简单,直接调用即可。

50.4.6 函数HAL_LTDC_SetWindowPosition

函数原型:

HAL_StatusTypeDef HAL_LTDC_SetWindowPosition(LTDC_HandleTypeDef *hltdc, uint32_t X0, uint32_t Y0, uint32_t LayerIdx)
{
  LTDC_LayerCfgTypeDef *pLayerCfg;
  
  /* 检测参数 */
  assert_param(IS_LTDC_LAYER(LayerIdx));
  assert_param(IS_LTDC_CFBLL(X0));
  assert_param(IS_LTDC_CFBLNBR(Y0));

  /* 上锁 */
  __HAL_LOCK(hltdc);

  /* 设置LTDC状态 */
  hltdc->State = HAL_LTDC_STATE_BUSY;

  /* 获取图层配置 */
  pLayerCfg = &hltdc->LayerCfg[LayerIdx];

  /* 更新水平起始和结束位置 */
  pLayerCfg->WindowX0 = X0;
  pLayerCfg->WindowX1 = X0 + pLayerCfg->ImageWidth;

  /* 更新垂直起始和结束位置 */
  pLayerCfg->WindowY0 = Y0;
  pLayerCfg->WindowY1 = Y0 + pLayerCfg->ImageHeight;

  /* 设置LTDC参数 */
  LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);

  /* 设置立即更新 */
  hltdc->Instance->SRCR = LTDC_SRCR_IMR;

  /* 设置LTDC就绪 */
  hltdc->State = HAL_LTDC_STATE_READY;

  /* 解锁 */
  __HAL_UNLOCK(hltdc);

  return HAL_OK;
}

函数描述:

此函数用于设置显示区在图层中的起始位置。

函数参数:

  •   第1个参数是LTDC_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。
  •   第2个参数是设置显示区在图层中的X轴起始位置。
  •   第3个参数是设置显示区在图层中的Y轴起始位置。
  •   第4个参数用于要配置的图层,LTDC_LAYER_1表示配置图层1,LTDC_LAYER_2表示配置图层2。
  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

使用举例:

此函数的使用相对比较简单,直接调用即可,注意设置的显示区最好不要超出图层范围。

50.4.7 函数HAL_LTDC_SetWindowSize_NoReload

函数原型:

HAL_StatusTypeDef HAL_LTDC_SetWindowSize_NoReload(LTDC_HandleTypeDef *hltdc, uint32_t XSize, uint32_t YSize, uint32_t LayerIdx) 
{
  LTDC_LayerCfgTypeDef *pLayerCfg;

  /* 检测参数 */
  assert_param(IS_LTDC_LAYER(LayerIdx));
  assert_param(IS_LTDC_CFBLL(XSize));
  assert_param(IS_LTDC_CFBLNBR(YSize));

  /* 上锁 */
  __HAL_LOCK(hltdc);

  /* 设置LTDC状态 */
  hltdc->State = HAL_LTDC_STATE_BUSY; 

  /* 获取图层配置 */
  pLayerCfg = &hltdc->LayerCfg[LayerIdx];

  /* 更新水平结束位置 */
  pLayerCfg->WindowX1 = XSize + pLayerCfg->WindowX0;

  /* 更新垂直解锁位置 */  
  pLayerCfg->WindowY1 = YSize + pLayerCfg->WindowY0;

  /* 重新配置颜色帧缓冲的行长 */
  pLayerCfg->ImageWidth = XSize;

  /* 重新配置颜色帧缓冲的行数 */
  pLayerCfg->ImageHeight = YSize;

  /* 设置LTDC参数 */
  LTDC_SetConfig(hltdc, pLayerCfg, LayerIdx);

  /* 此函数没有配置立即更新配置,绘制下一个垂直消隐期更新  */

  /* 设置LTDC就绪 */
  hltdc->State = HAL_LTDC_STATE_READY;

  /* 解锁 */
  __HAL_UNLOCK(hltdc);

  return HAL_OK;
}

函数描述:

此函数用于设置图层显示区的大小,但不会立即更新,会在下一个垂直消隐期更新。

函数参数:

  •   第1个参数是LTDC_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。
  •   第2个参数设置图层显示区的行长,单位像素。
  •   第3个参数是设置图层显示区的行数,单位像素。
  •   第4个参数用于要配置的图层,LTDC_LAYER_1表示配置图层1,LTDC_LAYER_2表示配置图层2。
  •   返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。

使用举例:

此函数的使用相对比较简单,直接调用即可,注意设置的显示区最好不要超出图层范围。

50.5 总结

本章节涉及到的知识点比较多,而且比较重要,特别是第2小节中的几个知识点尤其重要,望初学者熟练掌握。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【STM32H7教程】第10章 STM32H7的FLASH,RAM和栈使用情况(map和htm文件)

    完整教程下载地址:http://forum.armfly.com/forum.php?mod=viewthread&tid=86980

    armfly
  • 【STM32F407开发板用户手册】第18章 STM32F407的GPIO应用之跑马灯

    最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255

    armfly
  • 【STM32F429开发板用户手册】第27章 STM32F429的定时器应用之TIM1-TIM14的PWM实现

    最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255

    armfly
  • vSphere初体验之添加主机

    物理机:DELL  IPTIPLEX 990 PC机 I52400处理器支持VT功能  8G内存 千兆网卡

    三杯水Plus
  • 从一个故障案例看强大到令人发紫的Oracle数据库--我和数据中心的故事

    作为一名混迹数据库江湖十几年的老DBA,当你对关系型数据库的了解越来越深入时,你会发现,Oracle数据库真的是强大到令人发紫! Oracle数据库的强大,不仅...

    数据和云
  • Python基础项目实战:爬取东方财富热门股票数据

    今天为大家分享一个用Python爬取股票的今开 成交量 ,最高, 涨停, 内盘 ,成交额 ,委比 ,流通市值市盈率MRQ ,每股收益总股本 ,昨收 ,换手率, ...

    一墨编程学习
  • 手把手教您构建自己的 DevOps 流水线

    持续交付是一组能够帮助软件开发团队极大的提高其软件交付的速度和质量的模式和最佳实践组成。

    DevOps时代
  • 以太坊核心开发者Karl Floersch:像黑客帝国那样学习加密经济学!

    区块链大本营
  • Hexo博客配置RSS插件

    試毅-思伟
  • 不要小看日本的AI公司

    有家日本AI创业公司,把这个当成奋斗目标挂在嘴边。而且还放言说,如果他们全速前进,肯定能干成世界第一。

    量子位

扫码关注云+社区

领取腾讯云代金券