你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32H7的图形加速器DMA2D的基础知识和HAL库API

[复制链接]
STMCU小助手 发布时间:2021-12-24 17:00
55.1 初学者重要提示
. W/ q$ j  B% Z4 B2 ^8 ~  DMA2D是专门用于LCD加速的,特别是刷单色屏,刷图片,刷Alpah(透明)混合效果全靠它,而且可以大大降低CPU利用率。5 y. p6 K. b$ O6 M) D
  测评STM32H7的LTDC+DMA2D性能,100Hz以上无压力,刷800*480图片和色块仅需2.6ms一张
5 \  i# y( I% a4 E$ L  H7的DMA2D与F429的DMA2D最大区别是支持了ARGB和ABGR互转,而且支持H7的硬解JEPG输出格式YCbCr转RGB,方便LCD显示。! ?: d4 o, A" l# i
  特别注意,大家只需对HAL库提供的DMA2D操作API有个了解即可,实际工程中,并不使用这些API,我们需要使用更加高效的寄存器直接操作,在下一章节会为大家说明。7 M8 d0 P+ D- Q: d  t# G6 z9 ], d7 S6 ^
55.2 DMA2D基础知识! v9 _/ o( {+ P# ?# Z( v) A" L
DMA2D主要实现了两个功能,一个是DMA数据传输功能,另一个是2D图形加速功能。; X+ U  {: J. B' f& ?& H1 L
) G+ c" Y' e8 L% _* \
  DMA数据传输8 }4 ?& a# q  s& ^2 r8 H
主要是两种方式,一个是寄存器到存储器,另一个是存储器到存储器。通过DMA可以大大降低CPU的利用率。
, O- o2 m" ?1 V* F* P
) V9 _  l" i$ M& l8 t% `  2D图形加速功能
& m: I2 h; r8 n: r支持硬件的颜色格式转换和Alpha混合效果。% |  B: `0 U$ E6 N1 M
) c2 Q  c+ \: k6 u$ r! v' _
55.2.1 DMA2D硬件框图
( E9 k2 @2 I2 T) o) G9 c认识一个外设,最好的方式就是看它的框图,方便我们快速地了解DMA2D的基本功能,然后再看手册了解细节。框图如下所示:
; Q) g% @. }+ E: z8 b+ l7 g
9 {5 z# `" A, }, t. m! m
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
9 [0 [3 \/ L% f+ W' i

, \- B3 \* N0 k5 o通过这个框图,我们可以得到如下信息:
. c* F# v5 k9 o. |
' S: \4 @' D! ~  dma2d_aclk3 T/ W& `9 x- J/ H) j
AXI 总线时钟输入。
/ d- T* J2 l# `7 f, w3 B5 o4 v2 Z% k9 z6 U
  dma2d_gbl_it
9 r7 v7 g6 f: i2 V- s" K$ xDMA2D全局中断输出。
2 d- n* _% q, A
4 k6 |% U/ s' w+ Y$ i& e) W3 N  dma2d_clut_trg, N1 k# N: [0 w& L
CLUT传输完成信号输出,可以触发MDMA。! J  E0 Y6 U  {6 S5 Z$ @

; g- c1 w0 X- O. g; }  dma2d_tc_trg
8 s1 Q1 S; n8 o% D7 x. y# P传输完成信号输出,可以触发MDMA。) e3 P+ f6 I( j' g& x2 v3 ^, G
5 F5 s$ f$ A3 p/ U# E
  dma2d_tw_trg
/ p' w3 Z& O# ^; ^- l8 j# c传输watermark信号输出,可以触发MDMA。- Q/ ?+ Q# v1 `/ g

) ]5 G( W) Y# G. h将这个硬件框图简化一下,就是下面这样:, O: W7 ^, i+ `! ^1 }

( V) z. h: v+ M* t9 i) ?& W
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
: p( B) {- c2 s( F7 D5 L/ z& y& n

" u+ Q. x& W9 Z0 B7 i下面按照简化的硬件框图,对每个部分做个说明。
: P& Q$ L& b6 h0 J6 _6 Z
# M7 Z' _  Y- C" T55.2.2 DMA2D工作模式. C  B+ M4 j; D$ b
DMA2D支持的工作模式如下:
0 L' j9 ]) @; a0 e- g' w0 D
. |3 q+ [2 ^, A  模式1:寄存器到存储器模式
' M. Q. K* L) I) U$ Z9 t这个模式主要用于清屏,也即是将显示屏清为单色效果。" m5 ^+ I! ~9 U; m, ~6 p$ D

) ^; z5 V% Y5 }# A. W  模式2:存储器到存储器模式; U: x+ b, C& ?% f
这个模式用于从一个存储器复制一块数据到另一个存储器,比如将摄像头OV7670的输出图像复制到LCD显存就可以采用这种方式。
6 C' V0 E4 S, B: b$ J7 R
8 o0 `7 C" O& O  模式3:存储器到存储器模式,带颜色格式转换
' k1 @# u1 F- e这个模式比模式2多了一个颜色格式转换,比如我们要显示一幅RGB888颜色格式的位图到RGB565颜色格式的显示屏,就需要用到这个模式,只需输入端配置为RGB888,输出端配置RGB565即可。位图颜色格式转换后会显示到显示屏上。
  |" D" J9 i: ~: A' @7 i) E+ j( t
  模式4:存储器到存储器模式,带颜色格式转换和混合
' u3 ^( I  C  f这个模式比模式3多了一个混合操作,通过混合,可以将两种效果进行混合显示。
( a6 A& l- \% w- B- V3 O  a$ w; K
9 T9 {7 ]* K, x4 r* k  模式5:存储器到存储器模式,带颜色格式转换和混合,前景色是固定的0 J. a) v2 S: S2 N9 W
同模式4,只是前景色的颜色值是固定的。
: S3 e& Y* L' ]# P3 p9 S4 v7 ]  G5 w, L$ _- X
55.2.3 前景层和背景层的输入以及颜色格式转换: c9 j& I9 x5 E" E5 l4 A' y8 ~' X8 M, J
前景层和背景层是指的用户绘制图形时的前景色和背景色,比如我们显示汉字,字体会有一个颜色,也就是前景色,还有一个背景色。又比如我们绘制两幅图片,想将两幅图片混合,那就可以将一幅图片作为前景层,另一个幅图片作为背景层。
# |/ u8 S5 E* b+ X  @( m5 K* A0 m3 j/ ^+ ~% o4 c  o, Y6 f0 [4 ]
DMA2D支持的输入颜色格式如下,前景层和背景层一样:
4 X- O4 D8 p, B1 F0 g; S. W0 J% c+ J' f/ u
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
7 r: z& D; o' E4 i, y6 V0 q! q7 y
5 t) }; n3 ]/ }7 c- J7 ]2 T
前8种颜色格式在第50章的第2小节开头有介绍,这里把后四种做个说明:6 v+ `- e/ A8 N' A9 _& N

( R1 R) `, v1 v  L4 (4-bit luminance or CLUT)$ C4 v. ^% `) m! H
4位颜色格式,实际上仅仅是4位索引值,范围0–15,而每个索引值的具体颜色值在查色表CLUT里面存储。( _- g* l4 _& s! Y9 d2 I: m! W
7 f; o) l2 O. F. L" ?7 e
  A4和A8
" [6 O7 g9 G' sA4和A8用于特定的Alpha模式,既不存储颜色信息,也没有索引值。3 B$ q8 t# s. _  o1 v
7 J; j, k* X3 ^7 [
  YCbCr
# p3 N+ k2 ]2 o2 i( ?2 \# u这个是H7的硬件JPEG输出的颜色格式,后面JPEG章节为大家专门做讲解。
1 V1 D4 J1 x) ?( D1 T& i( e. E* k. ]# j2 H, g! I, n  c, O: E9 {* e; J) E
这里特别注意一点,输入颜色格式的Alpha值是可以设置的,而且颜色格式里面的R通道和B通道可以交换位置。2 n7 |8 x, q# I: C+ K2 V3 C1 Z  v

2 {; d' p$ t$ ^4 r+ |* s55.2.4 前景层和背景层混合# T, B2 I8 T6 W/ E& ~' v# I+ D& t7 E: d
DMA2D混合器用于混合前景色和背景色,这个功能不需要任何配置,仅需要通过DMA2D_CR寄存器使能即可。混合公式如下:" p6 Q. w$ ]# d3 v, ^

0 V' S! H$ f- C2 E  r' K
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
  b( |9 Z! B' Q6 V! i/ m, ~4 ^

) Q6 j9 k" S8 k1 y6 v1 T; _55.2.5 DMA2D输出颜色格式; A0 Z. X: D9 \8 A1 G0 x# V
DMA2D支持的输出颜色格式如下:  a. E" _5 {0 r) n2 L$ J' ]# Y' e
# u# Z4 C" ^+ e* ~) O# s8 E9 F
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
9 r5 g2 g  z. M8 x, x3 V  r0 e  V

6 X8 ^. }9 ]8 C" I9 ?这里特别注意一点,输出颜色格式的Alpha值是可以设置的,而且颜色格式里面的R通道和B通道可以交换位置。9 q9 \3 O$ J/ Y& Y

