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

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

[复制链接]
STMCU小助手 发布时间:2021-12-24 17:00
55.1 初学者重要提示# e# |; u) E8 N  z5 g% X
  DMA2D是专门用于LCD加速的,特别是刷单色屏,刷图片,刷Alpah(透明)混合效果全靠它,而且可以大大降低CPU利用率。$ i' B+ _, ~7 L+ z, ~) _+ u7 a
  测评STM32H7的LTDC+DMA2D性能,100Hz以上无压力,刷800*480图片和色块仅需2.6ms一张
6 K0 M  w; `0 }  H7的DMA2D与F429的DMA2D最大区别是支持了ARGB和ABGR互转,而且支持H7的硬解JEPG输出格式YCbCr转RGB,方便LCD显示。
: [" t$ ]) N8 H  特别注意,大家只需对HAL库提供的DMA2D操作API有个了解即可,实际工程中,并不使用这些API,我们需要使用更加高效的寄存器直接操作,在下一章节会为大家说明。1 W0 C) I* a9 ?' y3 }
55.2 DMA2D基础知识
  @3 M, P6 q# _5 Y* uDMA2D主要实现了两个功能,一个是DMA数据传输功能,另一个是2D图形加速功能。
: T; R+ Z) `% o* l  M
. K7 ]9 G: i9 ~7 `& X" N  [  DMA数据传输
% h* u+ G5 T+ h8 w主要是两种方式,一个是寄存器到存储器,另一个是存储器到存储器。通过DMA可以大大降低CPU的利用率。
5 d8 d$ I" _* P! E2 b4 S
* C( I! X; G+ h# G  2D图形加速功能
: C6 y5 l1 t6 w. f支持硬件的颜色格式转换和Alpha混合效果。, \% I( V# @0 s) g  \0 z" s  F
/ N3 p, j* Y8 g% q6 {/ h
55.2.1 DMA2D硬件框图
7 ]! I) K  p5 Y* T+ {9 c$ X  S* n% t: B认识一个外设,最好的方式就是看它的框图,方便我们快速地了解DMA2D的基本功能,然后再看手册了解细节。框图如下所示:% C( {: t+ [$ l& V

8 I7 G& M, v" v* D5 \8 d. a
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
' e. Q& J0 e9 ~; p! Z+ {
9 \5 D  n! ~3 Y* s, k
通过这个框图,我们可以得到如下信息:+ X+ `7 P/ Y" p; x$ B' w3 x* a
+ u; p* l# H* v. C! U* K
  dma2d_aclk9 b! F3 X& x& y1 s
AXI 总线时钟输入。
) ?) a# `' x1 h" `9 m2 K9 a4 S$ u& {% Q! d( a
  dma2d_gbl_it
