【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小節中的幾個知識點尤其重要,望初學者熟練掌握。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM