• 【STM32F429开发板用户手册】第40章 STM32F429的LCD控制器LTDC基础知识和HAL库API


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

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

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

    40.1 初学者重要提示

    40.2 LTDC基础知识

    40.3 LTDC的HAL库用法

    40.4 源文件stm32f4xx_hal_ltdc.c

    40.5 总结

    40.1 初学者重要提示

    1.   本章40.2小节中的几个知识点比较重要,比如DE同步模式和HV同步模式的区别,Alpha混合,水平消隐和垂直消隐等知识点尤其重要,需要大家理解透彻。

    40.2 LTDC基础知识

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

    1、  STM32F429的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里面存储。

    40.2.1 LTDC硬件框图

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

     

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

    •   AHB Clock

    AHB时钟域

    •   APB2 Clock

    APB2时钟域

    •   Interrupts

    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位蓝色数据。

    40.2.2 LTDC时钟源选择

    LTDC仅有一个时钟源可供选择,如下图所示:

     

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

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

    具体支持哪种模式是由裸屏自带的Driver IC决定,比如V6板子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,又重新从第一行扫描开始。

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

    40.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的像素时钟输出为单位。

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

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

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

    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;

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

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

     

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

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

    40.2.7 区分FPS帧率和刷新率

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

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

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

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

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

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

    •   出现这个问题的原因

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

     

    •   解决这个问题的办法

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

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

    40.3 LTDC的HAL库用法

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

    40.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_m4.h 文件定义了这个宏:

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

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

    #define PERIPH_BASE         ((uint32_t)0x40000000)              
    #define APB2PERIPH_BASE     (PERIPH_BASE + 0x00010000UL)
    
    #define LTDC_BASE           (APB2PERIPH_BASE + 0x6800UL)
    #define LTDC                ((LTDC_TypeDef *)LTDC_BASE) <----- 展开这个宏,(LTDC_TypeDef *) 0x40016800

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

    40.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。

    40.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颜色格式,那么未覆盖的区域会使用图层默认颜色。

    40.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的图层配置,对于STM32F429来说,支持双图层,MAX_LAYER=2。详见本章3.3小节。

    •   HAL_LockTypeDef   Lock

    __IO uint32_t    State;

    __IO uint32_t    ErrorCode

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

    40.3.5 LTDC初始化流程总结

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

    40.4 源文件stm32f4xx_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);

    40.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 (USE_HAL_LTDC_REGISTER_CALLBACKS == 1)
      if (hltdc->State == HAL_LTDC_STATE_RESET)
      {
         /*省略未写 */
      }
    #else
      if(hltdc->State == HAL_LTDC_STATE_RESET)
      {
        hltdc->Lock = HAL_UNLOCKED;
        /* 初始化GPIO,NVIC等 */
        HAL_LTDC_MspInit(hltdc);
      }
    #endif
      
      /* 设置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__);
    }

    40.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__);
    }  

    40.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表示时间溢出。

    使用举例:

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

    40.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表示时间溢出。

    使用举例:

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

    40.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表示时间溢出。

    使用举例:

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

    40.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表示时间溢出。

    使用举例:

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

    40.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表示时间溢出。

    使用举例:

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

    40.5 总结

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

  • 相关阅读:
    tomcat 服务器发布网站
    AJAX服务器返回数据 连接数据库查询数据
    MyEclipse jsp 中文乱码
    sql 数据库修复
    jquery checkbox
    Nexus介绍
    navicat for mysql快捷键
    Mysql limit offset用法举例
    tortoiseSVN如何发现和解决冲突?
    maven指定项目的构建、打包和tomcat插件的pom.xml配置
  • 原文地址:https://www.cnblogs.com/armfly/p/13441155.html
Copyright © 2020-2023  润新知