最新教程下載: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 初學者重要提示
- 本章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表示時間溢出。
注意事項:
- 如果配置了LTDC的NVIC,那么此函數會開啟LTDC的傳輸錯誤中斷和FIFO下溢中斷,所以LTDC的中斷服務程序別忘了寫。
- 函數HAL_LTDC_MspInit用於初始化LTDC的底層時鍾、引腳等功能。需要用戶自己在此函數里面實現具體的功能。由於這個函數是弱定義的,允許用戶在工程其它源文件里面重新實現此函數。當然,不限制一定要在此函數里面實現,也可以像早期的標准庫那樣,用戶自己初始化即可,更靈活些。
- 如果形參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小節中的幾個知識點尤其重要,望初學者熟練掌握。