5 `- h# C6 u5 L* B  w, E2 a55.3 DMA2D的HAL库用法
1 q4 D, J! w' Q  n( ?5 ^* DDMA2D的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断。下面我们逐一展开为大家做个说明。
+ G# p! ], X; }8 ^% \4 W
6 x7 h- ?8 I8 s55.3.1 DMA2D寄存器结构体DMA2D_TypeDef- g! M; O4 F! y: l
DMA2D相关的寄存器是通过HAL库中的结构体DMA2D_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:
7 ~% s7 c- W: k7 l0 Q- A: i
: }+ h, v( U- |) M0 y, D6 K
  1. typedef struct
    9 E, j* p5 u/ |/ y6 h6 `) S
  2. {. w3 d( I' G. M2 Y+ _
  3.   __IO uint32_t CR;            /*!< DMA2D Control Register,                         Address offset: 0x00 *// G; f* P  X8 M7 l' K  E9 a4 [" _" x
  4.   __IO uint32_t ISR;           /*!< DMA2D Interrupt Status Register,                Address offset: 0x04 */. R2 t. U# x6 Z. i0 \2 h
  5.   __IO uint32_t IFCR;          /*!< DMA2D Interrupt Flag Clear Register,            Address offset: 0x08 */4 Z9 S5 R1 v( W6 `) ~+ h1 [, p
  6.   __IO uint32_t FGMAR;         /*!< DMA2D Foreground Memory Address Register,       Address offset: 0x0C */8 h4 \. O/ _1 w+ U' R1 Q8 r7 k( \
  7.   __IO uint32_t FGOR;          /*!< DMA2D Foreground Offset Register,               Address offset: 0x10 */
    7 }  @! I8 a+ e) ?
  8.   __IO uint32_t BGMAR;         /*!< DMA2D Background Memory Address Register,       Address offset: 0x14 */
    ' W! }0 a; f% _1 h
  9.   __IO uint32_t BGOR;          /*!< DMA2D Background Offset Register,               Address offset: 0x18 */  D: J& m2 G5 |' t- O9 w
  10.   __IO uint32_t FGPFCCR;       /*!< DMA2D Foreground PFC Control Register,          Address offset: 0x1C */
    9 P) v" \5 M; u7 @! d
  11.   __IO uint32_t FGCOLR;        /*!< DMA2D Foreground Color Register,                Address offset: 0x20 */
    + a9 d. e. D9 F$ W0 V4 Z" Y
  12.   __IO uint32_t BGPFCCR;       /*!< DMA2D Background PFC Control Register,          Address offset: 0x24 */! E+ [/ b0 w7 Z6 w) g3 R& T
  13.   __IO uint32_t BGCOLR;        /*!< DMA2D Background Color Register,                Address offset: 0x28 */
    . e) X+ Y* w, D3 Y% n" y& ^
  14.   __IO uint32_t FGCMAR;        /*!< DMA2D Foreground CLUT Memory Address Register,  Address offset: 0x2C */; g3 Z! E! ~/ O& i& P: V
  15.   __IO uint32_t BGCMAR;        /*!< DMA2D Background CLUT Memory Address Register,  Address offset: 0x30 */* H# D  _9 o6 N. h
  16.   __IO uint32_t OPFCCR;        /*!< DMA2D Output PFC Control Register,              Address offset: 0x34 */
    $ `$ i) Y0 X# D- ]: M2 f
  17.   __IO uint32_t OCOLR;         /*!< DMA2D Output Color Register,                    Address offset: 0x38 */* W) h/ o+ [( p, r5 l1 m
  18.   __IO uint32_t OMAR;          /*!< DMA2D Output Memory Address Register,           Address offset: 0x3C */; C$ e3 s1 X9 L7 K  y
  19.   __IO uint32_t OOR;           /*!< DMA2D Output Offset Register,                   Address offset: 0x40 */3 ?% N! m# s1 M" D
  20.   __IO uint32_t NLR;           /*!< DMA2D Number of Line Register,                  Address offset: 0x44 */
    % q8 v/ {0 r5 q1 m
  21.   __IO uint32_t LWR;           /*!< DMA2D Line Watermark Register,                  Address offset: 0x48 */
    3 i* p  E9 ^/ R4 Y
  22.   __IO uint32_t AMTCR;         /*!< DMA2D AHB Master Timer Configuration Register,  Address offset: 0x4C */: O7 ?+ Z" R; B" p4 P
  23.   uint32_t      RESERVED[236]; /*!< Reserved, 0x50-0x3FF */9 J2 ]$ f4 b) t, {% R: O
  24.   __IO uint32_t FGCLUT[256];   /*!< DMA2D Foreground CLUT,                          Address offset:400-7FF */
    + T# M0 N$ u5 z/ \
  25.   __IO uint32_t BGCLUT[256];   /*!< DMA2D Background CLUT,                          Address offset:800-BFF */
    6 `. s6 {+ H/ `' p
  26. } DMA2D_TypeDef;
复制代码

: J, }( A" R2 k# k6 v3 W- f
+ i5 M& Z4 @4 b4 \# p__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
! y* U3 Z/ `3 X: V0 [7 n% s1 {9 K: z) \; d
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */1 W) {0 w" j5 O
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
% U7 K0 C! J$ R: K, A" [
下面我们再看DMA2D的定义,在stm32h743xx.h文件。
  1. #define PERIPH_BASE              ((uint32_t)0x40000000)
    ; h& B8 z8 `& d
  2. #define D1_AHB1PERIPH_BASE       (PERIPH_BASE + 0x12000000)
    & E7 R! A6 E* o) ^# A& O1 b: Z
  3. #define DMA2D_BASE               (D1_AHB1PERIPH_BASE + 0x1000)# E4 [! b% s$ g( o+ F7 K1 k
  4. #define DMA2D                    ((DMA2D_TypeDef *) DMA2D_BASE) <----- 展开这个宏,(DMA2D_TypeDef *) 0x52001000
复制代码
2 w/ t) c6 j" {: x0 S5 ~8 G
我们访问DMA2D的ISR寄存器可以采用这种形式:DMA2D->ISR = 0。0 B% W7 g$ l# s( N
5 y. z. U$ O% M( w9 Y, |" G
55.3.2 DMA2D参数初始化结构体DMA2D_InitTypeDef
# i: @  a! e* n3 c9 n2 p此结构体用于配置DMA2D的基本参数,具体定义如下:6 C7 g8 G! L/ p4 z3 V4 T
5 B' C& x4 R( w$ U& H; L
  1. typedef struct3 D; V* D0 b7 C
  2. {: l9 |: [1 e, R! ]' E9 ^% G0 S* F
  3.   uint32_t             Mode;              0 C9 S( a0 z: R3 T
  4.   uint32_t             ColorMode;          Q. G' C; _% I! J7 [/ K' H
  5.   uint32_t             OutputOffset;       3 e; c# i# w. w0 e& k
  6.   uint32_t             AlphaInverted;    & ~) m" J2 x$ _0 e4 ?
  7.   uint32_t             RedBlueSwap;      
    + L. r5 g( p; |
  8. } DMA2D_InitTypeDef;
复制代码
$ ~7 ]4 t% P8 \2 R% ~* q+ }0 Y
下面将这几个参数逐一为大家做个说明:( |, M# }+ m  X7 Y( A

" c6 s! t8 `! ^3 z5 g7 l7 Y4 L  uint32_t   Mode
9 A9 i/ I' m  c此参数用于设置DMA2D的传输模式,具体支持的参数如下:( t. s9 p' m: ?; D& N% ~) [
, ?/ k: C) O2 a* E: B: k- T& n
  1. #define DMA2D_M2M        ((uint32_t)0x00000000U)  /*存储器到存储传输模式 */9 A- A; o$ ?( h8 f5 ~+ _. R* B
  2. #define DMA2D_M2M_PFC     DMA2D_CR_MODE_0         /*存储器到存储器传输模式,并执行FPC像素格式转 */
    0 F4 }1 v! V0 l9 p
  3. #define DMA2D_M2M_BLEND   DMA2D_CR_MODE_1         /* 存储器到存储器模式,并执行像素格式转换和混合 *// I+ G: F+ H. \7 K' g
  4. #define DMA2D_R2M         DMA2D_CR_MODE           /* 寄存器到存储器传输模式 */
    . l. e# v6 \3 q& b  x5 Y9 ?