6 h2 c- [! u4 _DMA2D全局中断输出。
% {7 l; w! {6 f* Q. [$ A$ G& U3 w3 {4 D1 X2 Y  Q
  dma2d_clut_trg- Y6 O7 y; W- J3 K7 I) [
CLUT传输完成信号输出,可以触发MDMA。; |, P0 M% ?8 s' m. l' \

5 i' p0 ~4 |( y6 r1 _! W  dma2d_tc_trg
3 [0 m% u! A7 F. V  [7 c, b传输完成信号输出,可以触发MDMA。3 Z# I/ F. o3 J9 A  ]6 y

& |: q3 w- Y3 F$ Q  dma2d_tw_trg
2 O% x3 j1 x6 D6 U: R- Y传输watermark信号输出,可以触发MDMA。
7 i1 Z' V6 O4 E9 p3 P
; n3 M6 l" y0 q: L0 i) v5 ]将这个硬件框图简化一下,就是下面这样:  v$ [/ h7 q; ~! t$ X3 m: m

" {' c0 r% Z: m. ]
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
/ {$ @) {' h) j+ ]3 j1 b

% l: p' `) y6 `: ^3 |0 ^' y下面按照简化的硬件框图,对每个部分做个说明。0 X1 b$ @# T* ?7 A
( L0 H% g0 J' n
55.2.2 DMA2D工作模式7 q$ i5 }$ Y+ |6 h
DMA2D支持的工作模式如下:
" R0 L+ d: R- w; Z5 f8 g% V& U0 `0 j- I0 E
  模式1:寄存器到存储器模式
; y3 h, V* [5 \- [: E, t+ e5 G这个模式主要用于清屏,也即是将显示屏清为单色效果。
  g2 a) k$ O: {" M& c3 S3 f+ u/ ?4 I! C
  模式2:存储器到存储器模式* O. G& O6 o  q$ J6 S; z/ T/ q
这个模式用于从一个存储器复制一块数据到另一个存储器,比如将摄像头OV7670的输出图像复制到LCD显存就可以采用这种方式。
) ^7 A  y. q( g, D9 V1 a: U0 W, x6 J5 }# b
  模式3:存储器到存储器模式,带颜色格式转换
! |; J- b& x! D这个模式比模式2多了一个颜色格式转换,比如我们要显示一幅RGB888颜色格式的位图到RGB565颜色格式的显示屏,就需要用到这个模式,只需输入端配置为RGB888,输出端配置RGB565即可。位图颜色格式转换后会显示到显示屏上。
% w4 E) Y$ e; d4 c$ O8 }( t. f
" L$ ^% P* l3 S# l2 ?- U, X  模式4:存储器到存储器模式,带颜色格式转换和混合+ N# E1 y+ X3 s) H/ V
这个模式比模式3多了一个混合操作,通过混合,可以将两种效果进行混合显示。7 u+ S1 \& }0 @' T% z

$ h, U4 ~4 M  K3 s# {  模式5:存储器到存储器模式,带颜色格式转换和混合,前景色是固定的, i( [6 C" u4 a. \- Y6 a! j* n
同模式4,只是前景色的颜色值是固定的。  \) X3 V- s  n+ s) F4 b. B
* s+ ~4 L3 d9 ]& M( v1 w
55.2.3 前景层和背景层的输入以及颜色格式转换5 j) T) C0 t; \# N  G
前景层和背景层是指的用户绘制图形时的前景色和背景色,比如我们显示汉字,字体会有一个颜色,也就是前景色,还有一个背景色。又比如我们绘制两幅图片,想将两幅图片混合,那就可以将一幅图片作为前景层,另一个幅图片作为背景层。
: p% `7 W7 _1 z9 l, C
, B* A3 L$ w) n" M  vDMA2D支持的输入颜色格式如下,前景层和背景层一样:' d% ^: M3 ]: ?* @7 I$ Y$ v% W9 N
2 ~0 O& w6 Q$ q' B
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

( S) l2 G  S0 S. [8 H4 z& H; u; p& j/ l3 I# q2 r, g
前8种颜色格式在第50章的第2小节开头有介绍,这里把后四种做个说明:
* p4 @- X  z; i) [: E4 E0 t
/ t/ D3 g1 m0 T# w! T  L4 (4-bit luminance or CLUT)8 {' O8 I) E0 F0 |: o& Q# d
4位颜色格式,实际上仅仅是4位索引值,范围0–15,而每个索引值的具体颜色值在查色表CLUT里面存储。, w- R  g% B0 ]6 [6 x5 p: m
+ A& v  K( C! U* |% q! }
  A4和A8% Q$ ?* n6 m& v- N
A4和A8用于特定的Alpha模式,既不存储颜色信息,也没有索引值。  [) M# a1 f0 f* \1 X3 f6 D- e
. Z, r6 m8 O& ?" q
  YCbCr
% e  U) o5 S$ u( A9 r1 z这个是H7的硬件JPEG输出的颜色格式,后面JPEG章节为大家专门做讲解。5 a9 g$ s) T8 T

9 G6 w) C9 P5 w- I& {- w1 Q这里特别注意一点,输入颜色格式的Alpha值是可以设置的,而且颜色格式里面的R通道和B通道可以交换位置。
. _* y! W4 D4 q
# _0 D( A2 n+ {+ Y$ c& ?- D55.2.4 前景层和背景层混合
$ e0 E3 q, D8 A0 g% h2 ZDMA2D混合器用于混合前景色和背景色,这个功能不需要任何配置,仅需要通过DMA2D_CR寄存器使能即可。混合公式如下:
( q( T1 L1 n# x+ `( x5 [9 v
5 [) P* o4 m) r  G
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

& j6 `" o6 a/ z9 \- G5 F5 T9 L3 K- }+ x
55.2.5 DMA2D输出颜色格式1 ?3 e% b) T7 [) E
DMA2D支持的输出颜色格式如下:" }7 O! Z7 m, l

% X, H8 D( F. e6 v7 V
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

/ X+ K! e7 Q( N
4 M( o- r4 [/ C( n这里特别注意一点,输出颜色格式的Alpha值是可以设置的,而且颜色格式里面的R通道和B通道可以交换位置。6 W2 S! a5 k) C5 p/ j1 Z
  {7 j6 c1 {, \3 u1 t, _5 E# G
55.3 DMA2D的HAL库用法
& |6 J. j2 O% VDMA2D的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断。下面我们逐一展开为大家做个说明。
3 X. ]# ]- @3 d2 [/ e. }1 r6 ?7 p
55.3.1 DMA2D寄存器结构体DMA2D_TypeDef$ w- m  M0 B3 U3 T7 T9 C( w1 ^1 e* |
DMA2D相关的寄存器是通过HAL库中的结构体DMA2D_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:" a) @& H, h+ d$ y# q

7 N$ ~6 P! G$ f/ ?
  1. typedef struct
    6 @: R2 B+ b3 v! `' o# l0 I
  2. {7 G# g9 p5 p8 i. `/ W4 c
  3.   __IO uint32_t CR;            /*!< DMA2D Control Register,                         Address offset: 0x00 */
    ! C6 u  W, @4 T
  4.   __IO uint32_t ISR;           /*!< DMA2D Interrupt Status Register,                Address offset: 0x04 */
    ) g# Y8 C3 T2 [6 H8 u% N- g
  5.   __IO uint32_t IFCR;          /*!< DMA2D Interrupt Flag Clear Register,            Address offset: 0x08 */" E$ o" g2 R! q: ?
  6.   __IO uint32_t FGMAR;         /*!< DMA2D Foreground Memory Address Register,       Address offset: 0x0C *// g% O3 X3 g8 k# ]5 m- C
  7.   __IO uint32_t FGOR;          /*!< DMA2D Foreground Offset Register,               Address offset: 0x10 */
    4 B' e; j: }7 e$ S0 P  V* G; r# o/ B
  8.   __IO uint32_t BGMAR;         /*!< DMA2D Background Memory Address Register,       Address offset: 0x14 */
    * Y( t% i. w: }* A# e% [) K1 M2 f
  9.   __IO uint32_t BGOR;          /*!< DMA2D Background Offset Register,               Address offset: 0x18 */
    , V/ T0 l' t; @% {2 j
  10.   __IO uint32_t FGPFCCR;       /*!< DMA2D Foreground PFC Control Register,          Address offset: 0x1C */
      ^) J+ K% @% G- S
  11.   __IO uint32_t FGCOLR;        /*!< DMA2D Foreground Color Register,                Address offset: 0x20 */
    : S% b/ o4 k1 _: M% Q9 C8 O
  12.   __IO uint32_t BGPFCCR;       /*!< DMA2D Background PFC Control Register,          Address offset: 0x24 */
    7 G7 e* T+ k9 g8 `+ ^8 Y- B- s
  13.   __IO uint32_t BGCOLR;        /*!< DMA2D Background Color Register,                Address offset: 0x28 */0 P, U) ?4 Z& n7 L6 y- l, @1 G
  14.   __IO uint32_t FGCMAR;        /*!< DMA2D Foreground CLUT Memory Address Register,  Address offset: 0x2C */7 T( G3 Z. C- `& r; s+ r! Z
  15.   __IO uint32_t BGCMAR;        /*!< DMA2D Background CLUT Memory Address Register,  Address offset: 0x30 */
    / j2 |; M; N0 g  e# X) i
  16.   __IO uint32_t OPFCCR;        /*!< DMA2D Output PFC Control Register,              Address offset: 0x34 */" P8 f* t1 _2 a) L% B
  17.   __IO uint32_t OCOLR;         /*!< DMA2D Output Color Register,                    Address offset: 0x38 *// q2 q! i# a1 C; r
  18.   __IO uint32_t OMAR;          /*!< DMA2D Output Memory Address Register,           Address offset: 0x3C */
    / Q- G( r% T$ F& v4 h
  19.   __IO uint32_t OOR;           /*!< DMA2D Output Offset Register,                   Address offset: 0x40 */
    $ H% Q$ B' C2 @/ T
  20.   __IO uint32_t NLR;           /*!< DMA2D Number of Line Register,                  Address offset: 0x44 */
    * K; G* |+ N8 m; a( C; S
  21.   __IO uint32_t LWR;           /*!< DMA2D Line Watermark Register,                  Address offset: 0x48 */
    / R; U* O$ I+ q! R$ l9 x/ {& G1 C6 W
  22.   __IO uint32_t AMTCR;         /*!< DMA2D AHB Master Timer Configuration Register,  Address offset: 0x4C */
    & a' q+ W- k; u) C! H9 A( N
  23.   uint32_t      RESERVED[236]; /*!< Reserved, 0x50-0x3FF */  z2 T3 h8 K& Q* x8 v7 T
  24.   __IO uint32_t FGCLUT[256];   /*!< DMA2D Foreground CLUT,                          Address offset:400-7FF */9 @2 p, @5 d4 S  d9 K
  25.   __IO uint32_t BGCLUT[256];   /*!< DMA2D Background CLUT,                          Address offset:800-BFF */
    # E, {0 G! a( H7 E7 v) }9 j9 A
  26. } DMA2D_TypeDef;
复制代码

; i4 L( w8 T- `. L1 l: ^) O+ |# x4 k$ y1 W
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
8 C8 p# _8 V/ N' K
  r' \" ]- _) v# a! `1 ^
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */! w$ U6 q, u: L/ g+ u
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
3 l* _3 D3 [! ~8 m" h, s  I
下面我们再看DMA2D的定义,在stm32h743xx.h文件。
  1. #define PERIPH_BASE              ((uint32_t)0x40000000)
    3 k9 ~, n3 R& D$ Z% B+ V
  2. #define D1_AHB1PERIPH_BASE       (PERIPH_BASE + 0x12000000)
    * D# c' e+ A# k/ z3 F3 G
  3. #define DMA2D_BASE               (D1_AHB1PERIPH_BASE + 0x1000)! V! f* x5 E- S, [7 ]
  4. #define DMA2D                    ((DMA2D_TypeDef *) DMA2D_BASE) <----- 展开这个宏,(DMA2D_TypeDef *) 0x52001000
复制代码
: n5 }3 J- H5 _
我们访问DMA2D的ISR寄存器可以采用这种形式:DMA2D->ISR = 0。
& I, M% n/ t+ |+ z5 }# ~: B9 f  m" S4 v
55.3.2 DMA2D参数初始化结构体DMA2D_InitTypeDef
# d8 D0 h# H  Y" D此结构体用于配置DMA2D的基本参数,具体定义如下:4 C* L: U2 C  M, `$ G' c- A

6 c7 E( [7 F6 c' z, D% a9 f: D6 @0 ^
  1. typedef struct
    & t1 b3 M5 h) D2 y/ [% l4 n9 F
  2. {
    / u5 Q8 X. A& U; Q6 b
  3.   uint32_t             Mode;              2 b2 }9 k% s( _" b
  4.   uint32_t             ColorMode;        
    / G0 X6 R$ R+ [8 O
  5.   uint32_t             OutputOffset;       , ^* @0 w& Y+ q: o! q8 H6 v3 Z7 n
  6.   uint32_t             AlphaInverted;   
    0 K' U( G8 a2 K
  7.   uint32_t             RedBlueSwap;       ) g1 z5 Z7 C# t; _
  8. } DMA2D_InitTypeDef;
复制代码

7 {$ w5 g" A- B% D! [7 `. |下面将这几个参数逐一为大家做个说明:
1 R+ o3 l( c6 r! J- ^+ n' N- i' ]- M9 T9 z, X
  uint32_t   Mode+ c1 A7 [4 W' g0 B3 T
此参数用于设置DMA2D的传输模式,具体支持的参数如下:
3 u$ c# U2 H) H& s8 }, T6 R. `* O" M9 o- u: i  D
  1. #define DMA2D_M2M        ((uint32_t)0x00000000U)  /*存储器到存储传输模式 */6 d# J) c) i& H/ A8 u! B1 U2 a; l
  2. #define DMA2D_M2M_PFC     DMA2D_CR_MODE_0         /*存储器到存储器传输模式,并执行FPC像素格式转 */
    $ N) _2 t7 l! @
  3. #define DMA2D_M2M_BLEND   DMA2D_CR_MODE_1         /* 存储器到存储器模式,并执行像素格式转换和混合 */2 M9 C  b" L4 k  u- L; }( J
  4. #define DMA2D_R2M         DMA2D_CR_MODE           /* 寄存器到存储器传输模式 */; ^( u6 d3 k3 K$ |1 U5 z
复制代码
2 M& N, V, k- r2 w( F% O- D; J6 c% c
, I: @$ J; @/ i* i( k
  uint32_t   ColorMode
8 H3 v& E0 ~9 v6 T+ k此参数用于设置DMA2D的输出颜色格式,具体支持的参数如下:
/ `$ m7 a- X$ j; C: ?( g* }  X: Q6 `* o  }
  1. #define DMA2D_OUTPUT_ARGB8888       ((uint32_t)0x00000000U)               /* ARGB8888 */& @) W4 `0 I6 w+ x$ h. n
  2. #define DMA2D_OUTPUT_RGB888         DMA2D_OPFCCR_CM_0                     /* RGB888 */2 x0 D2 Z- }$ S: g& P
  3. #define DMA2D_OUTPUT_RGB565         DMA2D_OPFCCR_CM_1                     /* RGB565 */
    ) V6 u6 e/ r" I0 v
  4. #define DMA2D_OUTPUT_ARGB1555       (DMA2D_OPFCCR_CM_0|DMA2D_OPFCCR_CM_1) /* ARGB1555 */0 {1 V. x9 N3 `3 t9 ?
  5. #define DMA2D_OUTPUT_ARGB4444       DMA2D_OPFCCR_CM_2                     /* ARGB4444 */. `! T: _9 x& ]+ A$ g
复制代码
: G) c: e1 t/ [1 i

& y, M( b7 p! [5 ~  uint32_t   OutputOffset
/ x! I4 ~2 x* j% @; r此参数用于设置输出位置的偏移值,参数范围0x0000到0x3FFF。
" s! m1 `( J* g( d/ ]5 l* @3 F$ W$ H$ S6 z" A
  uint32_t   AlphaInverted, _8 ?0 P0 {" Z
此参数用于设置DMA2D的输出颜色格式Alpha值反转(即255-原来数值),具体支持的参数如下:     1 O8 D5 t0 @0 z* C
9 z5 S( o& A+ o6 l9 I! Y3 ^
  1. #define DMA2D_REGULAR_ALPHA      ((uint32_t)0x00000000U)  /* 正常输出 */
    ( |9 Q. B# `" h( {4 u; t0 n
  2. #define DMA2D_INVERTED_ALPHA     ((uint32_t)0x00000001U)  /* 反转输出 */
复制代码

* ~+ o4 ?/ _& M& R) }. n  uint32_t   RedBlueSwap
+ Q1 q" D/ o/ l- ~1 X: I8 P此参数用于设置DMA2D的输出颜色格式中R通道和B通道的交换,具体支持的参数如下:% {  P7 a# k  e% b* i
) S  s+ J  J& s: A4 o3 D
  1. #define DMA2D_RB_REGULAR   ((uint32_t)0x00000000U)  /* 不交换(RGB or ARGB) */
    ! u' e9 f$ P" S. ^
  2. #define DMA2D_RB_SWAP      ((uint32_t)0x00000001U)  /* 交换(BGR or ABGR) */
复制代码

/ J8 t# S1 |$ u2 _0 J55.3.3 DMA2D的图层结构体DMA2D_LayerCfgTypeDef( j' i) k! {9 C3 g  }" z* E
此结构体用于配置前景色和背景色。
9 D' o8 e' P( e0 F0 o
/ ~% ]; G7 ?+ T4 r
  1. typedef struct8 K3 @6 j3 P3 I9 ]4 V. c) S, ?8 A$ @
  2. {
      R, |1 E$ F' \
  3.   uint32_t             InputOffset;      
    $ u9 m) H% S( f
  4.   uint32_t             InputColorMode;    9 u+ Y/ H, l3 S, n- g
  5.   uint32_t             AlphaMode;        ( ?* i$ C0 q9 V4 _
  6.   uint32_t             InputAlpha;        
    # C  U2 `9 w! d
  7.   uint32_t             AlphaInverted;    * v* ]* r( x: U+ a4 f
  8.   uint32_t             RedBlueSwap;      
    / W8 r* L- X! U% _
  9.   uint32_t             ChromaSubSampling;9 }* N3 `! ]* {4 ~) R0 ]' M
  10. } DMA2D_LayerCfgTypeDef;
复制代码

- d: H0 m6 p7 T: D5 R下面将这几个参数逐一为大家做个说明。
# b0 Q2 R+ V9 ?$ h7 @, t" t- I- S0 `% w9 l% G
  uint32_t  InputOffset8 N2 g1 _8 v5 u% C6 n: C& {
设置前景色或者背景色的输入偏移,范围0x000到0x3FFF。7 X1 V1 v2 N  C6 w3 ?  q* Q

% V8 j- C- J# a5 K( ^2 j  uint32_t  InputColorMode4 D3 |4 q: H4 C4 q4 L
设置前景色或者背景色的输入颜色格式,具体支持的参数如下:" i8 P* ], @8 Z. z9 Z" H
$ B* g( D+ O8 I/ @
  1. #define DMA2D_INPUT_ARGB8888        ((uint32_t)0x00000000U)  /* ARGB8888 */1 h3 C8 r7 c; R* z$ y
  2. #define DMA2D_INPUT_RGB888          ((uint32_t)0x00000001U)  /* RGB888   */
    5 A: a4 H' _( k
  3. #define DMA2D_INPUT_RGB565          ((uint32_t)0x00000002U)  /* RGB565   */
    . F8 y* s  m3 `* R& p0 d, T4 V
  4. #define DMA2D_INPUT_ARGB1555        ((uint32_t)0x00000003U)  /* ARGB1555 */; p3 d5 D" |0 S) t9 G
  5. #define DMA2D_INPUT_ARGB4444        ((uint32_t)0x00000004U)  /* ARGB4444 */: ~! y; t5 Y# E( f, C, [: \
  6. #define DMA2D_INPUT_L8              ((uint32_t)0x00000005U)  /* L8       */* U5 J- T  d6 y  G# O
  7. #define DMA2D_INPUT_AL44            ((uint32_t)0x00000006U)  /* AL44     */
    & p* ^* u$ X# u0 i( E" |
  8. #define DMA2D_INPUT_AL88            ((uint32_t)0x00000007U)  /* AL88     */
      C! `. p" R1 d
  9. #define DMA2D_INPUT_L4              ((uint32_t)0x00000008U)  /* L4       */4 V$ n3 X# Q: K- R
  10. #define DMA2D_INPUT_A8              ((uint32_t)0x00000009U)  /* A8       */
    ) G6 t# k* h) m$ h* Y" x
  11. #define DMA2D_INPUT_A4              ((uint32_t)0x0000000AU)  /* A4       */
    : m4 S' X" u5 q$ H8 Y
  12. #define DMA2D_INPUT_YCBCR           ((uint32_t)0x0000000BU)  /* YCbCr    */
复制代码
: v- z7 G. b& V( z5 `% ]
  uint32_t AlphaMode- `9 X2 m) J, K
设置前景色或者背景色的Alpha模式,具体支持的参数如下:5 v8 B' Y- [, O9 E! k

4 F4 `4 j1 G' N+ u" b5 h5 q- r
  1. #define DMA2D_NO_MODIF_ALPHA   ((uint32_t)0x00000000U)  /* 不修改Alpha通道值 */
    2 H+ s4 v- d$ ^4 p- F. B
  2. #define DMA2D_REPLACE_ALPHA    ((uint32_t)0x00000001U)  /* 用新设置的Alpha值替换原始Alpha值 */
    7 n( ^6 b* j0 X2 I  f: ?+ U# o
  3. #define DMA2D_COMBINE_ALPHA    ((uint32_t)0x00000002U)  /* 用新设置的Alpha值与原始Alpha值的乘积替换原始Alaha值*/
复制代码
, m/ p1 I- C4 I1 }$ k" q: a
  uint32_t  InputAlpha1 g4 l3 W2 C% x0 L" u
设置前景色或者背景色的Alpha值,范围0x00到0xFF,如果颜色格式是A4或者A8,那么此参数的范围是0x00000000到0xFFFFFFFF,标准的ARGB8888格式。
, U$ q1 W2 x% v9 a) G6 _; J0 P* b9 G$ ^3 n& F# |
  uint32_t AlphaInverted" }5 |" d: o; k/ m* S, W  n! r
设置前景色或者背景色的输入颜色格式Alpha值反转(即255-原来数值),具体支持的参数如下:     
. C9 b- S' H' A" U: _# ]7 ~6 F3 L8 I7 q# s5 L' n& O
  1. #define DMA2D_REGULAR_ALPHA      ((uint32_t)0x00000000U)  /* 正常输出 */8 g( ~1 J: ~. Q# h: e0 w: v! e
  2. #define DMA2D_INVERTED_ALPHA     ((uint32_t)0x00000001U)  /* 反转输出 */     
复制代码
6 m* D$ S" Y6 G( D
  uint32_t   RedBlueSwap* p" c  E( Y2 h! j
设置前景色或者背景色颜色格式中R通道和B通道的交换,具体支持的参数如下:
; o' n2 S( J, A$ H# |
/ h# P' W) g7 x( v- Q  d* [
  1. #define DMA2D_RB_REGULAR   ((uint32_t)0x00000000U)  /* 不交换(RGB or ARGB) */
    ! b; a$ @. V3 h
  2. #define DMA2D_RB_SWAP      ((uint32_t)0x00000001U)  /* 交换(BGR or ABGR) */
复制代码
8 [+ U0 z, z6 F# Y
  uint32_t   ChromaSubSampling
% o- M8 s0 }( _6 }/ a/ z设置前景色或者背景色中YCbCr 颜色模式的采样格式,具体支持的参数如下:
  1. #define DMA2D_NO_CSS               ((uint32_t)0x00000000)  /* 4:4:4 */8 |* y/ n+ {! J) B! p; \3 B0 U
  2. #define DMA2D_CSS_422              ((uint32_t)0x00000001)  /* 4:2:2 */( R, n& f8 Z, ^, Z% ]/ r* [3 e
  3. #define DMA2D_CSS_420              ((uint32_t)0x00000002)  /* 4:2:0 */  
复制代码
1 ]; R% n  f9 [  m; ^  W! \
55.3.4 DMA2D句柄结构体DMA2D_HandleTypeDef
$ I* _3 S. E% [/ i
HAL库在DMA2D_TypeDef, DMA2D_InitTypeDef和DMA2D_LayerCfgTypeDef的基础上封装了一个结构体DMA2D_HandleTypeDef,定义如下:4 f, p/ S; ?6 S8 J" b
& y8 ?: A1 I1 n4 q5 d
  1. typedef struct __DMA2D_HandleTypeDef  Y8 @$ @0 M: }5 m2 n( _: ]$ }
  2. {
    " X2 |! g9 ?0 O
  3.   DMA2D_TypeDef               *Instance;                                                                                                                                                                                          
    ' S2 \* B, @; m3 Y
  4.   DMA2D_InitTypeDef           Init;                                                        
    2 g6 H4 q, f( b/ E, y& `& i
  5.   void                        (* XferCpltCallback)(struct __DMA2D_HandleTypeDef * hdma2d);                                                                                                                                             
    5 s# W, {5 y6 M' q
  6.   void                        (* XferErrorCallback)(struct __DMA2D_HandleTypeDef * hdma2d);                                                                                      / u' T9 ~4 O2 {8 |  y3 I
  7.   DMA2D_LayerCfgTypeDef       LayerCfg[MAX_DMA2D_LAYER];                                    
    : F7 O2 s5 N8 {0 O
  8.   HAL_LockTypeDef             Lock;                                                                                                                                                                                                   
    8 C: j) {% A6 H- ~! l& d/ R
  9.   __IO HAL_DMA2D_StateTypeDef State;                                                                                                                                                                                                   
    * p+ [* b9 K0 B: R: t1 e
  10.   __IO uint32_t               ErrorCode;                                                   } DMA2D_HandleTypeDef;
    $ k8 u1 @# U: A* Q4 x7 r
复制代码

; A2 z, [. n: [2 @下面将这几个参数逐一做个说明。
% Q( ]9 w. B' x% i4 [/ ?: M  q) \: K5 L; i3 I0 ?8 E
  DMA2D_TypeDef  *Instance  y, [* A4 O6 Z  R) H1 j
这个参数是寄存器的例化,方便操作寄存器,详见本章3.1小节。) n4 i  @# \8 ^# D4 h
& L$ q! b' Q+ j' j
  DMA2D_InitTypeDef  Init;  ' W; x% Q: U$ L. m  H8 }) D& O
这个参数是用户接触较多的,用于配置DMA2D的基本参数,详见本章3.2小节。
1 q) \+ c- x( b* j% }! c2 Y
, Q3 ~( o/ \# y% D  void     (* XferCpltCallback)(struct __DMA2D_HandleTypeDef * hdma2d);4 r# ?4 P5 p& [* d1 |$ I  F0 I) |% `
  void     (* XferErrorCallback)(struct __DMA2D_HandleTypeDef * hdma2d);% P% Y& o- ]9 C! _: a& |) f4 X
DMA2D中断服务程序里面执行的回调函数,一个是传输完成回调,另一个是传输错误回调。
. f( ]; J5 ?6 o! z0 ~0 z8 }/ `/ b( P/ I- N
  DMA2D_LayerCfgTypeDef   LayerCfg[MAX_DMA2D_LAYER]+ Q' P# t! E8 m. O9 d
这个参数用于前景色和背景色的设置,MAX_DMA2D_LAYER=2,详见本章3.3小节。) U3 @! u5 _+ f' h
1 ^/ H# x) W% Z
  HAL_LockTypeDef   Lock
4 s# N) p& @2 Y: V9 L- Q__IO uint32_t    State;3 }& R) p$ e' t, j, W% g& t; q5 m
1 V0 B6 M9 I6 e" W; s
__IO uint32_t    ErrorCode: i& ?$ A5 @" F  h7 J

7 j& W& {- _! A0 p7 x这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DMA2D通信状态,而ErrorCode用于配置代码错误。
  p' v7 \/ E' J- m, e4 v
* _0 \+ \3 [! }5 ^+ _55.3.5 DMA2D初始化流程总结
* M8 T, u+ J9 |) D( n
对于DMA2D来说,其实不需要初始化流程,每个功能都可以直接封装出一个函数来,下个章节会为大家专门讲解,也是实际项目比较推荐的方式。* O; o$ p4 i* `  f4 d$ C1 @
3 g0 b3 L3 q5 d7 k
55.4 源文件stm32h7xx_hal_dma2d.c
7 N0 l7 D- D2 D8 q这里把我们把如下几个常用到的函数做个说明:8 _+ I3 e$ J; N" A+ Y( v: g7 w
; e; F, h" f) r! E) E
  HAL_DMA2D_Init5 E3 f/ {: t1 [7 B2 u( e3 F4 b0 Y
  HAL_DMA2D_ConfigLayer- ?: b2 A7 i" s0 q3 V9 x
  HAL_DMA2D_Start_IT
( m$ [. ~6 K7 U1 F" C; x  HAL_DMA2D_BlendingStart_IT
  K* b: X5 P4 @% M5 P
; w0 p" J. f- W1 w, z+ _55.4.1 函数HAL_DMA2D_Init
- w9 b3 F" A8 e: K! x4 x, O函数原型:3 \4 |6 H% A7 U, ~! h6 v4 R

2 a% N0 f6 j$ J/ ~; X9 x5 j
  1. HAL_StatusTypeDef HAL_DMA2D_Init(DMA2D_HandleTypeDef *hdma2d)
    4 V0 K; y* n5 S$ s
  2. {
    0 p- p- {2 ]4 p0 m7 j! {
  3. 9 W6 |5 \; c7 H9 N
  4. /*  检测参数是否有效 */
    " f$ G* U8 k, |: L" V2 }# w
  5.   if(hdma2d == NULL)
    - K; K. ~8 ?- I# O( u& C4 g
  6.   {  a$ @1 w9 c: j/ C0 y& A8 Z1 n5 `
  7.      return HAL_ERROR;
    # @2 U, e, u- |2 k
  8.   }
    # p7 d5 i0 Y6 R3 p* v
  9. : r$ c; k& @8 F/ I  r6 m5 N  ^& r7 n* l7 O! E
  10.   /* 检测函数形参 */' O: g& B3 t; G! l$ `3 ~) U: O
  11.   assert_param(IS_DMA2D_ALL_INSTANCE(hdma2d->Instance));
      ]2 @" S0 n8 }" _
  12.   assert_param(IS_DMA2D_MODE(hdma2d->Init.Mode));; P! T$ I- b/ f+ T, O! d4 l
  13.   assert_param(IS_DMA2D_CMODE(hdma2d->Init.ColorMode));
    1 [# R/ h/ N5 N/ ]+ m7 ~% ?& ?( g
  14.   assert_param(IS_DMA2D_OFFSET(hdma2d->Init.OutputOffset));7 \8 `7 D  X5 |6 T3 E, O: K  w5 S

  15. ) G- [; Q2 G- ]; s. H9 A
  16.   if(hdma2d->State == HAL_DMA2D_STATE_RESET)
    0 H3 W  R2 y+ U  u
  17.   {- z  [. O; e+ N) Z$ \# C# {
  18.     hdma2d->Lock = HAL_UNLOCKED;9 Q2 V5 P* N5 @, R3 b2 J
  19.     /* 初始化GPIO,NVIC等 */
    & u6 Z; ]9 @; ]9 p
  20.     HAL_DMA2D_MspInit(hdma2d);
    - y! t1 [7 g/ y5 R( L5 P
  21.   }* M$ u8 X1 y! i
  22. 7 A3 H7 Q7 d, W+ w/ r' K
  23.   /* 设置DAM2D外设状态 */
    # ]. X4 I- b$ V" _
  24.   hdma2d->State = HAL_DMA2D_STATE_BUSY;  " n! Z! u6 ?/ @

  25.   t5 a, h7 g% n
  26.   /* 设置DAM2D工作模式 -------------------------------------------*/8 }1 M- \# x; [% I: M+ B9 k
  27.   MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_MODE, hdma2d->Init.Mode);4 Y7 G2 ^1 z- D, N! `3 b
  28. 9 F; V7 {& X) u6 A
  29.   /* 设置输出颜色格式 ---------------------------------------*/
    : N! t- q* R0 M2 {9 T( _' j
  30.   MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_CM, hdma2d->Init.ColorMode);6 `) s! ?4 G! i' ?9 v+ g, c: @
  31. / N: s" L. M) S. k; }( N+ m
  32.   /* 设置输出偏移 ------------------------------------------*/  9 W, b2 u0 N) R+ }# J3 U
  33.   MODIFY_REG(hdma2d->Instance->OOR, DMA2D_OOR_LO, hdma2d->Init.OutputOffset);  1 R9 r2 T: V$ M3 x, ^5 _7 e4 k( k0 Y
  34.   u  P+ @7 T6 t+ [# X3 F6 i
  35.   /* 设置输出颜色格式中的Alpah值反转 */( r* g- |3 U9 r8 L( F- T( L5 w
  36.   MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_AI, (hdma2d->Init.AlphaInverted << DMA2D_POSITION_OPFCCR_AI));; \- `7 N& ?- O) r- h: V
  37. : @, T& C3 o. b, ^1 ?: A( @
  38.   MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_RBS,(hdma2d->Init.RedBlueSwap << DMA2D_POSITION_OPFCCR_RBS));: M2 [5 _' u. ^8 T9 J5 l' x
  39. & s+ G2 r( c. O- }0 ^

  40. 6 |( s: h/ k: q+ ]8 r9 F- K
  41.   /* 无错误 */& Y1 u& ^. L  @! z  B+ ^
  42.   hdma2d->ErrorCode = HAL_DMA2D_ERROR_NONE;- X6 f- S& C5 i
  43. * Q; k0 `1 [8 D2 Q& V
  44.   /* DAM2D就绪 */3 l3 b: N! E$ i2 u) Q0 C# H4 \
  45.   hdma2d->State  = HAL_DMA2D_STATE_READY;" n5 r! S" z+ X+ b: I6 E
  46. 3 f8 A7 ?1 S1 Y2 n
  47.   return HAL_OK;, Y! ]: J7 o& }6 @! j
  48. }
复制代码
2 W7 S. o$ S" Q, y8 q
函数描述:! M4 h0 ^% [/ J
4 q" W* }4 X  G: A3 B, x
此函数用于初始化DMA2D的工作模式和输出颜色格式。5 J! ^: }- c% |, [6 l% o9 z: q
+ x0 P7 k1 E4 w9 Z
函数参数:. W0 [3 a- L- X+ F9 A, X$ R
* Z" h, o$ T# @0 U8 N$ J9 j
  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。5 Q3 A% P$ J* T2 r0 K" T
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。% }. r0 o- t) b$ r7 c( o: @
注意事项:
' I0 ?2 R' y6 j$ F+ p; |8 H% _: z( _. M1 q, f
函数HAL_DMA2D_MspInit用于初始化DMA2D的底层时钟、NVIC等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。# l4 o0 a3 i2 T
如果形参hdma2d的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量DMA2D_HandleTypeDef Dma2dHandle。) E: l; s7 i& V) i; p& X  Q2 u
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_DMA2D_STATE_RESET  = 0x00U。
6 R# U. z* l0 ~# K1 Q: \( P* \9 t! P+ o  x+ j
解决办法有三
" \' _3 J" |4 \2 B' Q& Y
. J: [* _+ ]; K$ @方法1:用户自己初始DMA2D底层。/ X0 p6 A( G1 P1 O

" X% P: _4 C; W6 x方法2:定义DMA2D_HandleTypeDef LtdcHandle为全局变量。+ m" }+ A! Z2 ~" b, Q) @
9 b4 k9 v1 H' `4 L8 w) q, i
方法3:下面的方法
  1. if(HAL_DMA2D_DeInit(&Dma2dHandle) != HAL_OK)
    3 Z& w' `6 |; X7 M* b0 h# ]9 Y: ]
  2. {
    $ {" b( k$ ~& g0 `- P
  3.     Error_Handler();' P! w2 ^; s# R6 A0 {* C$ o2 `
  4. }  ' l7 Q) f# r6 P# `
  5. if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)
    # ?6 m1 n$ f5 d! H! h
  6. {
    ! B( Y4 _: w5 J, U. I6 s* z
  7.     Error_Handler();
    ( B" {6 L7 n8 ]0 O3 @4 f1 D
  8. }
复制代码
8 k$ t+ ^+ s! q
) L1 e6 o) {0 j' d* h
使用举例:# {( P6 g* @9 G0 P0 n
! l( h$ G# G/ M6 f/ B$ w
  1. DMA2D_HandleTypeDef Dma2dHandle;' T" Y  x2 [8 r" ?5 J% N
  2.   H6 \! G7 h- y  t7 X$ f6 {
  3. /*##-1- 配置DMA工作模式,输出颜色格式和输出偏移 #############*/
    7 y( |& h* w% O
  4. Dma2dHandle.Instance = DMA2D;7 d: K* ~3 E' A+ [1 K

  5. # Q4 N  V( u  K2 `2 P
  6. Dma2dHandle.Init.Mode          = DMA2D_M2M;             /* 存储器到存储器模式 */3 Y. A5 L% c% Y3 V/ L& E, x
  7. Dma2dHandle.Init.ColorMode     = DMA2D_OUTPUT_ARGB4444; /* 输出颜色格式 */  C6 k9 b$ d! B3 p; p; G
  8. Dma2dHandle.Init.OutputOffset  = 0x0;                   /* 无输出偏移 */9 k! A  p* i" v$ N
  9. Dma2dHandle.Init.RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输出颜色的R/B通过不切换 */5 ~: K* r* w: v8 K
  10. Dma2dHandle.Init.AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输出颜色的Alpha通道数值不翻转 */
    * e4 }& s! M  t* l- C
  11. $ J3 P  g7 U; A3 @2 |
  12. /*##-2- DMA2D 回调函数配置 ######################################*/: X* O9 A" D7 w3 j* P
  13. Dma2dHandle.XferCpltCallback  = TransferComplete;# C' t+ d  `) l. H7 H$ m
  14. Dma2dHandle.XferErrorCallback = TransferError;5 j" d# s3 a' Y
  15. ! y+ q9 w/ y& q) _* z$ x5 F) p9 s) [
  16. /*##-3- 前景层配置 ###########################################*/% K7 Y( o" w5 j0 h' \
  17. Dma2dHandle.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;      /* 保持输入颜色格式中的Alpha值 */
    - e) S& a! d% ?6 [6 U$ _2 V# K
  18. Dma2dHandle.LayerCfg[1].InputAlpha = 0xFF;                     /* 完全不透明 */
    . _( j  ~" \, e
  19. Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB4444; /* 输入颜色格式 */
    * Y( T6 c9 w7 _' x- ?# U; I
  20. Dma2dHandle.LayerCfg[1].InputOffset = 0x0;                     /* 输入无偏移 */! S0 [: K9 s. b7 r+ V* _
  21. Dma2dHandle.LayerCfg[1].RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输入颜色的R/B通过不切换*/
    # F; `1 h* o$ R2 l* q
  22. Dma2dHandle.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输入颜色的Alpha通道数值不翻转*/3 }: J1 S0 T4 D1 p9 r- F

  23. 3 R2 u2 M' }1 a) |& e/ g

  24. ; D; n* ~6 V9 J0 x. e
  25. /*##-4- DMA2D 初始化 ###############################################*/
    " G% s  Q. ~8 f) h, p- n
  26. if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)$ {3 y2 o+ ^! \) S; C' s5 t2 q. x
  27. {& d" I. i# N- O$ [8 `
  28.     Error_Handler();! }4 a) D6 v4 Z
  29. }
复制代码

1 t& O) p, S; U8 y# D* u+ F55.4.2 函数HAL_DMA2D_ConfigLayer
. q/ D1 `) A3 b* `5 ~函数原型:
, Q  l) ?6 }) c) h, y, d$ _, e& @- t1 V7 d5 z
  1. HAL_StatusTypeDef HAL_DMA2D_ConfigLayer(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx)8 g1 g* l4 e' Y( u. J$ {% ^0 L
  2. {
    3 |- z$ j& W* q$ t2 d/ U; P) e' t5 k
  3.   DMA2D_LayerCfgTypeDef *pLayerCfg = &hdma2d->LayerCfg[LayerIdx];
    + _5 I8 s5 @( @  B3 E3 ]

  4. : s- C9 ~7 X5 X
  5.   uint32_t regMask = 0, regValue = 0;& g& J! `$ f3 G9 h; Y2 @( a
  6. 9 E$ a6 u5 F- f0 m( B
  7.   /* 检查参数 */1 O$ H& M  |/ L' _
  8.   assert_param(IS_DMA2D_LAYER(LayerIdx));  
      ~3 J6 w7 I% H+ j
  9.   assert_param(IS_DMA2D_OFFSET(pLayerCfg->InputOffset));  
    5 p; j. q4 ]+ [; t. j& P6 W
  10.   if(hdma2d->Init.Mode != DMA2D_R2M)
    ( `; T# D* V$ Z: f! q) l* Q
  11.   {  & m5 Y/ u) I) n8 S) e4 h' }/ d$ V& }
  12.     assert_param(IS_DMA2D_INPUT_COLOR_MODE(pLayerCfg->InputColorMode));5 \- W8 g/ ^2 B
  13.     if(hdma2d->Init.Mode != DMA2D_M2M)4 W) ?! C+ U' t  ], a
  14.     {
    ) H: ^* ?. i+ O/ w" e
  15.       assert_param(IS_DMA2D_ALPHA_MODE(pLayerCfg->AlphaMode));
    ) q+ o4 M0 X+ D! I! ?, P
  16.     }! s6 G. `1 E; K9 ^1 A' Z- o6 V
  17.   }) c4 Y! p( ]& J& m6 f# K5 y* E8 ~3 C
  18. " b$ b0 N5 T- V1 x# y% X+ s
  19.   /* 上锁 */
    ( u4 g' ^& V6 l9 z) u6 W
  20.   __HAL_LOCK(hdma2d);- v; u/ m. p: R$ p' r
  21. 9 h) h; N4 F! |$ ^
  22.   /* 设置DMA2D外设状态 */9 b4 ^" g6 g. D
  23.   hdma2d->State = HAL_DMA2D_STATE_BUSY;  ( f& [5 d9 M4 K6 ]2 E
  24. : Y7 P6 L$ H3 t" l0 U
  25.   /* 准备好背景层或者前景层FPC寄存器配置参数*/: _$ r9 \. o$ B0 Z" O
  26.   regValue = pLayerCfg->InputColorMode | (pLayerCfg->AlphaMode << DMA2D_POSITION_BGPFCCR_AM) | \
    + @) `  H4 i, D' ]" E% Y
  27.             (pLayerCfg->AlphaInverted << DMA2D_POSITION_BGPFCCR_AI) | \% C! q2 n0 E. U
  28.             (pLayerCfg->RedBlueSwap << DMA2D_POSITION_BGPFCCR_RBS);6 [4 l0 R( h7 x% ?6 f6 ]

  29. 6 {( ~; R- `* M
  30.   regMask  = DMA2D_BGPFCCR_CM | DMA2D_BGPFCCR_AM | DMA2D_BGPFCCR_ALPHA | DMA2D_BGPFCCR_AI | DMA2D_BGPFCCR_RBS;
    : Y1 e. z, w' Z& B9 [- E
  31. " Z  o* J, a8 u* u* V5 ]- N( v7 R
  32.   if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))
    / h& N/ S2 V5 G$ {
  33.   {1 t& d1 g; m# `9 O- ^& b
  34.     regValue |= (pLayerCfg->InputAlpha & DMA2D_BGPFCCR_ALPHA);$ D& j2 n3 s  C$ ^
  35.   }
    3 X/ B2 y/ T' O8 o
  36.   else# }' T- U) {1 y" Y( A( [
  37.   {
    8 K: _6 y! U. O- p& z
  38.     regValue |=  (pLayerCfg->InputAlpha << DMA2D_POSITION_BGPFCCR_ALPHA);
    + Q! _5 p1 V% u3 A% n- m
  39.   }
    ) ?  _; Z1 P, {3 a& m) A

  40.   s& v! E8 E% {' Z
  41.   /* 配置背景层 */
    8 @; f1 o4 g6 i7 b
  42.   if(LayerIdx == 0)
    9 t( l7 k) f8 I
  43.   {+ z" [/ ]* ]6 p
  44.     /* DMA2D BGPFCCR 寄存器 */, m; {; f! O8 G4 v
  45.     MODIFY_REG(hdma2d->Instance->BGPFCCR, regMask, regValue);
    1 h; h! c; ^. j/ U

  46. 0 e* {7 }* R" P
  47.     /* DMA2D BGOR 寄存器 */  3 v' p. A9 V: j  z) R) R& N
  48.     WRITE_REG(hdma2d->Instance->BGOR, pLayerCfg->InputOffset);
    9 f( C" e! L8 t2 T2 ?
  49. 2 L$ H1 w% V4 V+ L# ~( Y& C% e. @
  50.     /* DMA2D BGCOLR 寄存器 */ 1 B5 J7 X" P3 g; l- H* G
  51.     if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))7 g; T8 }/ n  G: ~2 k  t
  52.     {    ( h6 D( `; \+ f6 |
  53.       WRITE_REG(hdma2d->Instance->BGCOLR, pLayerCfg->InputAlpha & 1 J8 i& Z1 r4 e
  54. (DMA2D_BGCOLR_BLUE|DMA2D_BGCOLR_GREEN|DMA2D_BGCOLR_RED));' a# N1 J. G% J% d3 N# t
  55.     }   
    ; Z. P+ `' Q" C# u& e) A
  56.   }$ c( ?4 g, T6 x
  57.   /* 配置前景层 */
    ' m6 ]9 ]7 m2 o8 P; k, a* f
  58.   else! J# i+ K) y' A( A! x4 ?1 @
  59.   {& \1 R! y7 M3 p
  60.     if(pLayerCfg->InputColorMode == DMA2D_INPUT_YCBCR)
    ' U" e1 B% z5 [
  61.     {
    ' O1 }' L) A( R$ P8 g
  62.       regValue |= (pLayerCfg->ChromaSubSampling << DMA2D_POSITION_FGPFCCR_CSS);0 L- N+ M$ I3 Y6 [( [/ ]
  63.       regMask  |= DMA2D_FGPFCCR_CSS;) S, S$ @, {. H% J$ [
  64.     }
    / a) _# q) R- D1 q

  65. " y% d6 J; q8 @, A4 K$ M" B& z
  66.      /* DMA2D FGPFCCR 寄存器 */$ ~5 h9 y( E# @9 g! k$ G* ~
  67.     MODIFY_REG(hdma2d->Instance->FGPFCCR, regMask, regValue);1 @( v7 Q  L3 N+ Q/ Z4 n9 c* ?

  68. * ^6 e( A7 r6 P" U
  69.     /* DMA2D FGOR 寄存器 */
      u) p9 S( ?3 m  d4 q, a
  70.     WRITE_REG(hdma2d->Instance->FGOR, pLayerCfg->InputOffset);      
      o9 V8 t2 g0 Q0 l- S& K, r2 N
  71. 0 w. G3 q: m2 g9 m
  72.     /* DMA2D FGCOLR 寄存器 */   ! i: f' C( X9 d3 r6 v) C) ^0 o: K( ^
  73.     if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))) |  k: ^( _- X& w0 |% ~; T
  74.     {: N2 \1 {  Z) v& }. x
  75.       WRITE_REG(hdma2d->Instance->FGCOLR, pLayerCfg->InputAlpha &
    ! o% [' A7 |6 p7 m
  76. (DMA2D_FGCOLR_BLUE|DMA2D_FGCOLR_GREEN|DMA2D_FGCOLR_RED));      1 t* E; S. s, [: Y' r3 E
  77.     }   ( {9 G" g- T8 f+ l: ^! h
  78.   }   3 k: t& T+ A. j; n: e8 _$ T2 {3 _
  79.   /* DMA2D就绪 */
    / Y" Q0 n9 \( ?  g4 w7 p) k# H( g  N
  80.   hdma2d->State = HAL_DMA2D_STATE_READY;
    & V% M* h5 F) ^4 d* I7 e

  81. # C9 M- `: [& `9 q5 b5 y
  82.   /* 解锁 */
    5 ]5 H! T! y0 I" m% T  s" ?
  83.   __HAL_UNLOCK(hdma2d);  
    8 g' u6 h  M% K+ m/ C( i
  84. # c' B2 X: B1 B
  85.   return HAL_OK;* C; e  I# G+ M# h5 r) ]
  86. }
复制代码
' o( C, y7 X- ^) w8 y8 G
函数描述:* T/ L6 D+ q3 d/ Y/ N
0 S& s9 z$ s/ G0 o" `% u
此函数主要用于配置DMA2D要转换的前景层和背景层,即输入颜色配置。而前面的函数HAL_DMA2D_Init配置的输出颜色。
5 J& Y4 }1 H1 x! o, \- ~. E% D& W, C. c, j2 `* f
函数参数:
5 T5 ]5 ~/ w; w3 [
2 u7 `0 R) D; A& V7 h$ e4 V4 ^  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置DMA2D的基本参数,结构体变量成员的详细介绍看本章3.4小节。
3 d7 Y4 i( G# P$ s/ e  第2个参数用于配置前景层和背景层,0表示背景层,1表示前景层。
+ D1 n3 O, E" c1 X- {7 U  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。. _+ f& ?9 U* Y; u: f
使用举例:
* M9 w! n$ {2 h" \. R+ O. i
  1. ) b7 E+ w0 K% @
  2. DMA2D_HandleTypeDef Dma2dHandle;
    1 D7 B+ U4 }  c4 F' Z' z0 L

  3. - r1 z7 C! e: [5 b

  4. 0 m- n9 F1 s: r7 Z) }4 W3 v" v( u/ |* P
  5. /*##-1- 配置DMA工作模式,输出颜色格式和输出偏移 #############*/8 w1 T/ r2 g) x& k! F
  6. Dma2dHandle.Instance = DMA2D;, m: Q# `$ ?: P9 n4 h9 P. e3 ^
  7. & G4 k1 p( ]  a* ~. q* q
  8. Dma2dHandle.Init.Mode          = DMA2D_M2M;             /* 存储器到存储器模式 */
      E3 z  @4 ~: A  \  x
  9. Dma2dHandle.Init.ColorMode     = DMA2D_OUTPUT_ARGB4444; /* 输出颜色格式 */4 f3 R! P. b2 k+ s" @5 d; b) x7 C
  10. Dma2dHandle.Init.OutputOffset  = 0x0;                   /* 无输出偏移 */
    ) j6 a- a& x; `+ t
  11. Dma2dHandle.Init.RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输出颜色的R/B通过不切换 */' `( k/ S- H8 c3 ?8 M4 I1 u6 ^
  12. Dma2dHandle.Init.AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输出颜色的Alpha通道数值不翻转 */- W+ c9 N. N2 ^+ P; o7 b. z
  13. ! {2 m: h9 S- K2 f4 X, a2 @' `
  14. /*##-2- DMA2D 回调函数配置 ######################################*/& Q* k( A/ N7 J
  15. Dma2dHandle.XferCpltCallback  = TransferComplete;" F% g4 Y( ^& a; \! p6 ]% l
  16. Dma2dHandle.XferErrorCallback = TransferError;
    ! q. d. P" r/ Y+ p5 C# [$ I$ {
  17. - C- I; Z% e4 _4 h9 B( _" Z0 C
  18. /*##-3- 前景层配置 ###########################################*/! ^! E& e# k  W% `
  19. Dma2dHandle.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;      /* 保持输入颜色格式中的Alpha值 */
    ! g! e9 k! z+ v$ a2 m- ~' Z
  20. Dma2dHandle.LayerCfg[1].InputAlpha = 0xFF;                     /* 完全不透明 */) @' g7 w: Y, g, O
  21. Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB4444; /* 输入颜色格式 */
    ! S7 Z, w( O/ Z; p
  22. Dma2dHandle.LayerCfg[1].InputOffset = 0x0;                     /* 输入无偏移 */
    8 L0 q0 d) Q+ h8 _
  23. Dma2dHandle.LayerCfg[1].RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输入颜色的R/B通过不切换*/, E" Z8 K: l! d5 C' ?* @' U
  24. Dma2dHandle.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输入颜色的Alpha通道数值不翻转*/- \5 x2 I4 O* A: J5 }! R7 Y# D, r, [

  25. " r/ W3 n/ B3 X1 f; n% a
  26. /*##-4- DMA2D 初始化 ###############################################*/
    ; l: Q9 F4 f! B4 I/ }
  27. if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)
    & N+ Z" Q( Y0 l2 Q( m
  28. {& V: R8 S+ H2 H0 j5 S  D
  29.     Error_Handler();3 C2 s- ?* \  x( }
  30. }
    2 j; F; j' F7 m% X" M

  31. ) e5 `! m1 n* h* ?2 s
  32. /* 配置前景层  */- u! ?( W- Y  ~- M
  33. if(HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1) != HAL_OK)9 h- y/ j8 \: Q+ q- s
  34. {$ s' k6 R& R+ D
  35.    Error_Handler();0 l$ k5 l  P9 a1 q
  36. }
复制代码

7 s( ~6 |  ]- R0 P4 P1 x9 @, ?2 F3 i3 g7 t  K  s- C' G
55.4.3 函数HAL_DMA2D_Start_IT
: J8 x* T; ?7 F. d函数原型:- t; f% M  [0 x$ `) a/ V( n" r

$ z$ Z& @' }9 F
  1. HAL_StatusTypeDef HAL_DMA2D_Start_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width,  uint32_t Height)
    ) I% v/ S) ?( M; \) Q; N; J
  2. {
    # ^( ?; W" n2 H
  3.   /* 检测函数形参 */
    * O  g. l; L% m: X4 \2 D
  4.   assert_param(IS_DMA2D_LINE(Height));
    + h3 Q/ n1 N  |3 T9 X& H
  5.   assert_param(IS_DMA2D_PIXEL(Width));( M2 m, `% f8 e8 M# p7 K
  6.   H5 z1 G  K4 F% Y8 n
  7.   /* 上锁 */2 w; F, S8 ?- x5 K& F
  8.   __HAL_LOCK(hdma2d);" N0 w6 H+ b$ v5 l& s1 N

  9. 0 W5 b) V: t4 r
  10.   /* 设置DMA2D外设状态 */" Y6 G' J. o* z8 J
  11.   hdma2d->State = HAL_DMA2D_STATE_BUSY;
    3 c9 T" _3 o- Z5 B0 g0 r  o
  12. / A. L0 w* k# @
  13.   /* 设置源地址,目的地址和数据大小 */
    6 K. F$ J" a2 Q8 S- [- m  s  V2 V' `
  14.   DMA2D_SetConfig(hdma2d, pdata, DstAddress, Width, Height);0 I1 ^& B, M+ n

  15. # t8 P5 X5 I+ ~5 W
  16.   /* 使能DMA2D的传输完成中断,传输错误中断和配置错误中断 */
    : Z" |! R9 V0 H/ F9 A
  17.   __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE);
    # `! E  D7 s' t/ N) @0 G6 s
  18. ' n5 u+ u- V6 H2 i  Y$ e
  19.   /* 使能DMA2D */
      Y0 Q* t  F2 |, h# P
  20.   __HAL_DMA2D_ENABLE(hdma2d);
    ) A# A5 y( \  S+ c! v5 i& C1 I

  21. * J6 F7 h6 }$ a0 `6 I$ R7 L) M
  22.   return HAL_OK;& X+ A; K- p* k
  23. }
复制代码

8 [0 I) U. Q6 q) n, P5 B# r函数描述:
* x" P  K; S- N7 N3 M9 _" X0 k/ U+ z! T& U4 E$ p& d( M  n6 M. D( u$ `
此函数用于启动DMA2D数据传输。由于采用的中断方式,此函数使能了多个DMA2D中断,不要忘记DMA2D中断服务程序的处理。" w! w0 v7 ~3 D% ?4 t

! E2 S: m$ p4 ^% E/ t函数参数:: o: k' ]" p; C0 G9 G

+ U+ N+ A2 T. ], y  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置DMA2D的基本参数,结构体变量成员的详细介绍看本章3.4小节。% y8 S" @2 y6 S9 K
  第2个参数是源数据地址。2 |) F* F- k; a5 g2 V; v
  第3个参数是目的数据地址。& m* @# N% G5 N9 n# p* }# L
  第4个参数是源数据的长度,即每行的像素个数。
9 h5 h" B( M0 J  N2 R& s/ I- d( s$ x  第5个参数是源数据的高度,即行数。2 z7 f/ I9 a5 j
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。! i4 L. W. @4 X# Q9 `
使用举例:- d. n. T, {* T1 |) l; h4 y3 \5 x5 k
% |8 X1 H, s9 R4 C+ C
  1. DMA2D_HandleTypeDef Dma2dHandle;( E+ f; f: M" w7 F& t& ?9 s' `

  2.   v% q3 `- T# T1 X4 \  ]
  3. if(HAL_DMA2D_Start_IT(&Dma2dHandle,            /* DMA2D句柄 */4 f% R* Y6 \, }" m
  4.                       (uint32_t)&BufferInput,  /* 源地址 */ 8 l. _& o' Q2 u
  5.                       (uint32_t)&BufferResult, /* 目的地址 */5 i: l0 Z1 y/ y+ z7 p
  6.                       SIZE_X,                  /* 源数据长度,单位像素个数*/
    & g7 w1 g7 ]" N5 T
  7.                       SIZE_Y)                  /* 源数据行数 */: f( B6 B, J9 _6 A
  8.    != HAL_OK)1 c; {; R* z$ o! s
  9. {7 h% `& u. F/ z. T4 D- {7 P' \
  10.    Error_Handler();
    3 a" I( f) P5 H( O3 P% w9 F+ T
  11. }
复制代码
2 Z& _% `) m6 N4 Y- b7 k
55.4.4 函数HAL_DMA2D_BlendingStart_IT0 b/ I. k4 k9 f, v5 A5 g
函数原型:( X$ L/ T# n4 Y
# I; [5 {5 V1 e) C: V
  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)' z" [" @+ K2 G* d# `0 f& V
  2. {+ {. j. n; o$ Z/ ]8 M6 U! A; P* V" A( e
  3.   /* 检测参数 */6 e! P0 G1 ^" Y1 t3 t! T
  4.   assert_param(IS_DMA2D_LINE(Height));
    # H7 ?3 Z1 E3 G( _& r
  5.   assert_param(IS_DMA2D_PIXEL(Width));( Z& ~0 S% B; Z" q% O# h& {
  6. ! `( w  x+ f$ U
  7.   /* 上锁 */& K7 N  F) W9 ~' x( h' ?
  8.   __HAL_LOCK(hdma2d);: d1 }) U. l/ a- b
  9. % `( s, n: j% V& p
  10.   /* 设置DMA2D外设状态 */
    0 Y9 {5 l- }  w8 J; }% W
  11.   hdma2d->State = HAL_DMA2D_STATE_BUSY;
    3 o# B/ `7 R0 G9 B! D# ]
  12. / c1 m& |- e) Z+ v; A8 ~
  13.   /* 配置DMA2D源地址2 */) E4 f5 H# c5 Y7 u  g; k
  14.   WRITE_REG(hdma2d->Instance->BGMAR, SrcAddress2);
    ' J  D2 p( L6 ^+ j; @7 q, d
  15. 7 V- N: \" h, J
  16.   /* 配置源地址1,目的地址和数据大小 */+ R/ Q0 n' W0 m3 h% b) \5 W, L, ?
  17.   DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height);# }2 @% R: y; s0 c- F( d$ U7 n
  18. + `' V8 N% s. d5 V* h
  19.   /* 使能DMA2D传输完成中断,传输错误中断和配置错误中断 */
    4 d7 K+ K6 c# U# z$ V* ^7 M; ^: J
  20.   __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE);
    8 t, Z2 r" d+ R# U( h& {
  21. * Z) z3 @$ @) v! z  N5 G
  22.   /* 使能DMA2D */( d7 y- ?, N5 T7 {$ ^7 a
  23.   __HAL_DMA2D_ENABLE(hdma2d);
    0 u6 }. p. m) ^8 i$ m. \
  24. / r2 M6 u$ `) o! h& n
  25.   return HAL_OK;
    ' f( I% A+ ?* |! q& R
  26. }
复制代码

) p% d9 Z$ P3 j% x, Z8 K% b9 I函数描述:* `& D4 l) g. {1 P/ g- {
# o) m! o3 V: ?6 G
此函数用于启动DMA2D传输,除了数据传输以外,还支持颜色格式转换和颜色混合。由于采用的中断方式,此函数使能了多个DMA2D中断,不要忘记DMA2D中断服务程序的处理。
1 L" E' w* _& A8 E
- s; F8 L8 C6 G* R( f  q函数参数:
4 K: b1 b9 s- c  [- \% ]
$ B% Y  ]- k$ u% T  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置DMA2D的基本参数,结构体变量成员的详细介绍看本章3.4小节。
% N3 `& v" I/ [1 |  第2个参数是源数据地址1。1 {+ x+ A- V3 U. {3 U, E$ h" H
  第3个参数是源数据地址2。1 \4 M' R1 O# R
  第4个参数是目的数据地址。
