【STM32F429開發板使用者手冊】第45章 STM32F429的圖形加速器DMA2D的基礎知識和HAL庫API

2020-08-08 15:47:40

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

第45章       STM32F429的圖形加速器DMA2D的基礎知識和HAL庫API

本章節爲大家講解DMA2D,實際專案中顯示屏的加速全靠它了,而且效能也比較給力。

目錄

第45章       STM32F429的圖形加速器DMA2D的基礎知識和HAL庫API

45.1 初學者重要提示

45.2 DMA2D基礎知識

45.2.1 DMA2D硬體框圖

45.2.2 DMA2D工作模式

45.2.3 前景層和背景層的輸入以及顏色格式轉換

45.2.4 前景層和背景層混合

45.2.5 DMA2D輸出顏色格式

45.3 DMA2D的HAL庫用法

45.3.1 DMA2D暫存器結構體DMA2D_TypeDef

45.3.2 DMA2D參數初始化結構體DMA2D_InitTypeDef

45.3.3 DMA2D的圖層結構體DMA2D_LayerCfgTypeDef

45.3.4 DMA2D控制代碼結構體DMA2D_HandleTypeDef

45.3.5 DMA2D初始化流程總結

45.4 原始檔stm32f4xx_hal_dma2d.c

45.4.1 函數HAL_DMA2D_Init

45.4.2 函數HAL_DMA2D_ConfigLayer

45.4.3 函數HAL_DMA2D_Start_IT

45.4.4 函數HAL_DMA2D_BlendingStart_IT

45.5 總結


 

45.1 初學者重要提示

  1.   DMA2D是專門用於LCD加速的,特別是刷單色屏,刷圖片,刷Alpha(透明)混合效果全靠它,而且可以大大降低CPU利用率。
  2.   特別注意,大家只需對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表示時間溢位。

注意事項:

  1. 函數HAL_DMA2D_MspInit用於初始化DMA2D的底層時鐘、NVIC等功能。需要使用者自己在此函數裏面實現具體的功能。由於這個函數是弱定義的,允許使用者在工程其它原始檔裏面重新實現此函數。當然,不限制一定要在此函數裏面實現,也可以像早期的標準庫那樣,使用者自己初始化即可,更靈活些。
  2. 如果形參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功能比較重要,一定要做到熟練使用。