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

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

[复制链接]
STMCU小助手 发布时间:2021-12-24 17:00
55.1 初学者重要提示
' f6 o, q! q8 f' m( P  DMA2D是专门用于LCD加速的,特别是刷单色屏,刷图片,刷Alpah(透明)混合效果全靠它,而且可以大大降低CPU利用率。  M2 {0 r9 O( l2 A6 L; t
  测评STM32H7的LTDC+DMA2D性能,100Hz以上无压力,刷800*480图片和色块仅需2.6ms一张
- w( S( I( ^: a4 N+ r& ]% {  H7的DMA2D与F429的DMA2D最大区别是支持了ARGB和ABGR互转,而且支持H7的硬解JEPG输出格式YCbCr转RGB,方便LCD显示。7 k; @8 {: U6 R4 y, Z1 ]  k
  特别注意,大家只需对HAL库提供的DMA2D操作API有个了解即可,实际工程中,并不使用这些API,我们需要使用更加高效的寄存器直接操作,在下一章节会为大家说明。
* g- C/ H  a" A( `2 J; W55.2 DMA2D基础知识
( Q' V9 @0 E% ^4 V! O9 sDMA2D主要实现了两个功能,一个是DMA数据传输功能,另一个是2D图形加速功能。
! S. _- _5 s; }: M
' ?  @, ^$ D) d6 f9 [' z0 N- I  DMA数据传输
+ R* D/ w# T/ H% j8 C; H主要是两种方式,一个是寄存器到存储器,另一个是存储器到存储器。通过DMA可以大大降低CPU的利用率。: `! O* E, h; R/ ~/ k) T7 L  f
9 [6 |0 t! \$ p2 f* i# X7 t# J
  2D图形加速功能1 s) Z# [) O* e) L3 D# L" [
支持硬件的颜色格式转换和Alpha混合效果。3 _. w  Z" Y4 {9 q- D: j
. I8 Y: s; g" c
55.2.1 DMA2D硬件框图
2 A1 G5 U7 v$ w! d2 s( G7 ^* ~认识一个外设,最好的方式就是看它的框图,方便我们快速地了解DMA2D的基本功能,然后再看手册了解细节。框图如下所示:$ U. p: o( c& U6 {4 x
7 R) }. j% a+ O) p. t4 Q2 v/ e
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

9 ?- z( P8 B9 U$ U6 _
6 g) S2 b/ V; P! R) a通过这个框图,我们可以得到如下信息:
4 A% N6 Z% }- W# C* ^6 |1 ?
  B% q( D& l$ ?) ~: L* |3 P# Z4 J9 w( d  dma2d_aclk
; g; ]- o8 A6 JAXI 总线时钟输入。
$ X$ S, Z( ^- s6 ]1 {1 L
( K" `0 I0 N1 F$ \  dma2d_gbl_it
: B9 q+ y3 c! k3 [- q, c7 jDMA2D全局中断输出。+ v8 i6 p' @* [/ @$ \7 s$ E3 r

3 \& h9 l, d$ H+ `0 S4 L  dma2d_clut_trg
8 D0 k9 R) _1 [: z1 ]CLUT传输完成信号输出,可以触发MDMA。
: q) o- o8 s5 l1 M) d. x! s
! q# ~5 T) B- q/ H4 }  dma2d_tc_trg; a( |7 s" g/ U7 j' I* e# L
传输完成信号输出,可以触发MDMA。
4 ]! `: L7 G. |& }  S
4 I; z9 t( Z9 G# Y  dma2d_tw_trg
6 D4 N* Q5 F5 w5 I传输watermark信号输出,可以触发MDMA。
5 ~0 Q& Z' t( A# c
6 z; h. C- C3 d将这个硬件框图简化一下,就是下面这样:
  D# N6 k* v8 Z! N9 H; q  P
0 F/ L. t* f! n7 D
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

9 Y7 Z8 {2 B; i+ v9 {! R5 n6 K/ |# \8 G2 T/ N' z
下面按照简化的硬件框图,对每个部分做个说明。" H3 `$ w' T8 G# D0 z
- ~# `7 Y5 r% T) O" h1 b' i
55.2.2 DMA2D工作模式
  Z; D) B* s% R3 L# \0 TDMA2D支持的工作模式如下:
/ U4 |4 \) J9 {: S+ c: Q; F/ V; d8 q' D/ I9 L9 t0 w
  模式1:寄存器到存储器模式4 A1 C5 [- U0 S' W3 _% A
这个模式主要用于清屏,也即是将显示屏清为单色效果。
) N: ?. J4 [& [! ]; t# r
" c  u) J. E2 a+ s  模式2:存储器到存储器模式
9 Y1 {2 {8 k6 a) u0 O这个模式用于从一个存储器复制一块数据到另一个存储器,比如将摄像头OV7670的输出图像复制到LCD显存就可以采用这种方式。
% P' B) R+ W# Y' R  h- q8 c* w, B6 D% G+ v
  模式3:存储器到存储器模式,带颜色格式转换, F/ t: H: G' A9 h: a: S
这个模式比模式2多了一个颜色格式转换,比如我们要显示一幅RGB888颜色格式的位图到RGB565颜色格式的显示屏,就需要用到这个模式,只需输入端配置为RGB888,输出端配置RGB565即可。位图颜色格式转换后会显示到显示屏上。  l+ \/ m8 s4 S- `+ L; y9 Z9 q5 B7 b

& N- @8 ~1 b* s  ^  模式4:存储器到存储器模式,带颜色格式转换和混合
. h3 T: k+ E) \# c: r9 F/ i这个模式比模式3多了一个混合操作,通过混合,可以将两种效果进行混合显示。
1 Q/ }- u- P9 a0 F, x" Z$ ~+ T
0 `2 N# E6 s1 h, `. e7 k* d' v7 F4 y  模式5:存储器到存储器模式,带颜色格式转换和混合,前景色是固定的
9 [. f' n4 M. u) K+ r* C同模式4,只是前景色的颜色值是固定的。5 O6 T3 A' P/ ^/ z8 g
( v7 k! h; n( z% Y. g
55.2.3 前景层和背景层的输入以及颜色格式转换
" g' D5 }3 y" _8 z0 ]4 A前景层和背景层是指的用户绘制图形时的前景色和背景色,比如我们显示汉字,字体会有一个颜色,也就是前景色,还有一个背景色。又比如我们绘制两幅图片,想将两幅图片混合,那就可以将一幅图片作为前景层,另一个幅图片作为背景层。5 F5 E5 Z: j8 b

7 Z" l9 T4 s  D( P. g9 S# g4 H  KDMA2D支持的输入颜色格式如下,前景层和背景层一样:
5 w, d+ O, e" z1 h" j
# p+ b+ S  `" Q# e. W
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

9 M6 b0 C* Y7 a% h( k# S: N7 `- w: R2 S0 o
前8种颜色格式在第50章的第2小节开头有介绍,这里把后四种做个说明:% H! ^: V& E. a) v8 M9 V) ~9 c: Y) L

- x+ M  |+ A, r5 d* k4 P  L4 (4-bit luminance or CLUT)" l9 g% \* b+ L( p, X2 W( b
4位颜色格式,实际上仅仅是4位索引值,范围0–15,而每个索引值的具体颜色值在查色表CLUT里面存储。
/ z3 @, R# v: i" z, D* r% ^1 _" H6 F8 f! R$ M
  A4和A8
( c' ~, Y  [( IA4和A8用于特定的Alpha模式,既不存储颜色信息,也没有索引值。& {5 r+ z1 @+ A; [+ O
" s% {7 w0 J) n1 c# ?
  YCbCr
" t3 l( d+ ]7 }这个是H7的硬件JPEG输出的颜色格式,后面JPEG章节为大家专门做讲解。
7 G: ?! z7 y: ~1 W+ ^& _5 A
8 p& S: e* o. N8 T: @这里特别注意一点,输入颜色格式的Alpha值是可以设置的,而且颜色格式里面的R通道和B通道可以交换位置。  C8 ^2 y: s/ R$ h7 W% |  \

% `- K* O; u- L$ G* L3 l$ `2 q; _55.2.4 前景层和背景层混合
% |' X6 d. Y  V, B- J; KDMA2D混合器用于混合前景色和背景色,这个功能不需要任何配置,仅需要通过DMA2D_CR寄存器使能即可。混合公式如下:( M' S& b! Q) V, p

- O: d; v+ k' n# B* ?7 {8 t6 k
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
4 Z' H7 O( F. l  E0 L7 ]+ ^# S
( p9 q% R) K( k4 k
55.2.5 DMA2D输出颜色格式
( n4 {: `" T* oDMA2D支持的输出颜色格式如下:+ T- {) q/ Q1 Y4 [! p! R4 G5 ?. i

! Y6 n- n( D$ J6 ^" f2 F
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
% @7 J, F( f* f% M8 B

; F' N; I2 t* Q. b5 R: Z* C4 k! Y这里特别注意一点,输出颜色格式的Alpha值是可以设置的,而且颜色格式里面的R通道和B通道可以交换位置。: |, g. \% n' {  c$ @7 @' F
1 R# c: I4 V: F$ v/ R
55.3 DMA2D的HAL库用法4 t1 g. F$ b$ K) X) V
DMA2D的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断。下面我们逐一展开为大家做个说明。
( Z& n% j( Y4 T& W0 C, u
3 M4 p0 k# i& G7 ?6 {55.3.1 DMA2D寄存器结构体DMA2D_TypeDef
4 H0 I5 [) n2 aDMA2D相关的寄存器是通过HAL库中的结构体DMA2D_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:" P5 L; Y" S/ k& ]2 b) f
5 G# ^2 [$ s# [' A
  1. typedef struct
    . n7 G! Q* Q" n4 n2 V3 c" ~" \( r
  2. {
    ' X4 ?* ~; N' ?9 S8 _5 Q% j
  3.   __IO uint32_t CR;            /*!< DMA2D Control Register,                         Address offset: 0x00 */
    ' k8 R" T  i2 p- ?# ^: A$ J/ K) n( f/ y/ {# f
  4.   __IO uint32_t ISR;           /*!< DMA2D Interrupt Status Register,                Address offset: 0x04 */( X2 o: a  W/ h% w( j
  5.   __IO uint32_t IFCR;          /*!< DMA2D Interrupt Flag Clear Register,            Address offset: 0x08 */
    ( k* `, b+ _. Y( U' T6 V2 T
  6.   __IO uint32_t FGMAR;         /*!< DMA2D Foreground Memory Address Register,       Address offset: 0x0C */
    ! ^7 r- ]# _: b: W
  7.   __IO uint32_t FGOR;          /*!< DMA2D Foreground Offset Register,               Address offset: 0x10 */5 B" u8 {9 u0 ~
  8.   __IO uint32_t BGMAR;         /*!< DMA2D Background Memory Address Register,       Address offset: 0x14 */
    8 m6 o0 G4 e" `- P  }4 v( X
  9.   __IO uint32_t BGOR;          /*!< DMA2D Background Offset Register,               Address offset: 0x18 */
    $ H: d1 d& J+ r6 u
  10.   __IO uint32_t FGPFCCR;       /*!< DMA2D Foreground PFC Control Register,          Address offset: 0x1C */" s* E; q9 }. P
  11.   __IO uint32_t FGCOLR;        /*!< DMA2D Foreground Color Register,                Address offset: 0x20 */
    + L/ v; n* a8 X& O. C
  12.   __IO uint32_t BGPFCCR;       /*!< DMA2D Background PFC Control Register,          Address offset: 0x24 */& j3 W0 m: \" C; c) `6 ?
  13.   __IO uint32_t BGCOLR;        /*!< DMA2D Background Color Register,                Address offset: 0x28 */. h- m" t) L0 H" G  y& F2 p
  14.   __IO uint32_t FGCMAR;        /*!< DMA2D Foreground CLUT Memory Address Register,  Address offset: 0x2C */
    ; ~' |/ e& C' h% l1 |# f" Q
  15.   __IO uint32_t BGCMAR;        /*!< DMA2D Background CLUT Memory Address Register,  Address offset: 0x30 */1 n/ a  W) X- d: B/ p; P# w
  16.   __IO uint32_t OPFCCR;        /*!< DMA2D Output PFC Control Register,              Address offset: 0x34 */
    " _+ ^( D% n7 J) J" U% ^! ^" x4 t
  17.   __IO uint32_t OCOLR;         /*!< DMA2D Output Color Register,                    Address offset: 0x38 */
    * R" h5 A) z3 d4 f. ^+ i
  18.   __IO uint32_t OMAR;          /*!< DMA2D Output Memory Address Register,           Address offset: 0x3C */, D# p+ _; |5 J$ v% `
  19.   __IO uint32_t OOR;           /*!< DMA2D Output Offset Register,                   Address offset: 0x40 */
    2 I5 E/ Z* y' X5 p/ E1 y. O
  20.   __IO uint32_t NLR;           /*!< DMA2D Number of Line Register,                  Address offset: 0x44 *// v# J8 y0 x' Y
  21.   __IO uint32_t LWR;           /*!< DMA2D Line Watermark Register,                  Address offset: 0x48 */
    . S6 k/ M3 P4 R3 D$ H0 M" O4 r* e
  22.   __IO uint32_t AMTCR;         /*!< DMA2D AHB Master Timer Configuration Register,  Address offset: 0x4C */% y; |' f2 |- |. R% q3 X
  23.   uint32_t      RESERVED[236]; /*!< Reserved, 0x50-0x3FF */
    - ^; ^7 s" U; x2 ^, Q
  24.   __IO uint32_t FGCLUT[256];   /*!< DMA2D Foreground CLUT,                          Address offset:400-7FF */. o) A& W$ j& R5 ^7 y) |  g
  25.   __IO uint32_t BGCLUT[256];   /*!< DMA2D Background CLUT,                          Address offset:800-BFF */
    1 K9 Q; [0 d4 S& Q: S+ e  x
  26. } DMA2D_TypeDef;
复制代码

5 L+ M2 ?+ N9 I. G
1 L$ K2 @. m1 R/ w__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:. l2 q7 p9 p# A# a9 V; R9 K

8 Q$ @1 `! d; `" D5 C0 f; t
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    ; y( o9 O" K" E$ j; s7 z
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

# K6 }4 t* i4 y4 X下面我们再看DMA2D的定义,在stm32h743xx.h文件。
  1. #define PERIPH_BASE              ((uint32_t)0x40000000) . z/ C: u4 d1 q5 |+ {( p0 Q* X' H+ B* D
  2. #define D1_AHB1PERIPH_BASE       (PERIPH_BASE + 0x12000000)
    $ D1 ?" F4 V( p/ i
  3. #define DMA2D_BASE               (D1_AHB1PERIPH_BASE + 0x1000)
    & N$ L/ l; L( C! s
  4. #define DMA2D                    ((DMA2D_TypeDef *) DMA2D_BASE) <----- 展开这个宏,(DMA2D_TypeDef *) 0x52001000
复制代码
  w5 \. i5 u  N" w9 ~3 }
我们访问DMA2D的ISR寄存器可以采用这种形式:DMA2D->ISR = 0。( r3 m- J% M9 x5 G6 B" b! k
6 k+ }9 x2 W$ ]/ }
55.3.2 DMA2D参数初始化结构体DMA2D_InitTypeDef& M8 {! u7 v* y) _
此结构体用于配置DMA2D的基本参数,具体定义如下:  C0 c# c( B/ Z

& h  _/ K, ^" \# Q7 E6 t6 x6 m' g
  1. typedef struct
    # w6 Y0 m: R8 z
  2. {
    4 ]  y4 k; y; R0 v) ]3 Y4 v
  3.   uint32_t             Mode;              2 I! J/ [- I7 V' ^
  4.   uint32_t             ColorMode;        
    . e+ D- D( ^4 Q: g0 C
  5.   uint32_t             OutputOffset;       8 k( M1 R7 \4 K1 K- j
  6.   uint32_t             AlphaInverted;   
    ! z5 Z) x$ P) V1 Z3 ^3 A
  7.   uint32_t             RedBlueSwap;      
    7 y* I; @3 `" b3 x: E; r, |9 L
  8. } DMA2D_InitTypeDef;
复制代码
' y7 d4 M" F1 G* P
下面将这几个参数逐一为大家做个说明:& v% b4 X, E% ~1 b, S5 t

! h- Y) ^2 a, ~: e/ H  uint32_t   Mode2 N% P. x' a3 G" a9 l) @
此参数用于设置DMA2D的传输模式,具体支持的参数如下:
( e& T5 @. T' x; G
5 @0 o6 f3 {4 [, u+ M
  1. #define DMA2D_M2M        ((uint32_t)0x00000000U)  /*存储器到存储传输模式 */
    8 O$ I0 d$ I! e7 D9 _* d) @
  2. #define DMA2D_M2M_PFC     DMA2D_CR_MODE_0         /*存储器到存储器传输模式,并执行FPC像素格式转 */+ H1 b4 ^0 R& G2 j  X6 S3 F7 s
  3. #define DMA2D_M2M_BLEND   DMA2D_CR_MODE_1         /* 存储器到存储器模式,并执行像素格式转换和混合 */
    1 J) F* s% [2 S5 y" J, F
  4. #define DMA2D_R2M         DMA2D_CR_MODE           /* 寄存器到存储器传输模式 */, `1 ]( I8 M0 M/ r- x6 m2 z/ j" D/ w
复制代码

+ [& e& b; l; P% t' v6 q3 A
& M% m2 O  v4 y2 o5 R  uint32_t   ColorMode
' _, j/ D* f; x, n! }4 N此参数用于设置DMA2D的输出颜色格式,具体支持的参数如下:7 }0 y! y) I4 G. n5 I% G( B" r

+ D$ b: E* V. m& k
  1. #define DMA2D_OUTPUT_ARGB8888       ((uint32_t)0x00000000U)               /* ARGB8888 */
    5 L% z) I7 Z+ p1 _7 C
  2. #define DMA2D_OUTPUT_RGB888         DMA2D_OPFCCR_CM_0                     /* RGB888 */; i$ Z5 @' _7 \& I" j' Z+ p1 ?+ ~
  3. #define DMA2D_OUTPUT_RGB565         DMA2D_OPFCCR_CM_1                     /* RGB565 */- P. p8 ]" v7 P8 z7 _& j3 d
  4. #define DMA2D_OUTPUT_ARGB1555       (DMA2D_OPFCCR_CM_0|DMA2D_OPFCCR_CM_1) /* ARGB1555 */! \5 Q9 o8 ~( q8 X, B- z
  5. #define DMA2D_OUTPUT_ARGB4444       DMA2D_OPFCCR_CM_2                     /* ARGB4444 */
    / z. K% y& q5 C' z+ s
复制代码

. s4 N1 [$ H7 P/ g' ]
( U+ E& E+ l; G( O/ w( L. c  uint32_t   OutputOffset+ K  }2 V) U8 }1 h: _% U
此参数用于设置输出位置的偏移值,参数范围0x0000到0x3FFF。* B) m  [" G! K  _* @
+ l9 X- g9 W1 \, L; L8 N
  uint32_t   AlphaInverted; T4 ~" r8 i7 ?; G
此参数用于设置DMA2D的输出颜色格式Alpha值反转(即255-原来数值),具体支持的参数如下:     
* P. j5 w7 m2 N. ]7 J+ e9 o3 h( U8 m7 p* ^* `, X" k/ r
  1. #define DMA2D_REGULAR_ALPHA      ((uint32_t)0x00000000U)  /* 正常输出 */
    # [# u9 @# S9 Q) s/ w7 j7 S/ _
  2. #define DMA2D_INVERTED_ALPHA     ((uint32_t)0x00000001U)  /* 反转输出 */
复制代码

  G2 _+ i. r6 v0 ]/ d: N  uint32_t   RedBlueSwap
. F  x# c2 P) F2 Q此参数用于设置DMA2D的输出颜色格式中R通道和B通道的交换,具体支持的参数如下:
7 \( a  q* T0 C2 ^5 H/ t& q$ E2 }2 w/ d. ^$ X5 S. L4 c( `
  1. #define DMA2D_RB_REGULAR   ((uint32_t)0x00000000U)  /* 不交换(RGB or ARGB) */
    ) f" l# A( U& P1 g- R& H. N9 b: d
  2. #define DMA2D_RB_SWAP      ((uint32_t)0x00000001U)  /* 交换(BGR or ABGR) */
复制代码

9 U1 a5 X# \! _. N; T55.3.3 DMA2D的图层结构体DMA2D_LayerCfgTypeDef" x5 v& T' n3 V& E
此结构体用于配置前景色和背景色。2 x9 i6 {  p* M0 J5 K
- x5 A: j/ d8 ^# S& b
  1. typedef struct9 A0 V7 b- I2 v$ ^4 \
  2. {
    , U1 A  c' O7 o6 J9 z: _
  3.   uint32_t             InputOffset;         I! W6 k1 _" c, t. Z/ ?
  4.   uint32_t             InputColorMode;   
    8 D3 `# I3 V: A) }* P
  5.   uint32_t             AlphaMode;        & k5 V) I3 v& r& I/ S2 G2 [: w
  6.   uint32_t             InputAlpha;        . \! P5 k, o7 M+ E4 ]
  7.   uint32_t             AlphaInverted;    ( V5 Z, B  z5 ?! J4 K( Z+ Q
  8.   uint32_t             RedBlueSwap;      
    ) A. `( R+ p7 W8 Z; p% @# I, Y9 R
  9.   uint32_t             ChromaSubSampling;% S7 J( J' k: ]8 J
  10. } DMA2D_LayerCfgTypeDef;
复制代码
- z5 P) U* I* q2 S6 t9 b) N
下面将这几个参数逐一为大家做个说明。3 r  P; ^* l" U/ v, n
- B" F5 j$ D: Q0 t
  uint32_t  InputOffset7 B% j5 N: t8 y2 a9 A! d) q% X
设置前景色或者背景色的输入偏移,范围0x000到0x3FFF。
9 G/ ~8 ?4 V0 [+ j. i- @/ h
! \8 h. x2 `3 G  uint32_t  InputColorMode8 G& A+ L/ U9 s6 u" f
设置前景色或者背景色的输入颜色格式,具体支持的参数如下:
9 W/ s9 K' z5 b  @, H. L, a0 k3 Y9 L' m+ @: a
  1. #define DMA2D_INPUT_ARGB8888        ((uint32_t)0x00000000U)  /* ARGB8888 */
    ) n3 e3 }, U  `- H5 M: w4 ?
  2. #define DMA2D_INPUT_RGB888          ((uint32_t)0x00000001U)  /* RGB888   */
    8 n2 d) r' B# q" X$ E# F
  3. #define DMA2D_INPUT_RGB565          ((uint32_t)0x00000002U)  /* RGB565   */
    ; F" C) J! v+ j5 _2 [: [  d% Y
  4. #define DMA2D_INPUT_ARGB1555        ((uint32_t)0x00000003U)  /* ARGB1555 */
    6 u2 g9 t+ ?) j( ?, t4 j
  5. #define DMA2D_INPUT_ARGB4444        ((uint32_t)0x00000004U)  /* ARGB4444 */+ h$ ~, N( V/ y3 U; p
  6. #define DMA2D_INPUT_L8              ((uint32_t)0x00000005U)  /* L8       */, d! N8 r6 M3 I& x. n2 y& q
  7. #define DMA2D_INPUT_AL44            ((uint32_t)0x00000006U)  /* AL44     */* I$ O7 J1 z  Q5 o  {- U
  8. #define DMA2D_INPUT_AL88            ((uint32_t)0x00000007U)  /* AL88     */1 `: S3 c6 \6 ^  G. A; D
  9. #define DMA2D_INPUT_L4              ((uint32_t)0x00000008U)  /* L4       */
    7 H' f+ i1 X) F  H
  10. #define DMA2D_INPUT_A8              ((uint32_t)0x00000009U)  /* A8       */1 R' |1 D8 S& H  X( u
  11. #define DMA2D_INPUT_A4              ((uint32_t)0x0000000AU)  /* A4       */
    8 Z) N. _3 g* G2 ?4 Q. D" s
  12. #define DMA2D_INPUT_YCBCR           ((uint32_t)0x0000000BU)  /* YCbCr    */
复制代码

0 N7 _$ |; h! w7 J" x. z  uint32_t AlphaMode
' q1 p. I* B6 B( R设置前景色或者背景色的Alpha模式,具体支持的参数如下:
" D7 R  ?! }' i# ^) d: d6 b
( Y. Z/ v* v% Z; u7 }
  1. #define DMA2D_NO_MODIF_ALPHA   ((uint32_t)0x00000000U)  /* 不修改Alpha通道值 */
    / j0 H9 ~$ S4 K& H8 A$ e- \5 a, v- c0 M9 C
  2. #define DMA2D_REPLACE_ALPHA    ((uint32_t)0x00000001U)  /* 用新设置的Alpha值替换原始Alpha值 */$ Z3 O- R6 R+ f7 B/ _7 {
  3. #define DMA2D_COMBINE_ALPHA    ((uint32_t)0x00000002U)  /* 用新设置的Alpha值与原始Alpha值的乘积替换原始Alaha值*/
复制代码

7 p' O# C/ a/ l- }  uint32_t  InputAlpha
9 t9 @7 B- O7 Q+ m* K1 k, M; Y设置前景色或者背景色的Alpha值,范围0x00到0xFF,如果颜色格式是A4或者A8,那么此参数的范围是0x00000000到0xFFFFFFFF,标准的ARGB8888格式。$ F/ G/ r* v3 G9 f
. B7 Q+ D$ e5 L
  uint32_t AlphaInverted
  \& m; @( @5 {1 |: `9 u设置前景色或者背景色的输入颜色格式Alpha值反转(即255-原来数值),具体支持的参数如下:     
* I7 b7 a0 M! ^4 p! i" l' O+ k
4 k- J0 _2 D- s4 ~
  1. #define DMA2D_REGULAR_ALPHA      ((uint32_t)0x00000000U)  /* 正常输出 */+ ~# [+ i, [) i2 Q
  2. #define DMA2D_INVERTED_ALPHA     ((uint32_t)0x00000001U)  /* 反转输出 */     
复制代码
; N& M& f2 R8 B$ x; a# h
  uint32_t   RedBlueSwap  [0 X( }5 O1 q% U
设置前景色或者背景色颜色格式中R通道和B通道的交换,具体支持的参数如下:
/ G/ U$ Q3 M2 f
6 o; ?% f6 k' T, i! m
  1. #define DMA2D_RB_REGULAR   ((uint32_t)0x00000000U)  /* 不交换(RGB or ARGB) */
    . u. c* ^& y2 v7 ^6 F- S: s
  2. #define DMA2D_RB_SWAP      ((uint32_t)0x00000001U)  /* 交换(BGR or ABGR) */
复制代码

9 s' z7 M  L. r* C0 F  uint32_t   ChromaSubSampling+ x# ^3 A, x' I
设置前景色或者背景色中YCbCr 颜色模式的采样格式,具体支持的参数如下:
  1. #define DMA2D_NO_CSS               ((uint32_t)0x00000000)  /* 4:4:4 */
    8 _4 m& W' U( b
  2. #define DMA2D_CSS_422              ((uint32_t)0x00000001)  /* 4:2:2 */% ~) r6 V' T, U* F( M$ ^9 ?
  3. #define DMA2D_CSS_420              ((uint32_t)0x00000002)  /* 4:2:0 */  
复制代码

: e- u! b/ D8 g) y+ o0 K# f* Z55.3.4 DMA2D句柄结构体DMA2D_HandleTypeDef
( x& T0 Q, @0 U# P9 R* M+ ^
HAL库在DMA2D_TypeDef, DMA2D_InitTypeDef和DMA2D_LayerCfgTypeDef的基础上封装了一个结构体DMA2D_HandleTypeDef,定义如下:4 r) e- ]% f' }& {, U9 D
, N0 A! |: A3 b- o% h2 m8 z- f  G
  1. typedef struct __DMA2D_HandleTypeDef# U" p$ _8 w' Z" `3 ^# o9 n9 x0 {
  2. {
    ( B/ C1 \% ?4 e1 N
  3.   DMA2D_TypeDef               *Instance;                                                                                                                                                                                          
    + o/ \% ?5 d' p" z5 B
  4.   DMA2D_InitTypeDef           Init;                                                        0 c$ K. N: B  `+ ~/ w
  5.   void                        (* XferCpltCallback)(struct __DMA2D_HandleTypeDef * hdma2d);                                                                                                                                             
    $ Y2 ~5 Q* @: g/ b
  6.   void                        (* XferErrorCallback)(struct __DMA2D_HandleTypeDef * hdma2d);                                                                                      
    / s- f1 v2 d5 L7 |0 l" k5 ^
  7.   DMA2D_LayerCfgTypeDef       LayerCfg[MAX_DMA2D_LAYER];                                    
    " E- ?8 D& b9 v) h, a" `
  8.   HAL_LockTypeDef             Lock;                                                                                                                                                                                                   
      V3 X( c0 E- V- p% S* C
  9.   __IO HAL_DMA2D_StateTypeDef State;                                                                                                                                                                                                   % Q6 C: U5 E  \4 S: O
  10.   __IO uint32_t               ErrorCode;                                                   } DMA2D_HandleTypeDef;% R, O& V1 S% Y* [. \  y9 ?
复制代码

2 @5 _/ U. e3 j2 K- s' z下面将这几个参数逐一做个说明。* Z  |9 b( ^" u4 ^$ f) c: Y( ]

. W4 l2 H# Z3 ?* n  DMA2D_TypeDef  *Instance; g$ x4 Y( F0 L8 t' W, F0 k
这个参数是寄存器的例化,方便操作寄存器,详见本章3.1小节。
1 `$ B) I' j2 Y) f  \3 `( _, N( A" {% v* K$ E& ?) m( P, k; @
  DMA2D_InitTypeDef  Init;  
3 r9 T/ V; ]/ o- B5 c$ q这个参数是用户接触较多的,用于配置DMA2D的基本参数,详见本章3.2小节。
6 {# h; o8 S* q2 }3 Q2 y+ M8 ~( O" Z
" K: e6 }9 x+ k7 Q  void     (* XferCpltCallback)(struct __DMA2D_HandleTypeDef * hdma2d);
/ o& x% E  x  I5 E- \  void     (* XferErrorCallback)(struct __DMA2D_HandleTypeDef * hdma2d);# X$ y+ e" z. f. `2 K1 e4 x! f8 P# v
DMA2D中断服务程序里面执行的回调函数,一个是传输完成回调,另一个是传输错误回调。
$ ~3 a8 k' t1 i+ Q2 V2 v# y0 F% r; F' K
  DMA2D_LayerCfgTypeDef   LayerCfg[MAX_DMA2D_LAYER]/ i- I% v( S, e& n1 f7 n& P
这个参数用于前景色和背景色的设置,MAX_DMA2D_LAYER=2,详见本章3.3小节。9 {2 D( `+ T* [, D
: G$ R- C0 C; Q3 M
  HAL_LockTypeDef   Lock9 B/ P9 Z( \) B4 }# ]9 s, p% ~3 P
__IO uint32_t    State;
: `* x3 t5 @0 U- D- G$ k' L$ [/ e; d9 z* Z3 h
__IO uint32_t    ErrorCode
( P: O; H3 x7 c" W. y
4 g6 Y, M8 x3 Q& `这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DMA2D通信状态,而ErrorCode用于配置代码错误。' A1 t1 h6 X: H% T! G1 ^

- R& p+ O4 K5 w: b3 {55.3.5 DMA2D初始化流程总结

& b  }# L; U% J; j# W对于DMA2D来说,其实不需要初始化流程,每个功能都可以直接封装出一个函数来,下个章节会为大家专门讲解,也是实际项目比较推荐的方式。9 y8 V4 _4 K, f: I8 Q; Z* _
* A8 h/ j. u+ v  Y+ j8 [
55.4 源文件stm32h7xx_hal_dma2d.c
0 B$ `( N2 j+ ]* Z( |) }6 H: b这里把我们把如下几个常用到的函数做个说明:  i# U2 L7 v, k6 L9 C
  W! h' S8 v$ b# s2 z
  HAL_DMA2D_Init
8 T! }- V. j- z  X- H- i  HAL_DMA2D_ConfigLayer
& e" ~1 p! O* I0 a0 l" v  HAL_DMA2D_Start_IT; K- N; I: b  ~5 A2 k! C5 N0 j
  HAL_DMA2D_BlendingStart_IT  o0 w$ B' h! J# T6 c" v

2 z4 R9 V" b) ?. X2 `8 F( c55.4.1 函数HAL_DMA2D_Init1 I* Y* J6 h" l9 M, t, c8 c0 G
函数原型:
; H$ v% @: \3 J- M9 n  ]! r
, W: S( K% a9 Z3 W& m9 z4 ^/ W' d9 n
  1. HAL_StatusTypeDef HAL_DMA2D_Init(DMA2D_HandleTypeDef *hdma2d), T( M, i  h* w; J  C9 |
  2. { $ g; V( S8 v* S* }- c0 h9 j$ i

  3. # C; ~' |3 a7 n: P' A3 j% B( G, `' h
  4. /*  检测参数是否有效 */
    " A9 q* ?( {! d0 j5 H
  5.   if(hdma2d == NULL)  c- i% c# h% u( C
  6.   {. P  H! ^+ p- J. h- m- R
  7.      return HAL_ERROR;
    2 e: o, _. k' @0 o9 h- b4 C
  8.   }3 n( d0 W1 n5 @+ `" _. i

  9. 6 K1 l' ~) N) o/ R- x% r$ |
  10.   /* 检测函数形参 */
    / e- V- V) L0 o" m' W8 O# q
  11.   assert_param(IS_DMA2D_ALL_INSTANCE(hdma2d->Instance));& {7 F- ^  N& x/ p: q
  12.   assert_param(IS_DMA2D_MODE(hdma2d->Init.Mode));
    ( b# Z! _4 r3 P6 s- \# Y9 l% f+ j
  13.   assert_param(IS_DMA2D_CMODE(hdma2d->Init.ColorMode));
    2 J9 |: R' u" G4 P/ a
  14.   assert_param(IS_DMA2D_OFFSET(hdma2d->Init.OutputOffset));, Y/ j/ ?( q9 u- D0 A0 Q% ?/ k) e

  15. ! H3 m) Q* ?5 ~. }
  16.   if(hdma2d->State == HAL_DMA2D_STATE_RESET)3 }& S7 f; K/ ^% N
  17.   {  J6 ]% @. ^7 J/ \; v
  18.     hdma2d->Lock = HAL_UNLOCKED;5 G9 t' t: c7 P( C3 z! }$ H
  19.     /* 初始化GPIO,NVIC等 */
    9 O0 ~) ?/ r7 M- g9 ~
  20.     HAL_DMA2D_MspInit(hdma2d);
    2 ?6 x* G, V7 \% u) H/ ^+ C
  21.   }% Z9 w( w) Y9 C
  22. + `8 C/ D$ }0 Q4 ]
  23.   /* 设置DAM2D外设状态 */$ @( Z4 [1 Z- x; d$ E/ r
  24.   hdma2d->State = HAL_DMA2D_STATE_BUSY;  ' R2 G# Y( B( J. g$ B
  25. 8 L' z0 Q0 q+ S+ J0 a! O
  26.   /* 设置DAM2D工作模式 -------------------------------------------*/6 q' W- @7 B- Q
  27.   MODIFY_REG(hdma2d->Instance->CR, DMA2D_CR_MODE, hdma2d->Init.Mode);
    . _2 t( [. n3 Z# R, ^4 M- [
  28. 0 q5 Y" t; F/ y) z
  29.   /* 设置输出颜色格式 ---------------------------------------*// P# }+ B! r6 j
  30.   MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_CM, hdma2d->Init.ColorMode);; C. _6 o1 ~$ k) b

  31. 1 [6 b" G8 M2 b
  32.   /* 设置输出偏移 ------------------------------------------*/    y5 O- ?; G, I. F; z( S4 W! }, d
  33.   MODIFY_REG(hdma2d->Instance->OOR, DMA2D_OOR_LO, hdma2d->Init.OutputOffset);  ( z1 o) q- @% |) `
  34. , b# J  Q. o) B. H) @7 W1 G
  35.   /* 设置输出颜色格式中的Alpah值反转 */
    7 X+ m! D: \  o! k
  36.   MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_AI, (hdma2d->Init.AlphaInverted << DMA2D_POSITION_OPFCCR_AI));" h1 j# l/ Y0 D9 O( t) ^

  37. 5 A+ U! r9 f7 A9 G- B6 e
  38.   MODIFY_REG(hdma2d->Instance->OPFCCR, DMA2D_OPFCCR_RBS,(hdma2d->Init.RedBlueSwap << DMA2D_POSITION_OPFCCR_RBS));( ~* J+ h" {6 b% _* k  k7 I2 V
  39.   S  F5 m% R+ C+ P/ l
  40. 0 p' Y) l$ B7 K  o3 o0 H8 U
  41.   /* 无错误 */. I. q2 S  Z% R9 p1 C1 k5 L
  42.   hdma2d->ErrorCode = HAL_DMA2D_ERROR_NONE;
    - g! S( Q3 M, f$ U
  43. 5 N/ f& E6 ]' W+ [% ^5 R" z
  44.   /* DAM2D就绪 */
    8 H/ p* E% O  @) X( |+ u
  45.   hdma2d->State  = HAL_DMA2D_STATE_READY;
    - K9 v1 t& X; L4 g. z

  46. * Q! ?5 m. r! @8 n% q& ?5 L) I& l+ [) g+ p
  47.   return HAL_OK;. l, Y0 o- G& z$ p
  48. }
复制代码
- t% Z6 g, O# k5 s3 q- ^& S: E+ J! c
函数描述:; q% v2 i0 p& s! |7 R! n
; l& J  _7 e$ P( U
此函数用于初始化DMA2D的工作模式和输出颜色格式。
" i% i4 i) J, K" S; O0 j% j0 g
5 I1 Y: z2 ~$ Q; ?9 T, ]3 n5 ^% R& A# S函数参数:
' L  m% V7 d/ m
# p/ [. t+ C5 X4 N  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数,结构体变量成员的详细介绍看本章3.4小节。4 B! c' F3 a) ?" i
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。, |0 q- }& Q% {( t3 p- V, ?9 i
注意事项:
# o) ~% o' P# Q
. {6 C+ ~& \0 k" M函数HAL_DMA2D_MspInit用于初始化DMA2D的底层时钟、NVIC等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。" P3 W, a" p9 A: r
如果形参hdma2d的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量DMA2D_HandleTypeDef Dma2dHandle。
5 L1 q# r/ |$ ~# y. b0 c对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_DMA2D_STATE_RESET  = 0x00U。* a% c" f4 a' N! H* ~
; I0 O. B4 i# Q; ?# P; ?. W5 {
解决办法有三7 g# N& O* R8 n+ e2 R
0 N% {4 ~, @3 B# n0 m
方法1:用户自己初始DMA2D底层。
- C( Z4 A  {. Q- A# |- I
* V: g$ M, t3 s6 z1 i3 \. d; j方法2:定义DMA2D_HandleTypeDef LtdcHandle为全局变量。
# r. p6 D1 X( q
7 _; x: @6 t; J5 n' d! S& U! p方法3:下面的方法
  1. if(HAL_DMA2D_DeInit(&Dma2dHandle) != HAL_OK)
    0 @3 r" x7 E) G) m! @1 g+ I, c
  2. {
    8 ~* F( n+ v* h: q& ]
  3.     Error_Handler();7 @1 m2 \. Q& a0 e7 R1 v
  4. }  
    ' r2 Z6 `! s: E3 _8 A2 f# S
  5. if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)
    / n- K8 F! @' M4 D- J
  6. {
    / A0 |' @, ~; n4 b3 H) o
  7.     Error_Handler();& Z: c8 e2 T# g0 L9 Y
  8. }
复制代码
/ y! l4 e6 ]6 C* A! V2 Z- V

- ?, j4 L( ~9 G  N使用举例:
  f  e) {/ o4 l3 E+ e& c8 T/ `, |( w! o" }$ V0 D6 Q
  1. DMA2D_HandleTypeDef Dma2dHandle;
    $ t/ K/ |& o: s9 w2 U0 X* D

  2. 4 P9 T7 m( W) C+ H; ~/ L
  3. /*##-1- 配置DMA工作模式,输出颜色格式和输出偏移 #############*/3 S! l9 u* W+ j) k# B* L, J
  4. Dma2dHandle.Instance = DMA2D;6 M) Y- o( i# |- R
  5.   w; K/ c! I& Y( }8 `* G2 E* Z6 q
  6. Dma2dHandle.Init.Mode          = DMA2D_M2M;             /* 存储器到存储器模式 */
    0 `7 U4 `! [: |/ |, K* t0 Q' m0 u
  7. Dma2dHandle.Init.ColorMode     = DMA2D_OUTPUT_ARGB4444; /* 输出颜色格式 */
    - I/ G+ u- c* H1 J9 [
  8. Dma2dHandle.Init.OutputOffset  = 0x0;                   /* 无输出偏移 */
    % u! F/ P% S# e
  9. Dma2dHandle.Init.RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输出颜色的R/B通过不切换 */
    / S2 p& h) g- H5 E5 F: {, m
  10. Dma2dHandle.Init.AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输出颜色的Alpha通道数值不翻转 */8 S  y- h+ A# m' y' ~; A: p2 `
  11. ; b5 r+ n. N" {" u. }/ ^6 x
  12. /*##-2- DMA2D 回调函数配置 ######################################*/' |3 u/ l: Y( Q. b" `
  13. Dma2dHandle.XferCpltCallback  = TransferComplete;: u+ J! R8 I; F  o
  14. Dma2dHandle.XferErrorCallback = TransferError;
    $ l5 t5 N6 ]6 P  g7 T; K3 D# k

  15. $ k9 i' W2 S9 t) Z; D) r8 Z
  16. /*##-3- 前景层配置 ###########################################*/
    % ^) P" T9 H5 T5 C
  17. Dma2dHandle.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;      /* 保持输入颜色格式中的Alpha值 */. [$ Q# r! Z9 U6 O
  18. Dma2dHandle.LayerCfg[1].InputAlpha = 0xFF;                     /* 完全不透明 */; l* m( ^6 q/ ]  p4 K
  19. Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB4444; /* 输入颜色格式 */% i. K# e% a1 ?, A" a: W# D
  20. Dma2dHandle.LayerCfg[1].InputOffset = 0x0;                     /* 输入无偏移 */. h- I- Q% t  z( }
  21. Dma2dHandle.LayerCfg[1].RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输入颜色的R/B通过不切换*/
    # Y2 y, Q8 C7 {, Y
  22. Dma2dHandle.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输入颜色的Alpha通道数值不翻转*/
    - o+ j: }' L$ J' C: `! ]

  23. ; C/ ?; C* p: l! z! `7 i
  24. ) R: @+ e, n( C( |8 c1 X
  25. /*##-4- DMA2D 初始化 ###############################################*/
    $ H' W1 ?% N5 `' Z; U
  26. if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)( l" q4 }* L4 W7 a8 k" v- G( B( ]
  27. {8 ]+ p5 Y5 c) P: I
  28.     Error_Handler();
    % x7 Z8 \1 N  M! r
  29. }
复制代码
' m. z1 N3 V9 |8 C! O$ y6 y) L
55.4.2 函数HAL_DMA2D_ConfigLayer
: y" p. F. H& Y- `+ T$ [' k函数原型:
5 O. ~+ p5 E" t  d: \9 j
8 A; S! D. L+ o8 ^% A# X6 A8 E
  1. HAL_StatusTypeDef HAL_DMA2D_ConfigLayer(DMA2D_HandleTypeDef *hdma2d, uint32_t LayerIdx)7 [4 y! n- x; f1 x9 [& z
  2. {
    6 D/ t& N8 w# {- o# p% Q
  3.   DMA2D_LayerCfgTypeDef *pLayerCfg = &hdma2d->LayerCfg[LayerIdx];  O! i; k2 Z- y7 m. u! N

  4. ! ~/ D% E# j; f) c3 v
  5.   uint32_t regMask = 0, regValue = 0;
    : I5 g" e* I5 I& Q( v. w
  6. 7 f3 V' p1 j9 ~& @( T( T
  7.   /* 检查参数 */3 g( \8 q: R# ]- p$ i
  8.   assert_param(IS_DMA2D_LAYER(LayerIdx));  / ~; t5 d+ q1 A/ {0 y" J% N
  9.   assert_param(IS_DMA2D_OFFSET(pLayerCfg->InputOffset));  5 p! a1 B. K3 f. w$ W& x
  10.   if(hdma2d->Init.Mode != DMA2D_R2M)
    ; F) O9 v* C4 i0 _; a
  11.   {  9 s) l- o0 q2 S# Y1 W1 g  J
  12.     assert_param(IS_DMA2D_INPUT_COLOR_MODE(pLayerCfg->InputColorMode));0 r. ^' ^, n; P  X' c. W# {" ?" ]
  13.     if(hdma2d->Init.Mode != DMA2D_M2M)
    ! }7 B% u" e  S8 |2 @
  14.     {
    % q9 N1 H6 }) G: K3 H! W
  15.       assert_param(IS_DMA2D_ALPHA_MODE(pLayerCfg->AlphaMode));
    3 T4 P3 v2 d9 j* |' A7 {( ~& s
  16.     }: A+ k+ n* u8 I) q
  17.   }, }& ?+ h' ]9 `7 `5 m3 O

  18. 5 Y- a- p! P7 B( S% k7 A8 {% n
  19.   /* 上锁 */
    ! U: y1 m! C; K5 F  m* Y
  20.   __HAL_LOCK(hdma2d);" H, g& ^& i& s* _6 S! C; \

  21. % l9 C! q3 `  w# a
  22.   /* 设置DMA2D外设状态 */' t" I: b2 Q9 G6 K
  23.   hdma2d->State = HAL_DMA2D_STATE_BUSY;  
    * g+ z( y" v3 z, u+ q- d. w$ P6 F
  24. 4 q2 a5 Y4 u2 K; j$ G- ^  I
  25.   /* 准备好背景层或者前景层FPC寄存器配置参数*/% w1 E. {8 P  x/ o% U6 q$ x
  26.   regValue = pLayerCfg->InputColorMode | (pLayerCfg->AlphaMode << DMA2D_POSITION_BGPFCCR_AM) | \8 _8 {! u6 Q9 V0 G6 P7 a! c0 ?
  27.             (pLayerCfg->AlphaInverted << DMA2D_POSITION_BGPFCCR_AI) | \
    ( R- n, R+ L3 s9 t- y/ t3 p' Y
  28.             (pLayerCfg->RedBlueSwap << DMA2D_POSITION_BGPFCCR_RBS);2 j" j  y0 `7 \
  29. $ x- u; u( |9 v
  30.   regMask  = DMA2D_BGPFCCR_CM | DMA2D_BGPFCCR_AM | DMA2D_BGPFCCR_ALPHA | DMA2D_BGPFCCR_AI | DMA2D_BGPFCCR_RBS;8 c9 j# g, c6 k$ U

  31. & b- K* ?* g5 R# A' p
  32.   if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))  \) ~" |  }$ U& @, t# ^
  33.   {/ z, N0 O1 E! @( h$ K
  34.     regValue |= (pLayerCfg->InputAlpha & DMA2D_BGPFCCR_ALPHA);
    8 Z! b- X. Y; Q* x" I
  35.   }
    % ]% |1 c/ `8 Y: L
  36.   else" N3 p7 L2 o$ i/ B: x. k' x
  37.   {
    - z" f+ T; V" y0 R6 u
  38.     regValue |=  (pLayerCfg->InputAlpha << DMA2D_POSITION_BGPFCCR_ALPHA);! \! |( C5 a; }4 Q
  39.   }0 q5 @/ X0 Q' a3 I# B' d' g

  40. 3 j& O3 N" g) f, k# x2 R# l+ w( W+ m
  41.   /* 配置背景层 */7 T" t: C, `# A/ ~/ w
  42.   if(LayerIdx == 0)' \' P4 P: ~7 D" b" ^" \
  43.   {" N& b# R, p9 k1 f
  44.     /* DMA2D BGPFCCR 寄存器 */8 S8 A0 M, t: \
  45.     MODIFY_REG(hdma2d->Instance->BGPFCCR, regMask, regValue);1 [& e1 H' K  U% K5 ?
  46. 1 B/ g( U# |# o0 E3 v) G% F+ k4 B" u
  47.     /* DMA2D BGOR 寄存器 */  ' m( b6 p3 p# J% m% F+ r
  48.     WRITE_REG(hdma2d->Instance->BGOR, pLayerCfg->InputOffset);7 R; W* D+ k+ a+ l4 q8 H
  49. + A% l% h% t+ r! H" u
  50.     /* DMA2D BGCOLR 寄存器 */
    * [8 C8 c) e3 x- d  |& F8 E
  51.     if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))/ w0 e2 D5 H8 I* ^; f
  52.     {   
    1 E; e5 y  b" Z* }: n, b" z* n+ I
  53.       WRITE_REG(hdma2d->Instance->BGCOLR, pLayerCfg->InputAlpha & ) l- A( C+ o. e( O
  54. (DMA2D_BGCOLR_BLUE|DMA2D_BGCOLR_GREEN|DMA2D_BGCOLR_RED));1 R7 w; ~  J- p; w" g" j. w7 `
  55.     }   
    - w5 e6 S: ^- ~4 ]- C' K/ V, V. T
  56.   }
    , j" E& N8 N  ?. }9 p" `
  57.   /* 配置前景层 */
    8 v0 m9 X$ y& ^( i1 p( S$ _
  58.   else4 f+ u; z3 S) L4 n$ N  K: C
  59.   {- R  Z9 _7 f9 S  c
  60.     if(pLayerCfg->InputColorMode == DMA2D_INPUT_YCBCR)4 ~0 U! H9 Y" {0 b4 w8 c
  61.     {& w8 e- i" c) Y  F* z' g
  62.       regValue |= (pLayerCfg->ChromaSubSampling << DMA2D_POSITION_FGPFCCR_CSS);0 h- E8 o: d8 u2 H- e
  63.       regMask  |= DMA2D_FGPFCCR_CSS;1 J/ s; v. ]( r; u( @- q1 y
  64.     }
    " \) c9 |" J; U; O

  65. : d9 }; [% ]' w5 s+ L
  66.      /* DMA2D FGPFCCR 寄存器 */2 O5 R- Q: ?9 [# L& `; H7 `
  67.     MODIFY_REG(hdma2d->Instance->FGPFCCR, regMask, regValue);
    8 e: h% P8 Z- Q5 Q, y
  68. 4 A7 o* L1 U3 \( `1 W1 E1 p* p9 I
  69.     /* DMA2D FGOR 寄存器 */. c: A" N* c- u( O
  70.     WRITE_REG(hdma2d->Instance->FGOR, pLayerCfg->InputOffset);      0 j# ?- W7 w& G5 x( F

  71. 1 s7 M. K3 ]# u0 ~( w
  72.     /* DMA2D FGCOLR 寄存器 */   
    + o( g3 N5 N( p6 s+ U: R5 z
  73.     if ((pLayerCfg->InputColorMode == DMA2D_INPUT_A4) || (pLayerCfg->InputColorMode == DMA2D_INPUT_A8))
    0 K% P1 N2 l7 w, e, @5 Y! c
  74.     {2 o9 u: |/ v8 K! @6 C0 z( B
  75.       WRITE_REG(hdma2d->Instance->FGCOLR, pLayerCfg->InputAlpha & ! |5 f: m1 m4 }$ ^, Y+ a* w! p
  76. (DMA2D_FGCOLR_BLUE|DMA2D_FGCOLR_GREEN|DMA2D_FGCOLR_RED));      , y) N3 _' }' y* k: I( i- J
  77.     }   
    % y; F& Q& O( @. v
  78.   }   # {* S0 [; V% T
  79.   /* DMA2D就绪 */3 V' P& T' Y6 i8 y, s1 X
  80.   hdma2d->State = HAL_DMA2D_STATE_READY;: U* l( m8 N2 p
  81. & n- C4 a- E5 k4 _2 V! v
  82.   /* 解锁 */
    ! I) U( A3 A- K3 {; M2 m+ |. c+ F1 ]
  83.   __HAL_UNLOCK(hdma2d);  4 k/ a+ g9 ]: v/ B
  84.   \4 s7 S$ a5 }/ J2 q9 y
  85.   return HAL_OK;1 q6 U. Z7 J' L* Z% X
  86. }
复制代码

) D9 I2 X# d2 e4 K函数描述:/ X- y/ H. q: ~4 f6 {& d
9 u0 F7 j* X- f& p7 P& k% ]
此函数主要用于配置DMA2D要转换的前景层和背景层,即输入颜色配置。而前面的函数HAL_DMA2D_Init配置的输出颜色。! j/ V0 i: J% k- `3 Y! b! Z

! A9 S9 ]/ d) R  Z0 G/ ~函数参数:
: [5 x' D% `( P
' y# E( |1 ~# _$ O) J( ?  T  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置DMA2D的基本参数,结构体变量成员的详细介绍看本章3.4小节。; v$ D8 a: N& E1 w6 J$ g
  第2个参数用于配置前景层和背景层,0表示背景层,1表示前景层。0 L9 `+ e9 S" ?) e& i% A2 i4 R- N
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
( B# A$ Y& W5 D使用举例:
$ M3 Y% O9 {9 p" P% J  d

  1. % U: N# y4 B$ ~
  2. DMA2D_HandleTypeDef Dma2dHandle;3 d$ {6 W: W; F! }: x4 P- E, M

  3. ; a7 n6 i6 T9 U. ^

  4. 7 O& K: g7 ]' L$ l: E
  5. /*##-1- 配置DMA工作模式,输出颜色格式和输出偏移 #############*/& z6 t) s/ ]' X  Q
  6. Dma2dHandle.Instance = DMA2D;
    , y+ k2 g5 T9 S
  7. - o, X9 k% r2 q: f% _
  8. Dma2dHandle.Init.Mode          = DMA2D_M2M;             /* 存储器到存储器模式 */
    1 m2 Q  H& m! x
  9. Dma2dHandle.Init.ColorMode     = DMA2D_OUTPUT_ARGB4444; /* 输出颜色格式 */
    0 o7 C# e- K# w6 N4 q8 T
  10. Dma2dHandle.Init.OutputOffset  = 0x0;                   /* 无输出偏移 */
    # l! c* T' N' s
  11. Dma2dHandle.Init.RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输出颜色的R/B通过不切换 */0 x; M2 x) O; S. ]
  12. Dma2dHandle.Init.AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输出颜色的Alpha通道数值不翻转 */
    % h$ F0 u; W8 k6 \& }4 m

  13. 7 m+ |- V+ ~9 B' }
  14. /*##-2- DMA2D 回调函数配置 ######################################*/8 M9 ~- I1 {/ q; P
  15. Dma2dHandle.XferCpltCallback  = TransferComplete;
    " D& Q& S& |; N; Y1 T
  16. Dma2dHandle.XferErrorCallback = TransferError;9 b1 A: }6 X9 I$ h( I

  17. ; r8 U8 H& h) p8 R% Q9 s3 ~
  18. /*##-3- 前景层配置 ###########################################*/
    0 g9 y- _0 i3 D; R7 Z" x
  19. Dma2dHandle.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;      /* 保持输入颜色格式中的Alpha值 */
    9 K' s( _; c' M! B5 s( c
  20. Dma2dHandle.LayerCfg[1].InputAlpha = 0xFF;                     /* 完全不透明 */
    9 B0 N" C) ^& R1 _! p- e8 j
  21. Dma2dHandle.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB4444; /* 输入颜色格式 */
    1 [( r- ~' N. k% T4 O0 E/ T# I
  22. Dma2dHandle.LayerCfg[1].InputOffset = 0x0;                     /* 输入无偏移 */* ?$ I. }8 ]4 |3 h) Q
  23. Dma2dHandle.LayerCfg[1].RedBlueSwap   = DMA2D_RB_REGULAR;      /* 输入颜色的R/B通过不切换*/6 O& d& ]/ N+ z7 `7 h+ z, ?+ J& J* p
  24. Dma2dHandle.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;   /* 输入颜色的Alpha通道数值不翻转*/
    % c7 c6 B. B" ~7 O2 T$ I7 ~
  25. 8 Q- c( u) J# Y7 b! i( b/ c
  26. /*##-4- DMA2D 初始化 ###############################################*/( g0 e( g9 I  v/ B8 m
  27. if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)
    : v2 u7 t/ |& U9 Z
  28. {
    5 F! @0 h0 U! t3 Q& C$ `
  29.     Error_Handler();
    + `' p# W5 j' \+ H0 s: c
  30. }# d+ y. H. y' p: R+ F

  31. # f0 j; u1 X) z5 l
  32. /* 配置前景层  */, Y/ |/ J: {4 V! E0 c% ?
  33. if(HAL_DMA2D_ConfigLayer(&Dma2dHandle, 1) != HAL_OK)8 X4 i% B' _! l: r6 j
  34. {
    ! {6 F: R6 E) Y% |: \; h: f5 p
  35.    Error_Handler();# z& s6 o7 a: M* o, O
  36. }
复制代码
3 ~# [: w; O/ L6 L: n
* Y& f3 k7 U: F# W
55.4.3 函数HAL_DMA2D_Start_IT
9 D$ }) b+ F  v/ N2 V& k函数原型:
7 G9 {. w1 z7 f& y6 G2 a/ ?$ ^* V* `: W' l
  1. HAL_StatusTypeDef HAL_DMA2D_Start_IT(DMA2D_HandleTypeDef *hdma2d, uint32_t pdata, uint32_t DstAddress, uint32_t Width,  uint32_t Height)9 e, B: ?" |; s+ ]. L7 [
  2. {# C7 j# K$ v! G* ~  n7 J% ~6 ^0 t
  3.   /* 检测函数形参 */1 e$ \! O5 V; u9 _! X! Q- r
  4.   assert_param(IS_DMA2D_LINE(Height));4 l- B# O1 j) a' G+ H
  5.   assert_param(IS_DMA2D_PIXEL(Width));
    # H3 \. m$ V  T% l
  6. 0 f" l( `4 J+ }4 k+ @
  7.   /* 上锁 */8 f2 u- Z* U6 U2 k0 F
  8.   __HAL_LOCK(hdma2d);" m  \  _: q, v) b3 W0 s: _
  9. ) a) k  L$ {& s. v' M2 ]) e+ s
  10.   /* 设置DMA2D外设状态 */, B( V3 d7 T  E3 c# c- W* _
  11.   hdma2d->State = HAL_DMA2D_STATE_BUSY;
    ) m- K, _" ]" ]7 h
  12. " k) F% i& O* J5 f  l+ i( b  P  V5 ^
  13.   /* 设置源地址,目的地址和数据大小 */" n0 {9 Z6 T' u) j
  14.   DMA2D_SetConfig(hdma2d, pdata, DstAddress, Width, Height);3 ?6 V3 o, R2 J) F3 K0 R* w5 h8 c
  15. + |, ]# ^, |, D3 q& E
  16.   /* 使能DMA2D的传输完成中断,传输错误中断和配置错误中断 */5 v( f9 D/ V8 ?7 l+ ^' C
  17.   __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE);2 y4 p9 h/ D: m9 f
  18. - R/ t9 |+ [$ c1 K* p4 I% d
  19.   /* 使能DMA2D */
    * a- \. H- S$ ^; h' P
  20.   __HAL_DMA2D_ENABLE(hdma2d);- s; i7 u! O' I1 P2 h
  21. ' y' {6 l( J3 D
  22.   return HAL_OK;
    4 {8 Y( e' l' k. I+ C3 m. A" t
  23. }
复制代码

3 V, S0 L$ y" L: y+ a/ k函数描述:" i2 O( P" H6 {0 ~( g, [8 L, M

0 x5 A! t3 c6 o# x, S7 N此函数用于启动DMA2D数据传输。由于采用的中断方式,此函数使能了多个DMA2D中断,不要忘记DMA2D中断服务程序的处理。
' r5 q$ O7 T/ ~6 g" i6 v" c
, k7 R( S- U6 T, u函数参数:
& N/ a' {% U- B* C* B+ Y) S
# Y- B8 {! M6 c) K  Z  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置DMA2D的基本参数,结构体变量成员的详细介绍看本章3.4小节。
; }8 E: U) F) \3 Y' g  第2个参数是源数据地址。3 G* o0 h' D0 e9 w; z  G9 R
  第3个参数是目的数据地址。& F8 ?4 a8 C0 d1 z
  第4个参数是源数据的长度,即每行的像素个数。
. j7 A3 b* c2 ]6 C9 ?6 s  第5个参数是源数据的高度,即行数。
* ]- V9 r. j; m  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。: b& c, B1 _1 R3 ?4 k# V
使用举例:
5 b% s5 v5 ~2 U# ]( {# G1 U5 B9 f% {& x8 C1 R8 y
  1. DMA2D_HandleTypeDef Dma2dHandle;5 @( |( p/ X( }8 x6 m, D! F: F  Z
  2. " F: |  [) [; P1 p: Q3 s% G0 F4 o
  3. if(HAL_DMA2D_Start_IT(&Dma2dHandle,            /* DMA2D句柄 */
    ! u1 y" k+ A; A# B' P
  4.                       (uint32_t)&BufferInput,  /* 源地址 */
    . S" [; O, ]$ S1 [- M
  5.                       (uint32_t)&BufferResult, /* 目的地址 */1 H, H+ x: {1 N2 E! r$ j) N
  6.                       SIZE_X,                  /* 源数据长度,单位像素个数*/6 H. R: y) n5 w- u
  7.                       SIZE_Y)                  /* 源数据行数 */
    - D( G, N* t" w+ K& c4 t
  8.    != HAL_OK)
    & y1 i. Q$ O0 f2 P3 Z* s! |
  9. {
    $ p( a: i. D( z- n& s
  10.    Error_Handler();
    % T( j& w; C/ s. u) K
  11. }
复制代码

4 b$ w$ @5 r& A( z55.4.4 函数HAL_DMA2D_BlendingStart_IT1 k8 ?) a( ]$ p& w
函数原型:, ?" x8 H7 O# x7 F

1 T4 Q. a, k1 b7 X  f
  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)- t- t' {. p, j
  2. {
    3 j) s3 ~1 v: Y; t4 B3 g
  3.   /* 检测参数 */4 G* X# O6 [6 z; O) K4 ~3 W. J
  4.   assert_param(IS_DMA2D_LINE(Height));
    - e6 h; m* W0 q. O: A1 J7 ]
  5.   assert_param(IS_DMA2D_PIXEL(Width));
    : B* K4 N' G; `* \4 O# ?2 w
  6. 9 B7 s3 S0 A" O# a/ }8 o9 M% f9 o1 }# W
  7.   /* 上锁 */
    4 m! E; D% a' D' ~  A
  8.   __HAL_LOCK(hdma2d);
    - N8 J3 r  b$ U% C' O# b

  9. * M, P% v# N; T, A+ _
  10.   /* 设置DMA2D外设状态 */
    ! }# E& [8 _+ B, v
  11.   hdma2d->State = HAL_DMA2D_STATE_BUSY;
    7 t# V6 a3 B+ x5 M2 N- ~, w* h
  12. * M' `; `, C4 L' j3 z8 R* k. @
  13.   /* 配置DMA2D源地址2 */) G9 D3 e5 Y. M  K9 S/ y/ c
  14.   WRITE_REG(hdma2d->Instance->BGMAR, SrcAddress2);$ z6 X' u7 d6 ?: [2 E

  15. ; _. Q$ `5 a" W9 c5 A% b
  16.   /* 配置源地址1,目的地址和数据大小 */* T# j1 W3 z3 j8 j$ D5 M
  17.   DMA2D_SetConfig(hdma2d, SrcAddress1, DstAddress, Width, Height);; b& L9 n( n5 ~# j7 e
  18. ' ~3 y& O2 q4 t+ \  f
  19.   /* 使能DMA2D传输完成中断,传输错误中断和配置错误中断 */
    ' Z' l' b- u( g
  20.   __HAL_DMA2D_ENABLE_IT(hdma2d, DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE);
    : {. q- ]# ~- W, |

  21. - X' b8 t) s: B' c" T9 y
  22.   /* 使能DMA2D */
    0 w  ?/ P" s1 P% Z" P3 O
  23.   __HAL_DMA2D_ENABLE(hdma2d);9 S8 S' q( `" V- a
  24. 7 Y4 ~1 @7 @3 f+ d3 ^
  25.   return HAL_OK;
    1 l" T! ^8 {+ V5 F5 k- b
  26. }
复制代码
. z- s- T& r' R- F3 {! }
函数描述:
& {1 \( ~; v$ J) V9 q
6 i' x& c  j1 w6 ~! F此函数用于启动DMA2D传输,除了数据传输以外,还支持颜色格式转换和颜色混合。由于采用的中断方式,此函数使能了多个DMA2D中断,不要忘记DMA2D中断服务程序的处理。
. {7 |& ^( ^/ ~) V5 z! a
$ H6 R# B- |: ]5 @' I: H: q; T函数参数:% D- S9 T+ h. `0 d
4 W* i- O3 q) J. T6 i  V8 a5 Y
  第1个参数是DMA2D_HandleTypeDef类型结构体指针变量,用于配置DMA2D的基本参数,结构体变量成员的详细介绍看本章3.4小节。
5 m! `8 M7 I0 }1 m5 b" [3 t. C  第2个参数是源数据地址1。
2 H0 @. E% k) s0 P* l, I9 Z  第3个参数是源数据地址2。4 o) r* [. ^+ r$ G$ ^. n, R
  第4个参数是目的数据地址。6 J2 L% Y5 K, e& j1 x
  第5个参数是源数据的长度,即每行的像素个数。4 z" j& z+ L: r. D
  第6个参数是源数据的高度,即行数。
) }% w# c: e8 J, b  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
; ~" N4 |3 }  R4 x4 @# u使用举例:
! T0 Y+ `% ~5 H2 y2 X/ u+ {$ q2 d0 L! M; Z
  1. DMA2D_HandleTypeDef Dma2dHandle;, z& {& j1 _# `# r) }

  2. ! s! b5 l  e, H
  3. if(HAL_DMA2D_BlendingStart_IT(&Dma2dHandle,           /* DMA2D句柄 */
    2 M5 ?! Y; `$ l0 Z$ K7 Z
  4.                              (uint32_t)&BufferInput1, /* 源地址1,前景色 */ 7 n/ d2 x! K$ d$ X9 S6 Z3 G; k
  5.                              (uint32_t)&BufferInput2, /* 源地址2,背景色 */8 Q) L! B. t, n1 t5 @
  6.                              (uint32_t)&BufferResult, /* 目的地址 */; C5 ?7 U: o2 L$ V+ K( I; A
  7.                               SIZE_X,                 /* 源数据长度,单位像素个数*/
    + B) |; _1 S0 v* O( D9 y
  8.                               SIZE_Y)                 /* 源数据行数 */
    2 t+ f' f: Y$ q6 ^, F4 a' G
  9.    != HAL_OK)
    & e; Y0 p) Z, e# R
  10. {6 ^- R) C% s- a
  11.    Error_Handler();
    1 c2 [0 h$ o, k1 U6 X
  12. }
复制代码
' b% t: \6 y! l) f
: |# F( M" S' E4 ?* `3 j& e, y
55.5 总结8 N( c1 a- m3 f6 `: V8 l& M
本章节就为大家讲解这么多,DMA2D功能比较重要,一定要做到熟练使用。
; k! J8 h0 ]5 s+ x2 o6 s7 V4 c& R8 G1 k& p' U! S% c; c
* b+ H0 ?8 c0 D. n; y8 D& @
7 c# m: R0 M4 u& t' w7 g
收藏 评论0 发布时间:2021-12-24 17:00

举报

0个回答

所属标签

相似分享

官网相关资源

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