最新教程下載:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255
第45章 STM32F429的圖形加速器DMA2D的基礎知識和HAL庫API
本章節為大家講解DMA2D,實際項目中顯示屏的加速全靠它了,而且性能也比較給力。
45.1 初學者重要提示
45.2 DMA2D基礎知識
45.3 DMA2D的HAL庫用法
45.4 源文件stm32f4xx_hal_dma2d.c
45.5 總結
45.1 初學者重要提示
- DMA2D是專門用於LCD加速的,特別是刷單色屏,刷圖片,刷Alpha(透明)混合效果全靠它,而且可以大大降低CPU利用率。
- 特別注意,大家只需對HAL庫提供的DMA2D操作API有個了解即可,實際工程中,並不使用這些API,我們需要使用更加高效的寄存器直接操作,在下一章節會為大家說明。
45.2 DMA2D基礎知識
DMA2D主要實現了兩個功能,一個是DMA數據傳輸功能,另一個是2D圖形加速功能。
- DMA數據傳輸
主要是兩種方式,一個是寄存器到存儲器,另一個是存儲器到存儲器。通過DMA可以大大降低CPU的利用率。
- 2D圖形加速功能
支持硬件的顏色格式轉換和Alpha混合效果。
45.2.1 DMA2D硬件框圖
認識一個外設,最好的方式就是看它的框圖,方便我們快速地了解DMA2D的基本功能,然后再看手冊了解細節。框圖如下所示:
將這個硬件框圖簡化一下,就是下面這樣:
下面按照簡化的硬件框圖,對每個部分做個說明。
45.2.2 DMA2D工作模式
DMA2D支持的工作模式如下:
- 模式1:寄存器到存儲器模式
這個模式主要用於清屏,也即是將顯示屏清為單色效果。
- 模式2:存儲器到存儲器模式
這個模式用於從一個存儲器復制一塊數據到另一個存儲器,比如將攝像頭OV7670的輸出圖像復制到LCD顯存就可以采用這種方式。
- 模式3:存儲器到存儲器模式,帶顏色格式轉換
這個模式比模式2多了一個顏色格式轉換,比如我們要顯示一幅RGB888顏色格式的位圖到RGB565顏色格式的顯示屏,就需要用到這個模式,只需輸入端配置為RGB888,輸出端配置RGB565即可。位圖顏色格式轉換后會顯示到顯示屏上。
- 模式4:存儲器到存儲器模式,帶顏色格式轉換和混合
這個模式比模式3多了一個混合操作,通過混合,可以將兩種效果進行混合顯示。
- 模式5:存儲器到存儲器模式,帶顏色格式轉換和混合,前景色是固定的
同模式4,只是前景色的顏色值是固定的。
45.2.3 前景層和背景層的輸入以及顏色格式轉換
前景層和背景層是指的用戶繪制圖形時的前景色和背景色,比如我們顯示漢字,字體會有一個顏色,也就是前景色,還有一個背景色。又比如我們繪制兩幅圖片,想將兩幅圖片混合,那就可以將一幅圖片作為前景層,另一個幅圖片作為背景層。
DMA2D支持的輸入顏色格式如下,前景層和背景層一樣:
前8種顏色格式在第40章的第2小節開頭有介紹,這里把后四種做個說明:
- L4 (4-bit luminance or CLUT)
4位顏色格式,實際上僅僅是4位索引值,范圍0–15,而每個索引值的具體顏色值在查色表CLUT里面存儲。
- A4和A8
A4和A8用於特定的Alpha模式,既不存儲顏色信息,也沒有索引值。
這里特別注意一點,輸入顏色格式的Alpha值是可以設置的,而且顏色格式里面的R通道和B通道可以交換位置。
45.2.4 前景層和背景層混合
DMA2D混合器用於混合前景色和背景色,這個功能不需要任何配置,僅需要通過DMA2D_CR寄存器使能即可。混合公式如下:
45.2.5 DMA2D輸出顏色格式
DMA2D支持的輸出顏色格式如下:
45.3 DMA2D的HAL庫用法
DMA2D的HAL庫用法其實就是幾個結構體變量成員的配置和使用,然后配置時鍾,並根據需要配置NVIC、中斷。下面我們逐一展開為大家做個說明。
45.3.1 DMA2D寄存器結構體DMA2D_TypeDef
DMA2D相關的寄存器是通過HAL庫中的結構體DMA2D_TypeDef定義的,在stm32h743xx.h中可以找到它們的具體定義:
typedef struct { __IO uint32_t CR; /*!< DMA2D Control Register, Address offset: 0x00 */ __IO uint32_t ISR; /*!< DMA2D Interrupt Status Register, Address offset: 0x04 */ __IO uint32_t IFCR; /*!< DMA2D Interrupt Flag Clear Register, Address offset: 0x08 */ __IO uint32_t FGMAR; /*!< DMA2D Foreground Memory Address Register, Address offset: 0x0C */ __IO uint32_t FGOR; /*!< DMA2D Foreground Offset Register, Address offset: 0x10 */ __IO uint32_t BGMAR; /*!< DMA2D Background Memory Address Register, Address offset: 0x14 */ __IO uint32_t BGOR; /*!< DMA2D Background Offset Register, Address offset: 0x18 */ __IO uint32_t FGPFCCR; /*!< DMA2D Foreground PFC Control Register, Address offset: 0x1C */ __IO uint32_t FGCOLR; /*!< DMA2D Foreground Color Register, Address offset: 0x20 */ __IO uint32_t BGPFCCR; /*!< DMA2D Background PFC Control Register, Address offset: 0x24 */ __IO uint32_t BGCOLR; /*!< DMA2D Background Color Register, Address offset: 0x28 */ __IO uint32_t FGCMAR; /*!< DMA2D Foreground CLUT Memory Address Register, Address offset: 0x2C */ __IO uint32_t BGCMAR; /*!< DMA2D Background CLUT Memory Address Register, Address offset: 0x30 */ __IO uint32_t OPFCCR; /*!< DMA2D Output PFC Control Register, Address offset: 0x34 */ __IO uint32_t OCOLR; /*!< DMA2D Output Color Register, Address offset: 0x38 */ __IO uint32_t OMAR; /*!< DMA2D Output Memory Address Register, Address offset: 0x3C */ __IO uint32_t OOR; /*!< DMA2D Output Offset Register, Address offset: 0x40 */ __IO uint32_t NLR; /*!< DMA2D Number of Line Register, Address offset: 0x44 */ __IO uint32_t LWR; /*!< DMA2D Line Watermark Register, Address offset: 0x48 */ __IO uint32_t AMTCR; /*!< DMA2D AHB Master Timer Configuration Register, Address offset: 0x4C */ uint32_t RESERVED[236]; /*!< Reserved, 0x50-0x3FF */ __IO uint32_t FGCLUT[256]; /*!< DMA2D Foreground CLUT, Address offset:400-7FF */ __IO uint32_t BGCLUT[256]; /*!< DMA2D Background CLUT, Address offset:800-BFF */ } DMA2D_TypeDef;
__IO表示volatile, 這是標准C語言中的一個修飾字,表示這個變量是非易失性的,編譯器不要將其優化掉。core_m4.h 文件定義了這個宏:
#define __O volatile /*!< Defines 'write only' permissions */ #define __IO volatile /*!< Defines 'read / write' permissions */
下面我們再看DMA2D的定義,在stm32f429xx.h文件。
#define PERIPH_BASE 0x40000000UL #define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000UL) #define DMA2D_BASE (AHB1PERIPH_BASE + 0xB000UL) #define DMA2D ((DMA2D_TypeDef *)DMA2D_BASE) <----- 展開這個宏,(DMA2D_TypeDef *) 0x4002B000
我們訪問DMA2D的ISR寄存器可以采用這種形式:DMA2D->ISR = 0。
45.3.2 DMA2D參數初始化結構體DMA2D_InitTypeDef
此結構體用於配置DMA2D的基本參數,具體定義如下:
typedef struct { uint32_t Mode; uint32_t ColorMode; uint32_t OutputOffset; uint32_t AlphaInverted; uint32_t RedBlueSwap; } DMA2D_InitTypeDef;
下面將這幾個參數逐一為大家做個說明:
- uint32_t Mode
此參數用於設置DMA2D的傳輸模式,具體支持的參數如下:
#define DMA2D_M2M ((uint32_t)0x00000000U) /*存儲器到存儲傳輸模式 */ #define DMA2D_M2M_PFC DMA2D_CR_MODE_0 /*存儲器到存儲器傳輸模式,並執行FPC像素格式轉 */ #define DMA2D_M2M_BLEND DMA2D_CR_MODE_1 /* 存儲器到存儲器模式,並執行像素格式轉換和混合 */ #define DMA2D_R2M DMA2D_CR_MODE /* 寄存器到存儲器傳輸模式 */
- uint32_t ColorMode
此參數用於設置DMA2D的輸出顏色格式,具體支持的參數如下:
#define DMA2D_OUTPUT_ARGB8888 ((uint32_t)0x00000000U) /* ARGB8888 */ #define DMA2D_OUTPUT_RGB888 DMA2D_OPFCCR_CM_0 /* RGB888 */ #define DMA2D_OUTPUT_RGB565 DMA2D_OPFCCR_CM_1 /* RGB565 */ #define DMA2D_OUTPUT_ARGB1555 (DMA2D_OPFCCR_CM_0|DMA2D_OPFCCR_CM_1) /* ARGB1555 */ #define DMA2D_OUTPUT_ARGB4444 DMA2D_OPFCCR_CM_2 /* ARGB4444 */
- uint32_t OutputOffset
此參數用於設置輸出位置的偏移值,參數范圍0x0000到0x3FFF。
45.3.3 DMA2D的圖層結構體DMA2D_LayerCfgTypeDef
此結構體用於配置前景色和背景色。
typedef struct { uint32_t InputOffset; uint32_t InputColorMode; uint32_t AlphaMode; uint32_t InputAlpha; } DMA2D_LayerCfgTypeDef;
下面將這幾個參數逐一為大家做個說明。
- uint32_t InputOffset
設置前景色或者背景色的輸入偏移,范圍0x000到0x3FFF。
- uint32_t InputColorMode
設置前景色或者背景色的輸入顏色格式,具體支持的參數如下:
#define DMA2D_INPUT_ARGB8888 ((uint32_t)0x00000000U) /* ARGB8888 */ #define DMA2D_INPUT_RGB888 ((uint32_t)0x00000001U) /* RGB888 */ #define DMA2D_INPUT_RGB565 ((uint32_t)0x00000002U) /* RGB565 */ #define DMA2D_INPUT_ARGB1555 ((uint32_t)0x00000003U) /* ARGB1555 */ #define DMA2D_INPUT_ARGB4444 ((uint32_t)0x00000004U) /* ARGB4444 */ #define DMA2D_INPUT_L8 ((uint32_t)0x00000005U) /* L8 */ #define DMA2D_INPUT_AL44 ((uint32_t)0x00000006U) /* AL44 */ #define DMA2D_INPUT_AL88 ((uint32_t)0x00000007U) /* AL88 */ #define DMA2D_INPUT_L4 ((uint32_t)0x00000008U) /* L4 */ #define DMA2D_INPUT_A8 ((uint32_t)0x00000009U) /* A8 */ #define DMA2D_INPUT_A4 ((uint32_t)0x0000000AU) /* A4 */ #define DMA2D_INPUT_YCBCR ((uint32_t)0x0000000BU) /* YCbCr */
- uint32_t AlphaMode
設置前景色或者背景色的Alpha模式,具體支持的參數如下:
#define DMA2D_NO_MODIF_ALPHA ((uint32_t)0x00000000U) /* 不修改Alpha通道值 */ #define DMA2D_REPLACE_ALPHA ((uint32_t)0x00000001U) /* 用新設置的Alpha值替換原始Alpha值 */ #define DMA2D_COMBINE_ALPHA ((uint32_t)0x00000002U) /* 用新設置的Alpha值與原始Alpha值的乘積替換原始Alaha值*/
- uint32_t InputAlpha
設置前景色或者背景色的Alpha值,范圍0x00到0xFF,如果顏色格式是A4或者A8,那么此參數的范圍是0x00000000到0xFFFFFFFF,標准的ARGB8888格式。
45.3.4 DMA2D句柄結構體DMA2D_HandleTypeDef
HAL庫在DMA2D_TypeDef, DMA2D_InitTypeDef和DMA2D_LayerCfgTypeDef的基礎上封裝了一個結構體DMA2D_HandleTypeDef,定義如下:
注意事項:
條件編譯USE_HAL_DMA2D_REGISTER_CALLBACKS用來設置使用自定義回調還是使用默認回調,此定義一般放在stm32f4xx_hal_conf.h文件里面設置:
#define USE_HAL_DMA2D_REGISTER_CALLBACKS 1
通過函數HAL_DMA2D_RegisterCallback注冊回調,
取消注冊使用函數HAL_DMA2D_UnRegisterCallback。
這里重點介紹下面幾個參數,其它參數主要是HAL庫內部使用和自定義回調函數。
下面將這幾個參數逐一做個說明。
- DMA2D_TypeDef *Instance
這個參數是寄存器的例化,方便操作寄存器,詳見本章3.1小節。
- DMA2D_InitTypeDef Init;
這個參數是用戶接觸較多的,用於配置DMA2D的基本參數,詳見本章3.2小節。
- void (* XferCpltCallback)(struct __DMA2D_HandleTypeDef * hdma2d);
- void (* XferErrorCallback)(struct __DMA2D_HandleTypeDef * hdma2d);
DMA2D中斷服務程序里面執行的回調函數,一個是傳輸完成回調,另一個是傳輸錯誤回調。
- DMA2D_LayerCfgTypeDef LayerCfg[MAX_DMA2D_LAYER]
這個參數用於前景色和背景色的設置,MAX_DMA2D_LAYER=2,詳見本章3.3小節。
- HAL_LockTypeDef Lock
- __IO uint32_t State;
- __IO uint32_t ErrorCode
這三個變量主要供函數內部使用。Lock用於設置鎖狀態,State用於設置DMA2D通信狀態,而ErrorCode用於配置代碼錯誤。
45.3.5 DMA2D初始化流程總結
對於DMA2D來說,其實不需要初始化流程,每個功能都可以直接封裝出一個函數來,下個章節會為大家專門講解,也是實際項目比較推薦的方式。
45.4 源文件stm32f4xx_hal_dma2d.c
這里把我們把如下幾個常用到的函數做個說明:
- HAL_DMA2D_Init
- HAL_DMA2D_ConfigLayer
- HAL_DMA2D_Start_IT
- HAL_DMA2D_BlendingStart_IT
45.4.1 函數HAL_DMA2D_Init
函數原型:
HAL_StatusTypeDef HAL_DMA2D_Init(DMA2D_HandleTypeDef *hdma2d) { /* 檢測參數是否有效 */ if(hdma2d == NULL) { return HAL_ERROR; } /* 檢測函數形參 */ assert_param(IS_DMA2D_ALL_INSTANCE(hdma2d->Instance)); assert_param(IS_DMA2D_MODE(hdma2d->Init.Mode)); assert_param(IS_DMA2D_CMODE(hdma2d->Init.ColorMode)); assert_param(IS_DMA2D_OFFSET(hdma2d->Init.OutputOffset)); #if (USE_HAL_DMA2D_REGISTER_CALLBACKS == 1) if (hdma2d->State == HAL_DMA2D_STATE_RESET) { /* 復位回調 */ hdma2d->LineEventCallback = HAL_DMA2D_LineEventCallback; hdma2d->CLUTLoadingCpltCallback = HAL_DMA2D_CLUTLoadingCpltCallback; if(hdma2d->MspInitCallback == NULL) { hdma2d->MspInitCallback = HAL_DMA2D_MspInit; } /* 初始化底層硬件 */ hdma2d->MspInitCallback(hdma2d); } #else if(hdma2d->State == HAL_DMA2D_STATE_RESET) { hdma2d->Lock = HAL_UNLOCKED; /* 初始化底層 */ HAL_DMA2D_MspInit(hdma2d); } #endif /* (USE_HAL_DMA2D_REGISTER_CALLBACKS) */ /* 設置DAM2D外設狀態 */ hdma2d->State = HAL_DMA2D_STATE_BUSY; /* 設置DAM2D工作模式 -------------------------------------------*/ MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_MODE, hdma2d->Init.Mode); /* 設置輸出顏色格式 ---------------------------------------*/ MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_CM, hdma2d->Init.ColorMode); /* 設置輸出偏移 ------------------------------------------*/ MODIFY_REG(hdma2d->Instance->OOR, DMA2D_OOR_LO, hdma2d->Init.OutputOffset); /* 無錯誤 */ hdma2d->ErrorCode = HAL_DMA2D_ERROR_NONE; /* DAM2D就緒 */ hdma2d->State = HAL_DMA2D_STATE_READY; return HAL_OK; }
函數描述:
此函數用於初始化DMA2D的工作模式和輸出顏色格式。
函數參數:
- 第1個參數是DMA2D_HandleTypeDef類型結構體指針變量,用於配置要初始化的參數,結構體變量成員的詳細介紹看本章3.4小節。
- 返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。
注意事項:
- 函數HAL_DMA2D_MspInit用於初始化DMA2D的底層時鍾、NVIC等功能。需要用戶自己在此函數里面實現具體的功能。由於這個函數是弱定義的,允許用戶在工程其它源文件里面重新實現此函數。當然,不限制一定要在此函數里面實現,也可以像早期的標准庫那樣,用戶自己初始化即可,更靈活些。
- 如果形參hdma2d的結構體成員State沒有做初始狀態,這個地方就是個坑。特別是用戶搞了一個局部變量DMA2D_HandleTypeDef Dma2dHandle。
對於局部變量來說,這個參數就是一個隨機值,如果是全局變量還好,一般MDK和IAR都會將全部變量初始化為0,而恰好這個 HAL_DMA2D_STATE_RESET = 0x00U。
解決辦法有三
方法1:用戶自己初始DMA2D底層。
方法2:定義DMA2D_HandleTypeDef LtdcHandle為全局變量。
方法3:下面的方法
if(HAL_DMA2D_DeInit(&Dma2dHandle) != HAL_OK) { Error_Handler(); } if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK) { Error_Handler(); }
使用舉例:
DMA2D_HandleTypeDef Dma2dHandle; /*##-1- 配置DMA工作模式,輸出顏色格式和輸出偏移 #############*/ Dma2dHandle.Instance = DMA2D; Dma2dHandle.Init.Mode = DMA2D_M2M; /* 存儲器到存儲器模式 */ Dma2dHandle.Init.ColorMode = DMA2D_OUTPUT_ARGB4444; /* 輸出顏色格式 */ Dma2dHandle.Init.OutputOffset = 0x0; /* 無輸出偏移 */ /*##-2- DMA2D 回調函數配置 ######################################*/ Dma2dHandle.XferCpltCallback = TransferComplete; Dma2dHandle.XferErrorCallback = TransferError; /*##-3- 前景層配置 ###########################################*/ Dma2dHandle.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA; /* 保持輸入顏色格式中的Alpha值 */ Dma2dHandle.LayerCfg[1].InputAlpha = 0xFF; /* 完全不透明 */ Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB4444; /* 輸入顏色格式 */ Dma2dHandle.LayerCfg[1].InputOffset = 0x0; /* 輸入無偏移 */ /*##-4- DMA2D 初始化 ###############################################*/ if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK) { Error_Handler(); }
45.4.2 函數HAL_DMA2D_ConfigLayer
函數原型:
HAL_StatusTypeDef HAL_DMA2D_ConfigLayer(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx) { DMA2D_LayerCfgTypeDef *pLayerCfg = &hdma2d->LayerCfg[LayerIdx]; uint32_t regMask = 0, regValue = 0; /* 檢查參數 */ assert_param(IS_DMA2D_LAYER(LayerIdx)); assert_param(IS_DMA2D_OFFSET(pLayerCfg->InputOffset)); if(hdma2d->Init.Mode != DMA2D_R2M) { assert_param(IS_DMA2D_INPUT_COLOR_MODE(pLayerCfg->InputColorMode)); if(hdma2d->Init.Mode != DMA2D_M2M) { assert_param(IS_DMA2D_ALPHA_MODE(pLayerCfg->AlphaMode)); } } /* 上鎖 */ __HAL_LOCK(hdma2d); /* 設置DMA2D外設狀態 */ hdma2d->State = HAL_DMA2D_STATE_BUSY; /* 准備好背景層或者前景層FPC寄存器配置參數*/ regValue = pLayerCfg->InputColorMode | (pLayerCfg->AlphaMode << DMA2D_POSITION_BGPFCCR_AM) | \ (pLayerCfg->AlphaInverted << DMA2D_POSITION_BGPFCCR_AI) | \ (pLayerCfg->RedBlueSwap << DMA2D_POSITION_BGPFCCR_RBS); regMask = DMA2D_BGPFCCR_CM | DMA2D_BGPFCCR_AM | DMA2D_BGPFCCR_ALPHA | DMA2D_BGPFCCR_AI | DMA2D_BGPFCCR_RBS; if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8)) { regValue |= (pLayerCfg->InputAlpha & DMA2D_BGPFCCR_ALPHA); } else { regValue |= (pLayerCfg->InputAlpha << DMA2D_POSITION_BGPFCCR_ALPHA); } /* 配置背景層 */ if(LayerIdx == 0) { /* DMA2D BGPFCCR 寄存器 */ MODIFY_REG(hdma2d->Instance->BGPFCCR, regMask, regValue); /* DMA2D BGOR 寄存器 */ WRITE_REG(hdma2d->Instance->BGOR, pLayerCfg->InputOffset); /* DMA2D BGCOLR 寄存器 */ if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8)) { WRITE_REG(hdma2d->Instance->BGCOLR, pLayerCfg->InputAlpha & (DMA2D_BGCOLR_BLUE|DMA2D_BGCOLR_GREEN|DMA2D_BGCOLR_RED)); } } /* 配置前景層 */ else { if(pLayerCfg->InputColorMode == DMA2D_INPUT_YCBCR) { regValue |= (pLayerCfg->ChromaSubSampling << DMA2D_POSITION_FGPFCCR_CSS); regMask |= DMA2D_FGPFCCR_CSS; } /* DMA2D FGPFCCR 寄存器 */ MODIFY_REG(hdma2d->Instance->FGPFCCR, regMask, regValue); /* DMA2D FGOR 寄存器 */ WRITE_REG(hdma2d->Instance->FGOR, pLayerCfg->InputOffset); /* DMA2D FGCOLR 寄存器 */ if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8)) { WRITE_REG(hdma2d->Instance->FGCOLR, pLayerCfg->InputAlpha & (DMA2D_FGCOLR_BLUE|DMA2D_FGCOLR_GREEN|DMA2D_FGCOLR_RED)); } } /* DMA2D就緒 */ hdma2d->State = HAL_DMA2D_STATE_READY; /* 解鎖 */ __HAL_UNLOCK(hdma2d); return HAL_OK; }
函數描述:
此函數主要用於配置DMA2D要轉換的前景層和背景層,即輸入顏色配置。而前面的函數HAL_DMA2D_Init配置的輸出顏色。
函數參數:
- 第1個參數是DMA2D_HandleTypeDef類型結構體指針變量,用於配置DMA2D的基本參數,結構體變量成員的詳細介紹看本章3.4小節。
- 第2個參數用於配置前景層和背景層,0表示背景層,1表示前景層。
- 返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。
使用舉例:
DMA2D_HandleTypeDef Dma2dHandle; /*##-1- 配置DMA工作模式,輸出顏色格式和輸出偏移 #############*/ Dma2dHandle.Instance = DMA2D; Dma2dHandle.Init.Mode = DMA2D_M2M; /* 存儲器到存儲器模式 */ Dma2dHandle.Init.ColorMode = DMA2D_OUTPUT_ARGB4444; /* 輸出顏色格式 */ Dma2dHandle.Init.OutputOffset = 0x0; /* 無輸出偏移 */ /*##-2- DMA2D 回調函數配置 ######################################*/ Dma2dHandle.XferCpltCallback = TransferComplete; Dma2dHandle.XferErrorCallback = TransferError; /*##-3- 前景層配置 ###########################################*/ Dma2dHandle.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA; /* 保持輸入顏色格式中的Alpha值 */ Dma2dHandle.LayerCfg[1].InputAlpha = 0xFF; /* 完全不透明 */ Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB4444; /* 輸入顏色格式 */ Dma2dHandle.LayerCfg[1].InputOffset = 0x0; /* 輸入無偏移 */ /*##-4- DMA2D 初始化 ###############################################*/ if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK) { Error_Handler(); } /* 配置前景層 */ if(HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1) != HAL_OK) { Error_Handler(); }
45.4.3 函數HAL_DMA2D_Start_IT
函數原型:
HAL_StatusTypeDef HAL_DMA2D_Start_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width, uint32_t Height) { /* 檢測函數形參 */ assert_param(IS_DMA2D_LINE(Height)); assert_param(IS_DMA2D_PIXEL(Width)); /* 上鎖 */ __HAL_LOCK(hdma2d); /* 設置DMA2D外設狀態 */ hdma2d->State = HAL_DMA2D_STATE_BUSY; /* 設置源地址,目的地址和數據大小 */ DMA2D_SetConfig(hdma2d, pdata, DstAddress, Width, Height); /* 使能DMA2D的傳輸完成中斷,傳輸錯誤中斷和配置錯誤中斷 */ __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE); /* 使能DMA2D */ __HAL_DMA2D_ENABLE(hdma2d); return HAL_OK; }
函數描述:
此函數用於啟動DMA2D數據傳輸。由於采用的中斷方式,此函數使能了多個DMA2D中斷,不要忘記DMA2D中斷服務程序的處理。
函數參數:
- 第1個參數是DMA2D_HandleTypeDef類型結構體指針變量,用於配置DMA2D的基本參數,結構體變量成員的詳細介紹看本章3.4小節。
- 第2個參數是源數據地址。
- 第3個參數是目的數據地址。
- 第4個參數是源數據的長度,即每行的像素個數。
- 第5個參數是源數據的高度,即行數。
- 返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。
使用舉例:
DMA2D_HandleTypeDef Dma2dHandle; if(HAL_DMA2D_Start_IT(&Dma2dHandle, /* DMA2D句柄 */ (uint32_t)&BufferInput, /* 源地址 */ (uint32_t)&BufferResult, /* 目的地址 */ SIZE_X, /* 源數據長度,單位像素個數*/ SIZE_Y) /* 源數據行數 */ != HAL_OK) { Error_Handler(); }
45.4.4 函數HAL_DMA2D_BlendingStart_IT
函數原型:
HAL_StatusTypeDef HAL_DMA2D_BlendingStart_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t SrcAddress1, uint32_t SrcAddress2, uint32_t DstAddress, uint32_t Width, uint32_t Height) { /* 檢測參數 */ assert_param(IS_DMA2D_LINE(Height)); assert_param(IS_DMA2D_PIXEL(Width)); /* 上鎖 */ __HAL_LOCK(hdma2d); /* 設置DMA2D外設狀態 */ hdma2d->State = HAL_DMA2D_STATE_BUSY; /* 配置DMA2D源地址2 */ WRITE_REG(hdma2d->Instance->BGMAR, SrcAddress2); /* 配置源地址1,目的地址和數據大小 */ DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height); /* 使能DMA2D傳輸完成中斷,傳輸錯誤中斷和配置錯誤中斷 */ __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE); /* 使能DMA2D */ __HAL_DMA2D_ENABLE(hdma2d); return HAL_OK; }
函數描述:
此函數用於啟動DMA2D傳輸,除了數據傳輸以外,還支持顏色格式轉換和顏色混合。由於采用的中斷方式,此函數使能了多個DMA2D中斷,不要忘記DMA2D中斷服務程序的處理。
函數參數:
- 第1個參數是DMA2D_HandleTypeDef類型結構體指針變量,用於配置DMA2D的基本參數,結構體變量成員的詳細介紹看本章3.4小節。
- 第2個參數是源數據地址1。
- 第3個參數是源數據地址2。
- 第4個參數是目的數據地址。
- 第5個參數是源數據的長度,即每行的像素個數。
- 第6個參數是源數據的高度,即行數。
- 返回值,返回HAL_ERROR表示配置失敗,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示時間溢出。
使用舉例:
DMA2D_HandleTypeDef Dma2dHandle; if(HAL_DMA2D_BlendingStart_IT(&Dma2dHandle, /* DMA2D句柄 */ (uint32_t)&BufferInput1, /* 源地址1,前景色 */ (uint32_t)&BufferInput2, /* 源地址2,背景色 */ (uint32_t)&BufferResult, /* 目的地址 */ SIZE_X, /* 源數據長度,單位像素個數*/ SIZE_Y) /* 源數據行數 */ != HAL_OK) { Error_Handler(); }
45.5 總結
本章節就為大家講解這么多,DMA2D功能比較重要,一定要做到熟練使用。