• 【STM32F429开发板用户手册】第45章 STM32F429的图形加速器DMA2D的基础知识和HAL库API


    最新教程下载: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 初学者重要提示

    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功能比较重要,一定要做到熟练使用。

  • 相关阅读:
    一些 Ubuntu 使用的小技巧
    体验 Web 自动化测试工具 Selenium
    CentOS 7 上安装 Nginx
    Windows查看端口占用情况
    Windows远程登录提醒:由于没有远程桌面授权服务器可以提供许可证,远程会话连接已断开。请跟服务器管理员联系。
    Vue动态的改变css样式
    centos7 U盘安装卡在 starting dracut initqueue hook Reached target Basic System
    用tsc编译ts文件的时候报错,tsc : 无法加载文件,因为在此系统上禁止运行脚本;
    Linux修改SSH默认的端口号
    Centos编译安装新版本Git
  • 原文地址:https://www.cnblogs.com/armfly/p/13458070.html
Copyright © 2020-2023  润新知