复制代码

  b+ q% p% o: P* ?6 t1 Q# b
7 X& y  }2 r' g1 P8 m  uint32_t   ColorMode1 V$ `: b3 p& e5 u  `+ _
此参数用于设置DMA2D的输出颜色格式,具体支持的参数如下:
4 |: ?; A( ~8 f( z+ x% m
6 k; N: b7 [9 {1 w4 N* s7 F& R: V
  1. #define DMA2D_OUTPUT_ARGB8888       ((uint32_t)0x00000000U)               /* ARGB8888 */
    0 M. ~  R+ W: N+ i4 v: `
  2. #define DMA2D_OUTPUT_RGB888         DMA2D_OPFCCR_CM_0                     /* RGB888 */8 H$ e# N- B8 X8 E/ p; `% K: ?
  3. #define DMA2D_OUTPUT_RGB565         DMA2D_OPFCCR_CM_1                     /* RGB565 */
    : K4 @$ g3 n' e* n
  4. #define DMA2D_OUTPUT_ARGB1555       (DMA2D_OPFCCR_CM_0|DMA2D_OPFCCR_CM_1) /* ARGB1555 */6 l# O6 }! @2 K4 W# J6 H9 B% u
  5. #define DMA2D_OUTPUT_ARGB4444       DMA2D_OPFCCR_CM_2                     /* ARGB4444 */$ m: O% I$ S# d5 M, V
复制代码

9 h  Q1 _( r: D) K8 ^( @. v6 w0 ]5 F4 V9 a
  uint32_t   OutputOffset2 c, H1 ^1 C4 h
此参数用于设置输出位置的偏移值,参数范围0x0000到0x3FFF。6 j8 D' a( B# b* m/ y
4 X  x2 _3 ]' i6 s( a* `( k' a
  uint32_t   AlphaInverted2 ~# E# C$ _  _
此参数用于设置DMA2D的输出颜色格式Alpha值反转(即255-原来数值),具体支持的参数如下:     & Y! q* g, O* C9 b% d# E; t1 K
$ ]% S1 {' L4 f/ f% O
  1. #define DMA2D_REGULAR_ALPHA      ((uint32_t)0x00000000U)  /* 正常输出 */% k0 x, i0 T( D" ?# i+ B2 C$ q
  2. #define DMA2D_INVERTED_ALPHA     ((uint32_t)0x00000001U)  /* 反转输出 */
复制代码
0 _; p. a- d6 n  u& v+ o3 V1 @0 W
  uint32_t   RedBlueSwap
$ l' O* j3 X6 z+ `8 }6 ?+ O! j5 Q此参数用于设置DMA2D的输出颜色格式中R通道和B通道的交换,具体支持的参数如下:" q# ?& e  f" ?8 O% B) @4 K
; M4 S9 ~! w# Y* G& O$ \1 @
  1. #define DMA2D_RB_REGULAR   ((uint32_t)0x00000000U)  /* 不交换(RGB or ARGB) */
    2 x+ l% Z% e& y
  2. #define DMA2D_RB_SWAP      ((uint32_t)0x00000001U)  /* 交换(BGR or ABGR) */
复制代码

8 d% R. E2 Y2 n1 t1 T55.3.3 DMA2D的图层结构体DMA2D_LayerCfgTypeDef: g1 ^, t7 D" ?, r
此结构体用于配置前景色和背景色。
  M2 ^! ^5 F4 v6 l  X9 R( l5 g2 v
6 [+ h, k' v* [/ Z8 |0 E
  1. typedef struct( V1 U7 i  `1 e3 {% {
  2. {
    % I/ Q: r+ P* J1 v# n" y
  3.   uint32_t             InputOffset;       & r9 v+ d+ @- P: \
  4.   uint32_t             InputColorMode;    % ?4 {  F; F. E' H0 n( C5 F
  5.   uint32_t             AlphaMode;        
    ( x: x1 s/ ^2 o8 O& ^0 i. ?$ x3 b
  6.   uint32_t             InputAlpha;          Z7 r9 L5 }! ^
  7.   uint32_t             AlphaInverted;   
    5 s7 n" C9 v6 d; h" {8 T8 H; \
  8.   uint32_t             RedBlueSwap;       . Y. E) R3 `% u$ f
  9.   uint32_t             ChromaSubSampling;" o0 r: d* Y, O  _
  10. } DMA2D_LayerCfgTypeDef;
复制代码

& Q: K) E) p& m% [9 I下面将这几个参数逐一为大家做个说明。
3 E6 E" ^2 @/ T+ u; u5 L% y8 f* b
6 L0 e( G3 j1 ?7 M/ I  uint32_t  InputOffset
: V8 P1 }  R/ B5 R设置前景色或者背景色的输入偏移,范围0x000到0x3FFF。
6 Y$ z3 U4 Z" |7 M
3 A$ ]5 x: x% R  uint32_t  InputColorMode8 z/ o: Y: r/ x3 S0 h
设置前景色或者背景色的输入颜色格式,具体支持的参数如下:
9 W/ }, n0 S( r. o+ ?" D+ g: _2 t  }) X% }: p" b# l2 g, S; L
  1. #define DMA2D_INPUT_ARGB8888        ((uint32_t)0x00000000U)  /* ARGB8888 */
    2 z  O, e) f3 d4 D$ ^( u
  2. #define DMA2D_INPUT_RGB888          ((uint32_t)0x00000001U)  /* RGB888   */
    7 e" v" j( I5 @& n6 V5 j
  3. #define DMA2D_INPUT_RGB565          ((uint32_t)0x00000002U)  /* RGB565   */
    8 H3 Z& D8 Z( ]" {$ M
  4. #define DMA2D_INPUT_ARGB1555        ((uint32_t)0x00000003U)  /* ARGB1555 */
    ( e8 x# B& l" e6 s0 |: F
  5. #define DMA2D_INPUT_ARGB4444        ((uint32_t)0x00000004U)  /* ARGB4444 *// {  M- Q* {9 Z1 f0 U( v/ e0 U
  6. #define DMA2D_INPUT_L8              ((uint32_t)0x00000005U)  /* L8       */- D$ ]! @! R6 e% v/ N; L
  7. #define DMA2D_INPUT_AL44            ((uint32_t)0x00000006U)  /* AL44     */' ~6 }' }2 B$ r! d2 [, G% M& R
  8. #define DMA2D_INPUT_AL88            ((uint32_t)0x00000007U)  /* AL88     */
    ( s6 Z* G) D) A& m2 [! `
  9. #define DMA2D_INPUT_L4              ((uint32_t)0x00000008U)  /* L4       */" G0 l: C& A4 s- S1 F3 j1 I  l, Z/ r
  10. #define DMA2D_INPUT_A8              ((uint32_t)0x00000009U)  /* A8       */
    - T1 X# e- o: ~2 ?
  11. #define DMA2D_INPUT_A4              ((uint32_t)0x0000000AU)  /* A4       */
    , W$ k2 A  Y" i4 |6 _9 P
  12. #define DMA2D_INPUT_YCBCR           ((uint32_t)0x0000000BU)  /* YCbCr    */
复制代码
0 @+ I6 y+ n* V3 C
  uint32_t AlphaMode
/ U$ Y. e# U% K" I设置前景色或者背景色的Alpha模式,具体支持的参数如下:: b5 ~! f2 ~! t! o# T

: v5 n& H: ~% ^- \
  1. #define DMA2D_NO_MODIF_ALPHA   ((uint32_t)0x00000000U)  /* 不修改Alpha通道值 */
    8 w5 E, ^( X9 l. q$ R1 u' v
  2. #define DMA2D_REPLACE_ALPHA    ((uint32_t)0x00000001U)  /* 用新设置的Alpha值替换原始Alpha值 */
    $ G! r* {6 s- u: e% D, Y, f- P1 w
  3. #define DMA2D_COMBINE_ALPHA    ((uint32_t)0x00000002U)  /* 用新设置的Alpha值与原始Alpha值的乘积替换原始Alaha值*/
复制代码
: R- l7 [# W9 N& U2 c6 A) k
  uint32_t  InputAlpha
1 k3 F( _5 M+ l5 a1 H- D设置前景色或者背景色的Alpha值,范围0x00到0xFF,如果颜色格式是A4或者A8,那么此参数的范围是0x00000000到0xFFFFFFFF,标准的ARGB8888格式。+ P0 ]/ r/ i  j0 K  S, M& U( p. ?5 J

0 y0 [4 g) g/ b! v" \  uint32_t AlphaInverted9 _0 h  M% V# P. v8 w% s6 _" w$ Q/ z) @
设置前景色或者背景色的输入颜色格式Alpha值反转(即255-原来数值),具体支持的参数如下:     
# l  ^) a' D2 D# d
. S9 a# a; Z0 {- [- ^
  1. #define DMA2D_REGULAR_ALPHA      ((uint32_t)0x00000000U)  /* 正常输出 */
    % Y% f" D! _$ d! ^
  2. #define DMA2D_INVERTED_ALPHA     ((uint32_t)0x00000001U)  /* 反转输出 */     
复制代码
8 y  t* N9 Q( g; @
  uint32_t   RedBlueSwap
  Y% Q; D! [8 y: @) a) d设置前景色或者背景色颜色格式中R通道和B通道的交换,具体支持的参数如下:  \' ~: [5 |# ]4 O& I
  x# X$ G/ x$ J1 V4 }' C4 y9 ^
  1. #define DMA2D_RB_REGULAR   ((uint32_t)0x00000000U)  /* 不交换(RGB or ARGB) */3 M, e2 c; b! T/ f) S) _
  2. #define DMA2D_RB_SWAP      ((uint32_t)0x00000001U)  /* 交换(BGR or ABGR) */
复制代码
. {: ~; x0 |) |) N
  uint32_t   ChromaSubSampling
5 I2 ]  l: x- @6 q设置前景色或者背景色中YCbCr 颜色模式的采样格式,具体支持的参数如下:
  1. #define DMA2D_NO_CSS               ((uint32_t)0x00000000)  /* 4:4:4 */
    3 `2 X) z) X: b8 b* [' R4 m; `
  2. #define DMA2D_CSS_422              ((uint32_t)0x00000001)  /* 4:2:2 */
    ) G- Y0 i& \5 K0 S* X
  3. #define DMA2D_CSS_420              ((uint32_t)0x00000002)  /* 4:2:0 */  
复制代码

9 K+ T$ p3 }+ C" X55.3.4 DMA2D句柄结构体DMA2D_HandleTypeDef
: e, s& b5 z: [1 Z* g6 S
HAL库在DMA2D_TypeDef, DMA2D_InitTypeDef和DMA2D_LayerCfgTypeDef的基础上封装了一个结构体DMA2D_HandleTypeDef,定义如下:
, A2 m  R9 @- _/ l* x( s2 g/ N. Q+ \" o& j6 E
  1. typedef struct __DMA2D_HandleTypeDef
    # ~5 [+ N" d5 f# E! W! W# v  t- w
  2. {$ w( y% \2 |0 R3 k5 a! M8 e
  3.   DMA2D_TypeDef               *Instance;                                                                                                                                                                                          
    + Y% E) N4 V: Y* Z/ g6 f9 h: z
  4.   DMA2D_InitTypeDef           Init;                                                        
      |$ U- o* b- N( r5 q  O$ @3 W
  5.   void                        (* XferCpltCallback)(struct __DMA2D_HandleTypeDef * hdma2d);                                                                                                                                             
    ) K; F  Z4 T7 G6 j
  6.   void                        (* XferErrorCallback)(struct __DMA2D_HandleTypeDef * hdma2d);                                                                                      
    + B3 u' M# ?$ r* E
  7.   DMA2D_LayerCfgTypeDef       LayerCfg[MAX_DMA2D_LAYER];                                    
    0 d) r) y# D4 M, {' `8 B# ^
  8.   HAL_LockTypeDef             Lock;                                                                                                                                                                                                    ; |, K: y5 K5 u9 r$ E
  9.   __IO HAL_DMA2D_StateTypeDef State;                                                                                                                                                                                                   
    5 \: Q5 D$ g( m" C( H/ t! N' F7 B
  10.   __IO uint32_t               ErrorCode;                                                   } DMA2D_HandleTypeDef;
    + [8 h5 [2 ?  K( C1 ~
复制代码
3 V( ^! s) q, Y% M5 K6 G6 l
下面将这几个参数逐一做个说明。
  Q0 s! u& d+ x. {! g: U
5 X: l. I3 g( s2 Z) i  DMA2D_TypeDef  *Instance
4 g3 {5 w& x9 A, k( }  x这个参数是寄存器的例化,方便操作寄存器,详见本章3.1小节。
4 B+ ?. I6 P/ k/ D9 B& a0 h
. `7 `$ v( F9 H' |  DMA2D_InitTypeDef  Init;  7 N) h8 M/ x; ^5 N2 M; {0 L# m
这个参数是用户接触较多的,用于配置DMA2D的基本参数,详见本章3.2小节。
' y. L$ ^0 p5 b9 }; o' s. `3 x) A: P7 |# ?
  void     (* XferCpltCallback)(struct __DMA2D_HandleTypeDef * hdma2d);
# f1 ]) l: v& w  void     (* XferErrorCallback)(struct __DMA2D_HandleTypeDef * hdma2d);
2 |( q9 H. m: Z. z) j1 WDMA2D中断服务程序里面执行的回调函数,一个是传输完成回调,另一个是传输错误回调。
' \5 t- M* [* e( N$ h; t- d9 N( e- }
  DMA2D_LayerCfgTypeDef   LayerCfg[MAX_DMA2D_LAYER]5 I  @" Q3 V- K. O" v
这个参数用于前景色和背景色的设置,MAX_DMA2D_LAYER=2,详见本章3.3小节。4 X1 j; }7 |2 S* C/ y

0 m) |* d, a; {) B2 f  HAL_LockTypeDef   Lock" @+ j6 H/ j6 ]# m" ^
__IO uint32_t    State;* T; N. A0 ?) f/ e& o

0 O% w3 t1 m2 u& Q8 o__IO uint32_t    ErrorCode
: t7 h0 h  o6 _4 K, p- ]4 t$ b6 v; d4 w( ^/ K
这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DMA2D通信状态,而ErrorCode用于配置代码错误。" x8 Y4 J" H, e/ i
2 i  Z: |1 V8 O: X1 S
55.3.5 DMA2D初始化流程总结

: A# V, X$ g) u+ p对于DMA2D来说,其实不需要初始化流程,每个功能都可以直接封装出一个函数来,下个章节会为大家专门讲解,也是实际项目比较推荐的方式。6 M2 V7 ?: W$ J3 Q1 A: a! o

+ W) }4 K% z; T, ?/ J9 `$ b0 `- Z* Z# H55.4 源文件stm32h7xx_hal_dma2d.c
3 Z4 Z) e' M7 H7 ^# I2 b这里把我们把如下几个常用到的函数做个说明:
) H# Y" Q5 N, t. B3 m  A% j
: j4 }  G0 i# `# a3 _) ?  HAL_DMA2D_Init6 N& [; N8 n9 H+ L9 U
  HAL_DMA2D_ConfigLayer  T& b4 e$ K  [* x7 T3 X
  HAL_DMA2D_Start_IT
3 y; x' ]8 J- k, Q  HAL_DMA2D_BlendingStart_IT
2 ~1 O5 H+ A1 J" T- ^  w2 r; q, v4 k4 [! }4 F; v6 \- H
55.4.1 函数HAL_DMA2D_Init
) b- \# o% V  y$ B9 P4 n函数原型:3 U' L8 W* U3 [1 ^. J5 O. P. V
# P7 j7 C( H; k7 l8 X& K
  1. HAL_StatusTypeDef HAL_DMA2D_Init(DMA2D_HandleTypeDef *hdma2d)
    - C1 k5 h* v' y9 C. B9 ?
  2. {
    7 \0 k- k$ e0 W# r* {! a9 y

  3. & z- d2 M* h) Q4 _5 z! V  H
  4. /*  检测参数是否有效 */
    5 Y  `! I6 Y; f- w1 x  d
  5.   if(hdma2d == NULL)( o$ y0 N6 K* k% S) g" l
  6.   {' U, r3 D  e; Z6 H6 ^% v
  7.      return HAL_ERROR;
    $ }1 Y8 r; W# `" m; T% |. n  X
  8.   }2 B/ C4 u% C' \# E! f# n" _

  9. . T5 c2 ^( U6 N2 ^
  10.   /* 检测函数形参 */
    $ ~' `- \, x+ X0 N+ s4 v
  11.   assert_param(IS_DMA2D_ALL_INSTANCE(hdma2d->Instance));
    5 P4 R# i) o! M* X# F9 w# N
  12.   assert_param(IS_DMA2D_MODE(hdma2d->Init.Mode));
    , c- p. k1 J# ]3 I
  13.   assert_param(IS_DMA2D_CMODE(hdma2d->Init.ColorMode));
    3 K  P# }, n+ i' y- c' Y/ W
  14.   assert_param(IS_DMA2D_OFFSET(hdma2d->Init.OutputOffset));
    4 L. O2 b( Q, i. t( n/ ^. A
  15. " _6 e( H% e- O0 R* o0 q0 ?  M
  16.   if(hdma2d->State == HAL_DMA2D_STATE_RESET); l, k- s/ A$ a' I) W
  17.   {
    , N4 s# l9 C- D# Y; n1 G: x, |
  18.     hdma2d->Lock = HAL_UNLOCKED;) L5 A! v( ]9 E$ Q- |: F* P
  19.     /* 初始化GPIO,NVIC等 */
      q' F& r/ Z+ U: G* W
  20.     HAL_DMA2D_MspInit(hdma2d);7 |6 _1 ]# |4 T
  21.   }. U8 z6 Q2 ?* @" `
  22.   v7 S! K) g' ]4 W- \
  23.   /* 设置DAM2D外设状态 */
      W7 A, _7 Y" R6 g# m0 n
  24.   hdma2d->State = HAL_DMA2D_STATE_BUSY;  
    6 K1 s2 u) g9 q4 b+ `
  25. ( ^1 F1 F, u- D0 e  V( m& P, H
  26.   /* 设置DAM2D工作模式 -------------------------------------------*/5 |) D* h+ w  M2 W" \
  27.   MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_MODE, hdma2d->Init.Mode);/ C0 g3 S! A; Z' }& p. J' p" H

  28. : z6 h8 c* f: u7 ?' S
  29.   /* 设置输出颜色格式 ---------------------------------------*/. @/ R4 c/ ^6 r
  30.   MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_CM, hdma2d->Init.ColorMode);$ m8 g. A/ @5 N0 f/ q# _* n

  31. : p( T- {9 _9 t* }+ i: ^( `) b
  32.   /* 设置输出偏移 ------------------------------------------*/  
    0 i( j7 J  ~$ h; f6 i3 D
  33.   MODIFY_REG(hdma2d->Instance->OOR, DMA2D_OOR_LO, hdma2d->Init.OutputOffset);  
    / e! d# ^" l: D5 \8 S# g1 G

  34. ! }4 _1 e& [; `6 S5 @
  35.   /* 设置输出颜色格式中的Alpah值反转 */
    6 p3 n$ g. E8 M& o; F% e
  36.   MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_AI, (hdma2d->Init.AlphaInverted << DMA2D_POSITION_OPFCCR_AI));
    8 c' U+ J/ i: g* o

  37. ) r/ h+ \8 _% x9 V
  38.   MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_RBS,(hdma2d->Init.RedBlueSwap << DMA2D_POSITION_OPFCCR_RBS));
    ! [6 |5 ?# `5 T# A  ]' ]* K7 J

  39. 9 [$ o2 y, l# P( g: Q! a; _

  40. 0 ]- r9 H: _% B
  41.   /* 无错误 */
    4 p7 J: Q- @  N- \/ }' Y% D
  42.   hdma2d->ErrorCode = HAL_DMA2D_ERROR_NONE;
    : e# P9 Q2 e9 R

  43. " u0 R  j" j* S2 a3 ~( `+ c
  44.   /* DAM2D就绪 */
    8 t3 g9 \. H" `, [- H/ r
  45.   hdma2d->State  = HAL_DMA2D_STATE_READY;
    4 ~+ ?( ~' F" z& O% w
  46. + u6 h- n- X  K& P3 `$ G  I  E
  47.   return HAL_OK;
    6 D/ M  O: b1 d7 W% E  [
  48. }
复制代码
- `, C+ S9 n9 l  A' j. w% l
函数描述:
  v4 d! s* b" K2 L0 F
* h2 u( V3 Q9 R8 W* G/ K; A此函数用于初始化DMA2D的工作模式和输出颜色格式。
5 K# X% F! T: Y3 u" E; Q# M4 N$ Q2 P, P( ]" G  w, f4 D1 z3 H
函数参数:( i0 Z0 g! @7 [% B% r

- D  i$ k: }9 l: L7 [  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。
6 O: C% h  B! R  P  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
0 R, W" }" q: w9 O% i8 w8 }7 k注意事项:6 ^8 W: k5 n+ [  G

& Q5 r& H) m& f函数HAL_DMA2D_MspInit用于初始化DMA2D的底层时钟、NVIC等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。. Q& Q5 f! g; Y# T/ K
如果形参hdma2d的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量DMA2D_HandleTypeDef Dma2dHandle。- e$ R1 D/ n" `- L
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_DMA2D_STATE_RESET  = 0x00U。
* \! k& L/ a$ ^, j; u9 J& P3 H4 _7 P) |
6 y! t# O9 X  J解决办法有三
2 Z4 X2 i! F0 I6 V" Z, Z6 m( ]$ X" y6 m0 b! i+ o5 |: G* H" W5 X
方法1:用户自己初始DMA2D底层。  T' G$ E, ?& C2 I4 l/ Y2 O& t
1 y. B' |& f. v2 x4 h% y
方法2:定义DMA2D_HandleTypeDef LtdcHandle为全局变量。
$ r# y6 j: s/ i# f
* }2 F8 y3 m7 k7 _; a方法3:下面的方法
  1. if(HAL_DMA2D_DeInit(&Dma2dHandle) != HAL_OK)
    / o- H* h  J7 B7 J  X1 d; P
  2. {
    1 l9 h8 U6 n8 s' U' e
  3.     Error_Handler();; L4 m" N1 y; K$ f! o  B' m
  4. }  : |- v, T4 U6 e' S6 i
  5. if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)
    8 L' X3 U, K/ m' H: s/ e
  6. {' B5 G4 b% M8 c1 R& |! ]# m
  7.     Error_Handler();0 s4 f4 B5 m+ a$ ~" t' ~6 O" ?  X' J
  8. }
复制代码

6 R8 E( ^- [5 t5 w& {( r
* G8 j1 n! y. s. U+ j  z使用举例:( u% M% L+ `9 B$ v

! D( I# ?/ k( n( f- \; h
  1. DMA2D_HandleTypeDef Dma2dHandle;  [6 m$ Y8 R+ r/ T! {: |
  2. $ h0 p! c) k. \+ Z" d. ]
  3. /*##-1- 配置DMA工作模式,输出颜色格式和输出偏移 #############*/8 L/ e4 n, B8 g" G+ v0 C) Z2 P
  4. Dma2dHandle.Instance = DMA2D;
    6 p  k0 x8 K- C$ }2 v9 [4 L* _+ r  {! `

  5. 8 Z# c; n2 e/ ?' f9 h; A# Q
  6. Dma2dHandle.Init.Mode          = DMA2D_M2M;             /* 存储器到存储器模式 */9 S- g! ?' G) Z4 x9 z
  7. Dma2dHandle.Init.ColorMode     = DMA2D_OUTPUT_ARGB4444; /* 输出颜色格式 */5 K* j$ p. c% X( L/ Q1 u5 P
  8. Dma2dHandle.Init.OutputOffset  = 0x0;                   /* 无输出偏移 */2 y& @/ Y/ Z. m
  9. Dma2dHandle.Init.RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输出颜色的R/B通过不切换 */
    4 ^7 `0 E8 n: H% f3 [/ g( J
  10. Dma2dHandle.Init.AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输出颜色的Alpha通道数值不翻转 */& v! C3 O$ u  |. s0 B9 I3 p0 ~' Y

  11. 2 V- \# S1 H' u
  12. /*##-2- DMA2D 回调函数配置 ######################################*/6 d" f" m% H9 f8 N, V$ e( \2 F
  13. Dma2dHandle.XferCpltCallback  = TransferComplete;  ?( X& P7 s) a) R- l7 C1 P
  14. Dma2dHandle.XferErrorCallback = TransferError;- a8 d1 J' e- g/ w% }
  15. # k2 A- H! s" {+ H' Y# A
  16. /*##-3- 前景层配置 ###########################################*/
      k3 l2 i* {: y: q: a$ `) h; @
  17. Dma2dHandle.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;      /* 保持输入颜色格式中的Alpha值 */
    + _6 y( M3 X: F0 [( A- z/ U
  18. Dma2dHandle.LayerCfg[1].InputAlpha = 0xFF;                     /* 完全不透明 */5 H; R+ {1 v8 H5 N
  19. Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB4444; /* 输入颜色格式 */
    " O5 Z. v0 s! ]4 i. C
  20. Dma2dHandle.LayerCfg[1].InputOffset = 0x0;                     /* 输入无偏移 */
    * Q' y% P7 O9 F$ v7 K2 [, P
  21. Dma2dHandle.LayerCfg[1].RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输入颜色的R/B通过不切换*/
    * ]' [4 {6 w9 G' \! f7 T2 ~
  22. Dma2dHandle.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输入颜色的Alpha通道数值不翻转*/
    3 h3 b5 }: g2 P

  23. # o& d  D# a  Q% Z1 T/ w
  24. / w( U. d; A, E% d
  25. /*##-4- DMA2D 初始化 ###############################################*/
    4 I4 V7 L: U. l; |
  26. if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)
    5 G9 q+ H, ?" o) D
  27. {
    ; [! A4 w# x' b/ R$ z  X
  28.     Error_Handler();
    0 ], Z6 S9 u) Y; S8 T
  29. }
复制代码

6 Z8 \$ @# h# Q3 M5 c3 C3 ]6 a55.4.2 函数HAL_DMA2D_ConfigLayer4 t9 H4 ^7 v+ v& Q* k0 J) p
函数原型:, j' I0 x5 V' P1 t. ?
9 D" V; B. I( j; }! @' l
  1. HAL_StatusTypeDef HAL_DMA2D_ConfigLayer(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx)4 s  P. n2 Q7 E& O- Y0 X
  2. { ( N' m) I& I" p6 D
  3.   DMA2D_LayerCfgTypeDef *pLayerCfg = &hdma2d->LayerCfg[LayerIdx];; G5 c7 _# L0 |" A7 Q
  4. 9 v0 w. O1 p7 Y, b
  5.   uint32_t regMask = 0, regValue = 0;
    ! j( o) k4 ^/ {# b8 @

  6. # l: E" h% `/ j4 S! _& f: X. |
  7.   /* 检查参数 */
    ; k- s2 k4 P* ?6 @) S
  8.   assert_param(IS_DMA2D_LAYER(LayerIdx));  3 b6 k- x- y% J
  9.   assert_param(IS_DMA2D_OFFSET(pLayerCfg->InputOffset));  
    6 T, C: r% ~+ K9 q+ t+ Z
  10.   if(hdma2d->Init.Mode != DMA2D_R2M)1 e% `& @( F* f( f1 R- [6 G- N. B* y/ p  T
  11.   {  0 W9 @& h5 E  H1 N5 `# z
  12.     assert_param(IS_DMA2D_INPUT_COLOR_MODE(pLayerCfg->InputColorMode));8 Q5 e4 m# X. I  V- a: S6 f
  13.     if(hdma2d->Init.Mode != DMA2D_M2M)
    9 [0 N# M, Q% A" l9 W
  14.     {5 |# M, K# f0 V# m. }
  15.       assert_param(IS_DMA2D_ALPHA_MODE(pLayerCfg->AlphaMode));
    4 j: A0 q5 M! {! `4 Z
  16.     }( W' O/ c2 \3 L
  17.   }! \$ x& |2 |" u8 x% |& ^" s% V

  18. 5 M: S. H) A$ {
  19.   /* 上锁 */
    3 E4 }5 }- W' a
  20.   __HAL_LOCK(hdma2d);
    2 x/ g) U5 Y% h% z% @  q

  21. ( j5 z& E0 g3 c( {2 i
  22.   /* 设置DMA2D外设状态 */
    . ?$ c+ B7 R% B2 i
  23.   hdma2d->State = HAL_DMA2D_STATE_BUSY;  
    + N( Y  t9 K/ G& M7 r* U) z8 {0 z
  24. 2 J5 ]) d# J2 C# a7 Q7 q
  25.   /* 准备好背景层或者前景层FPC寄存器配置参数*/5 T+ [3 M$ u( w: f
  26.   regValue = pLayerCfg->InputColorMode | (pLayerCfg->AlphaMode << DMA2D_POSITION_BGPFCCR_AM) | \
    8 B+ k7 @) e- f: r5 B0 i
  27.             (pLayerCfg->AlphaInverted << DMA2D_POSITION_BGPFCCR_AI) | \' ?' [8 D& D) _% r" f" p1 H
  28.             (pLayerCfg->RedBlueSwap << DMA2D_POSITION_BGPFCCR_RBS);0 I$ o0 h, L& Q* D' L* n$ B, L( d/ P

  29. + ~4 |- `  x+ S
  30.   regMask  = DMA2D_BGPFCCR_CM | DMA2D_BGPFCCR_AM | DMA2D_BGPFCCR_ALPHA | DMA2D_BGPFCCR_AI | DMA2D_BGPFCCR_RBS;% p$ s5 t/ K+ s% E+ B1 e

  31. $ ^& b4 b- u! ^
  32.   if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))& }3 Y, R+ g4 s4 t) p, n. Q7 D) a
  33.   {
    3 q' G* z) ?% G* s
  34.     regValue |= (pLayerCfg->InputAlpha & DMA2D_BGPFCCR_ALPHA);" g* K2 K% y8 e: n& g2 N2 d: l; d
  35.   }, C* q" ]1 `. O4 |6 O4 ^0 z
  36.   else' ^# K8 p: _! o4 x
  37.   {$ ]$ {# i. D# k$ O
  38.     regValue |=  (pLayerCfg->InputAlpha << DMA2D_POSITION_BGPFCCR_ALPHA);, V( Y8 E1 ?9 @5 f  z( ?) o
  39.   }
    5 L7 F' t6 `: o
  40. ( F2 \7 E. V4 v" k
  41.   /* 配置背景层 */& T; p# K; B1 v  w) `
  42.   if(LayerIdx == 0)
    $ @  K6 }9 ]: _6 t' `/ C
  43.   {- m0 N4 I: r3 S3 A. X; O8 m
  44.     /* DMA2D BGPFCCR 寄存器 */7 q6 H4 d6 F5 G, D; x5 a" Q
  45.     MODIFY_REG(hdma2d->Instance->BGPFCCR, regMask, regValue);
    9 \5 g5 h$ h: q3 T& d6 g
  46.   \6 U+ e/ @+ g2 D* X, a- H) y
  47.     /* DMA2D BGOR 寄存器 */  
    # ^- `- d) v; J2 X6 {
  48.     WRITE_REG(hdma2d->Instance->BGOR, pLayerCfg->InputOffset);  G% m) Y0 @8 s6 ^# q* [

  49. ' @) \% \; b7 p. K$ U0 n4 Y
  50.     /* DMA2D BGCOLR 寄存器 */ 7 U1 C  Z' B# Z# B: K" r
  51.     if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))% W) g" w) u+ b7 Y& h
  52.     {   
    6 u' p8 j! t9 P! U! d7 L
  53.       WRITE_REG(hdma2d->Instance->BGCOLR, pLayerCfg->InputAlpha &
    4 l- H- [) o# o, b
  54. (DMA2D_BGCOLR_BLUE|DMA2D_BGCOLR_GREEN|DMA2D_BGCOLR_RED));- T2 T3 W, ?. k
  55.     }   
    7 w8 u5 T2 j' N- K' N
  56.   }( o& K% c8 ^4 h1 h
  57.   /* 配置前景层 */
    2 d* I% R7 g% d, `9 M
  58.   else+ z$ q: B3 d# C- J& E) G* P
  59.   {: H2 d' ~2 L: R1 x9 A, w6 L  a1 D
  60.     if(pLayerCfg->InputColorMode == DMA2D_INPUT_YCBCR)
    5 p3 Y1 s5 y& E: U
  61.     {- v0 t5 U/ t9 j( Q
  62.       regValue |= (pLayerCfg->ChromaSubSampling << DMA2D_POSITION_FGPFCCR_CSS);& J+ O9 h8 G6 H+ u
  63.       regMask  |= DMA2D_FGPFCCR_CSS;$ B2 C4 W! @/ q5 P2 T# D% L
  64.     }
    5 @& y% M. A6 D, w; [2 s

  65. 0 I+ c7 ~' H$ s. E" K9 c
  66.      /* DMA2D FGPFCCR 寄存器 */$ a( b$ }" ^( g& U) J$ p
  67.     MODIFY_REG(hdma2d->Instance->FGPFCCR, regMask, regValue);$ e( P! ]  }7 L1 v( O- {

  68. / a6 `2 ^8 q2 g+ P1 D0 L  s
  69.     /* DMA2D FGOR 寄存器 */" R, i) ~% Z  j/ F4 c  \5 }
  70.     WRITE_REG(hdma2d->Instance->FGOR, pLayerCfg->InputOffset);      9 `. A/ w5 [3 y9 `/ d. B. m- t
  71. " n/ }- w% C# ]! L. E3 V
  72.     /* DMA2D FGCOLR 寄存器 */   / x/ r; Y& U' P( q
  73.     if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))3 ]1 J; c5 `" N3 L8 [
  74.     {7 D9 F) ~8 D# w2 b- C
  75.       WRITE_REG(hdma2d->Instance->FGCOLR, pLayerCfg->InputAlpha &
    9 u9 g( A0 Y# t0 ~- I
  76. (DMA2D_FGCOLR_BLUE|DMA2D_FGCOLR_GREEN|DMA2D_FGCOLR_RED));      
    # j$ \# P/ V2 z6 P4 k
  77.     }   ' J* o5 n8 S: [( N8 q6 B0 x% b
  78.   }   
    . ~7 s" a. N( Y" b9 n$ Y
  79.   /* DMA2D就绪 */6 h0 |' k+ ]) O7 @% }
  80.   hdma2d->State = HAL_DMA2D_STATE_READY;& v. O& |  k* Q5 @7 O) h! O% B
  81. . n3 }0 v- \/ B9 G6 ]
  82.   /* 解锁 */6 r5 C+ i' s# P9 G+ ^8 V" F6 F
  83.   __HAL_UNLOCK(hdma2d);  " N! z* S7 a+ f) r# k
  84. 7 F+ a+ K9 Q# o2 I$ i& P* }
  85.   return HAL_OK;" U- W7 Z  D. G2 j. f$ r$ h; C% C4 f
  86. }
复制代码
* w6 S, q. r, `+ x8 s
函数描述:
& d. a0 P" n0 J
3 J7 S2 j$ I8 A3 m6 ]此函数主要用于配置DMA2D要转换的前景层和背景层,即输入颜色配置。而前面的函数HAL_DMA2D_Init配置的输出颜色。
0 J# p  ]  q/ t7 D- @
. g+ b. ^4 b, x  Z0 S8 }  E函数参数:2 o# L- `% K  z. C
( s$ Z% D) f. E, Y
  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置DMA2D的基本参数,结构体变量成员的详细介绍看本章3.4小节。
# E6 T: Q8 s/ T! a  第2个参数用于配置前景层和背景层,0表示背景层,1表示前景层。
. a# o) J! V/ B  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。7 X' _2 l6 C6 I
使用举例:9 v' @* y6 Z% ]' o# s& I4 @

  1. 1 W, i9 ^3 P: ]# W1 `8 l6 n
  2. DMA2D_HandleTypeDef Dma2dHandle;0 k' F4 T( z  l# K& W$ G5 W! x' m
  3. 9 ~1 A) b0 \! h1 y, z( a

  4. ) A; N" C- `* o+ c8 k; j
  5. /*##-1- 配置DMA工作模式,输出颜色格式和输出偏移 #############*/$ |9 i# }/ ]& |( c) R' {* h
  6. Dma2dHandle.Instance = DMA2D;
    ( ]0 L+ {  Q" f: g

  7. , P* q. `' f7 {
  8. Dma2dHandle.Init.Mode          = DMA2D_M2M;             /* 存储器到存储器模式 */6 e. x9 f# I+ s$ {
  9. Dma2dHandle.Init.ColorMode     = DMA2D_OUTPUT_ARGB4444; /* 输出颜色格式 */  u2 r- K) J/ U. H" A' w) s
  10. Dma2dHandle.Init.OutputOffset  = 0x0;                   /* 无输出偏移 */( A7 l# E& k5 w. Y6 i; E0 R( K
  11. Dma2dHandle.Init.RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输出颜色的R/B通过不切换 */  A  U* C# w% I' s
  12. Dma2dHandle.Init.AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输出颜色的Alpha通道数值不翻转 */
    1 m. ]) O; |) _8 ~8 L8 E
  13. , V4 u- u4 C) ?; N4 d: H  ?  V% E
  14. /*##-2- DMA2D 回调函数配置 ######################################*/
    6 T  i, x5 `7 }% U
  15. Dma2dHandle.XferCpltCallback  = TransferComplete;
    3 ?# C6 g, w: z' L& {2 E
  16. Dma2dHandle.XferErrorCallback = TransferError;
    2 V" O* R' x! d+ e3 U  @& m

  17. 5 ^7 L. F. f) ^* `& S0 R
  18. /*##-3- 前景层配置 ###########################################*/
    - m, Z6 W8 y$ k5 X" d* C) ?
  19. Dma2dHandle.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;      /* 保持输入颜色格式中的Alpha值 */& U* f9 T5 i4 H' O& A1 l7 V
  20. Dma2dHandle.LayerCfg[1].InputAlpha = 0xFF;                     /* 完全不透明 */; S2 m" e) L) h7 f! G
  21. Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB4444; /* 输入颜色格式 */3 H( ~5 W! Y0 r% Z: C+ P0 i
  22. Dma2dHandle.LayerCfg[1].InputOffset = 0x0;                     /* 输入无偏移 */
    3 k% y$ F: a, t5 w+ r4 Q
  23. Dma2dHandle.LayerCfg[1].RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输入颜色的R/B通过不切换*/- O: E/ O7 y9 @; x/ V, P
  24. Dma2dHandle.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输入颜色的Alpha通道数值不翻转*/
    0 K+ ?; r& q* N4 A  {  V8 r% |1 L
  25. . k" S) J9 W/ @
  26. /*##-4- DMA2D 初始化 ###############################################*/
    / F( _1 i/ `8 Q; Q: m9 K
  27. if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)" h' r0 k0 q, p
  28. {6 d  u+ W7 w/ A% w8 f; b1 s" O) K& T
  29.     Error_Handler();5 C1 Y3 D( N; \/ K# @0 X, s
  30. }
    % S: I9 c3 z( ]7 ^$ Y

  31. 3 @# O. D' }; M1 ]; Y0 |
  32. /* 配置前景层  */
    2 [9 \+ o5 O$ V' j; l$ g* x% \9 ^
  33. if(HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1) != HAL_OK); s  {6 N, @3 Z) E# Z
  34. {# @4 E9 c4 Q1 ~  @/ z9 t. P7 S
  35.    Error_Handler();2 M! t! g& B) i( i1 n, u* e7 j/ u
  36. }
复制代码

: Z3 |+ z$ M: @7 d- s5 p
0 _+ t. z3 e. ]% ?55.4.3 函数HAL_DMA2D_Start_IT
& f; |  F, w' X$ p5 ]; S5 ]函数原型:
3 Z4 d3 ?" M; w7 V. P( \! A& c- K0 ~7 P
  1. HAL_StatusTypeDef HAL_DMA2D_Start_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width,  uint32_t Height)4 O: v5 Z  c. `7 l3 C) ^' I7 N
  2. {
    ) r' T  q* M( ~
  3.   /* 检测函数形参 */
    ; }. C! r# z$ i: Z4 a
  4.   assert_param(IS_DMA2D_LINE(Height));% N2 u2 k# G; w) Y# @. `
  5.   assert_param(IS_DMA2D_PIXEL(Width));  u2 A- M( M* k1 u$ o: O

  6. - r. @4 w+ r9 c+ x1 Z+ N+ M  H- E
  7.   /* 上锁 */; w4 S! B7 H7 [4 ~5 e" `
  8.   __HAL_LOCK(hdma2d);6 X- Q% k" \# X" f( _( u0 l

  9. 5 M+ @, O0 z" H# G* N1 T: T" d
  10.   /* 设置DMA2D外设状态 */
    - z( r0 v( c$ K
  11.   hdma2d->State = HAL_DMA2D_STATE_BUSY;
    + A( R* Z2 z+ F- |; `
  12.   E7 K/ g8 M/ e8 Q! S
  13.   /* 设置源地址,目的地址和数据大小 */
    8 k/ R1 y. X6 Y0 E
  14.   DMA2D_SetConfig(hdma2d, pdata, DstAddress, Width, Height);. h8 }; p. l7 u  D6 |: |; j

  15. , b6 H& Y2 B/ o  q/ i2 x( @: m
  16.   /* 使能DMA2D的传输完成中断,传输错误中断和配置错误中断 */# w( c( Q- M* f% H+ _
  17.   __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE);
    / p! A: m# U* [9 I/ T

  18. - `! D& H+ N4 U. U$ r7 E
  19.   /* 使能DMA2D */
    * @0 N8 p1 \' r  o4 j& d
  20.   __HAL_DMA2D_ENABLE(hdma2d);+ e& H* x% Q( x8 t- u* r% L; Y
  21. 5 _$ T! u# h& @  j; O
  22.   return HAL_OK;
    , H: b& m. {2 R& @2 D1 o7 g
  23. }
复制代码

7 X/ p$ U" I8 O函数描述:
( U9 E1 j9 w+ ^: s& l8 q  ^9 i, M2 e/ v& o. r. t$ M" ?; H- \
此函数用于启动DMA2D数据传输。由于采用的中断方式,此函数使能了多个DMA2D中断,不要忘记DMA2D中断服务程序的处理。
" ^! ?0 j" l. ^4 C0 P* f9 `7 f# l4 a1 c+ B: ?+ h. g- Y  o
函数参数:
/ g9 P. U3 o+ f4 |1 T  [" w
+ ?, Y* \8 @6 n1 b. n6 E5 Q7 v  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置DMA2D的基本参数,结构体变量成员的详细介绍看本章3.4小节。3 A* E. X4 S/ a2 c$ _. E
  第2个参数是源数据地址。
0 h! T( b, t, r: F  第3个参数是目的数据地址。
: l; j# C/ Y; H3 y+ X/ U  第4个参数是源数据的长度,即每行的像素个数。
9 `8 {3 ~' X/ u7 M7 U# @3 V  第5个参数是源数据的高度,即行数。3 a% b' z$ t5 Z  C" p
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
  t2 H" }+ [, J/ T使用举例:# ?( k$ ^: o' B& |
2 i8 \/ Y$ R3 }5 t' [0 B
  1. DMA2D_HandleTypeDef Dma2dHandle;
    , @: G6 Q" t) p9 J: x5 j
  2. - ~$ d* ?# a' Q) u+ j
  3. if(HAL_DMA2D_Start_IT(&Dma2dHandle,            /* DMA2D句柄 */
    & n( z$ ^5 m8 N# a
  4.                       (uint32_t)&BufferInput,  /* 源地址 */
    $ M7 x3 g4 B( m, c. U# s
  5.                       (uint32_t)&BufferResult, /* 目的地址 */
    ' i. I/ g* L+ n. ~& o
  6.                       SIZE_X,                  /* 源数据长度,单位像素个数*/# Q  |$ K; h6 {( t
  7.                       SIZE_Y)                  /* 源数据行数 */
    " [6 O$ c4 a( Z9 X  ?# H0 C: p
  8.    != HAL_OK)
    1 m+ I6 B& l% N3 j
  9. {3 s* R3 q5 r; a2 d0 b$ q$ w
  10.    Error_Handler();! Y& P1 r5 @6 Z2 I
  11. }
复制代码
# C! s$ o4 c2 E
55.4.4 函数HAL_DMA2D_BlendingStart_IT% @# I7 |0 `' F# j3 M& V# o6 b
函数原型:
( i1 }4 o" o' z& I& Y2 y* T# h7 g2 C! O+ j/ \0 d" N! z/ \
  1. HAL_StatusTypeDef HAL_DMA2D_BlendingStart_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t SrcAddress1, uint32_t  SrcAddress2, uint32_t DstAddress, uint32_t Width,  uint32_t Height)* B- G% H* i' E
  2. {- d1 D- b8 m; h5 @( ?9 q
  3.   /* 检测参数 */
    $ i' Y! S( t# ^4 u; B9 {) _
  4.   assert_param(IS_DMA2D_LINE(Height));4 X3 V4 U6 ~3 a: c
  5.   assert_param(IS_DMA2D_PIXEL(Width));9 o0 e& a/ x( v7 F
  6. 8 K8 f8 \  F* x0 B) J& f. _
  7.   /* 上锁 */
    & ^2 C0 B! ~& Z/ j  k4 f
  8.   __HAL_LOCK(hdma2d);
      f9 }% s% f3 h5 s2 Z- V) }
  9. ; r  G) s% U$ ^
  10.   /* 设置DMA2D外设状态 */( m- V2 F, P3 {- L7 w$ G7 Z
  11.   hdma2d->State = HAL_DMA2D_STATE_BUSY;* n: \6 d( x4 ]. p2 c* g. J' A. W

  12. 8 F$ y$ `8 d, r0 o
  13.   /* 配置DMA2D源地址2 */
    0 ^% E/ J# o+ F) U/ `. j9 w
  14.   WRITE_REG(hdma2d->Instance->BGMAR, SrcAddress2);0 _$ }+ g7 u3 W) y* G( I

  15. 3 w, U: x! d/ X+ y0 e" O6 _
  16.   /* 配置源地址1,目的地址和数据大小 */
    8 Y6 f' v0 m" K! a7 T+ w
  17.   DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height);
    , I' Z# Y# j* U1 T
  18. 3 T3 p5 W8 d0 x) W* s
  19.   /* 使能DMA2D传输完成中断,传输错误中断和配置错误中断 */
    - Z( S' Z0 N/ p, x
  20.   __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE);
    # K4 |9 h  o  o/ M' P4 T2 K8 l) W

  21. 5 X$ l1 ^' j/ k7 }; W
  22.   /* 使能DMA2D */
    6 |* t1 {5 \, T) ~
  23.   __HAL_DMA2D_ENABLE(hdma2d);8 D) y6 M7 q- ?" G
  24.   Q2 I. L0 q! h. q6 `6 Q
  25.   return HAL_OK;
    ) F, t* O1 w2 X% @& L
  26. }
复制代码
: f4 c- G& G$ R! h+ q
函数描述:  f( J' Q- c+ f" m$ ?, @8 `6 G
* }! D" j7 h7 C$ G; W7 p
此函数用于启动DMA2D传输,除了数据传输以外,还支持颜色格式转换和颜色混合。由于采用的中断方式,此函数使能了多个DMA2D中断,不要忘记DMA2D中断服务程序的处理。( x6 \0 g  S7 e
; }8 ~, k2 P& {8 f/ a6 u
函数参数:
/ g5 S# E& m' T, r5 E' J; f2 ]: O
  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置DMA2D的基本参数,结构体变量成员的详细介绍看本章3.4小节。+ e9 n9 n/ k+ W: u7 l. b
  第2个参数是源数据地址1。5 Z3 C6 l8 M4 x
  第3个参数是源数据地址2。0 s7 X7 a  s6 O, l# |( `& Y4 l
  第4个参数是目的数据地址。3 d8 L$ |$ p4 `+ [1 f; x$ S% [
  第5个参数是源数据的长度,即每行的像素个数。
0 T8 [# S: z1 }0 `/ Q1 b7 ?  第6个参数是源数据的高度,即行数。
6 W/ S0 e0 ]. c; \3 w  b0 |  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
* U5 t) |, w6 `! R8 ?- z8 x使用举例:
& V1 O1 n; s, z" T$ q' Z/ Z/ C9 b; Q1 L$ A' R7 q
  1. DMA2D_HandleTypeDef Dma2dHandle;, }& Q9 d3 W- L, H( b0 `2 }9 o' U

  2. / ]5 ]$ U! i+ ~  w
  3. if(HAL_DMA2D_BlendingStart_IT(&Dma2dHandle,           /* DMA2D句柄 */: q+ I# x; r4 e7 r
  4.                              (uint32_t)&BufferInput1, /* 源地址1,前景色 */
    ( H& a4 H; H: q
  5.                              (uint32_t)&BufferInput2, /* 源地址2,背景色 */
    " \% q0 N0 c1 G1 \! I3 J
  6.                              (uint32_t)&BufferResult, /* 目的地址 */
    ) g& j/ c5 }  `0 x- v' N
  7.                               SIZE_X,                 /* 源数据长度,单位像素个数*/
    . L3 D2 s* E2 R- r- k
  8.                               SIZE_Y)                 /* 源数据行数 */# D0 S1 y  l* K5 c6 x
  9.    != HAL_OK)1 s7 p2 h$ Q# S: @6 w% T
  10. {
    ) \6 L) @+ z- m  _( A2 W$ k
  11.    Error_Handler();. E, M. {* t4 H
  12. }
复制代码

; {) N* ^% R" W* N  x# l, Y  D8 }6 {/ d: b/ s& [4 Y$ t: a) G
55.5 总结
; z, r% ^& _* K0 L本章节就为大家讲解这么多,DMA2D功能比较重要,一定要做到熟练使用。9 G# W/ J0 `# W1 N5 A
% ^$ ~+ M" b$ o5 k! @( \5 H
' s% ^1 s0 |9 a) l% j
* @. D0 U3 t2 }" o2 ?! L
收藏 评论0 发布时间:2021-12-24 17:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版