. P( [; g6 h6 ?7 `% U6 ^  第5个参数是源数据的长度,即每行的像素个数。
# ^/ e0 Z: ]5 ?% E9 T) t7 x5 T( l  第6个参数是源数据的高度,即行数。
7 T1 S8 A* J$ `) O/ t  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。6 {$ _- W! a5 S! @) H& J. a2 C' b
使用举例:
# p, `! f# n2 z
  F8 ?. I$ P+ W% r
  1. DMA2D_HandleTypeDef Dma2dHandle;) n$ V! O) k$ j6 x

  2. 5 o' B0 X3 i( L7 U# x  j
  3. if(HAL_DMA2D_BlendingStart_IT(&Dma2dHandle,           /* DMA2D句柄 *// P  R% S! w# \) i# }+ v7 c
  4.                              (uint32_t)&BufferInput1, /* 源地址1,前景色 */ 2 s" i* m, \' b4 J/ z* W6 p
  5.                              (uint32_t)&BufferInput2, /* 源地址2,背景色 */: U2 h/ U, M/ I& z. H
  6.                              (uint32_t)&BufferResult, /* 目的地址 */1 m" ]- n6 S9 \3 @
  7.                               SIZE_X,                 /* 源数据长度,单位像素个数*/) b. K) q* q1 |$ r
  8.                               SIZE_Y)                 /* 源数据行数 */8 J5 p1 b% L+ T$ z! W
  9.    != HAL_OK)
    & G) y( b5 ]4 o' H
  10. {' A% y7 D& ^9 ~  n. f' v
  11.    Error_Handler();
    - \1 B4 `5 W! A0 F6 ~2 C
  12. }
复制代码

; S+ q& }( l0 a7 l
/ C' S% |; a6 X; X. z55.5 总结
- Z" \" g5 b: o. e3 i本章节就为大家讲解这么多,DMA2D功能比较重要,一定要做到熟练使用。. A; u$ y) M$ g3 @' V

. ?4 N# @0 C9 L7 @7 E+ _9 ^$ S+ S+ {6 h! _: ^1 G( [7 Y
" s/ W2 q, Z9 q0 Z: R
收藏 评论0 发布时间:2021-12-24 17:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版