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

【经验分享】STM32F7--->使用LTDC接口驱动RGBLCD,并使用DMA2D图形加速

[复制链接]
STMCU小助手 发布时间:2021-12-13 08:50
基础知识简介6 `3 k, G- v' c2 Z0 T0 _( w
RGBLCD

" L' X7 Y9 ~$ J8 x1.RGBLCD的信号
& {" t/ V) i! b6 _  |4 \
20210720093227878.png

/ b8 ]  {+ k/ s! H
# n8 {1 ~9 g4 [6 d2 y+ M' @: P一般的 RGB 屏有 24 根颜色数据线(RGB 各站 8 根,即RGB888 格式),这样可以表示最多 1600W 色,DE、VS、HS 和 DCLK,用于控制数据传输。
( m# S4 O" Z% d4 [5 R* G+ y' X% w0 R( i& h: Y+ P* M' r1 |2 \
2.RGBLCD驱动模式
: \0 o* x2 q9 N" m
其驱动模式主要分为两种
5 t: c, J5 Y3 Y3 L% N$ T: y+ B2 c' O1 ~$ s: }# m  ?5 d
      DE模式
1 s" N2 c  `' q# K- ]      DE 模式使用 DE 信号来确定有效数据,DE 为高/低时,数据有效% D  D% s1 G1 s) \
      HV模式
* U- J/ C; M* i6 p; E& P      HV模式需要行同步和列同步,来表示扫描的行和列
" I! b+ \( P$ g2 Z+ G1 O5 d4 q/ h* M8 d
LTDC1 U# }0 f: ]7 y% {
STM32F767xx 系列芯片都带有 TFT LCD 控制器,即 LTDC,通过这个 LTDC,STM32F767可以直接外接 RGBLCD 屏,实现液晶驱动。
8 v$ b- [2 F- a% O: @+ M9 ^. }
1 j9 b2 A8 |$ g. y  y1 z7 p1.信号线
" x+ h- R+ J& o0 f8 ~) `3 d* TSTM32F767 核心板板载的 LCD 接口引出为了,节省 IO,并提高图片显示速度,使用 RGB565 颜色格式,这样只需要 16 个 IO 口,当使用 RGB565 格式的时候,LCD 面板的数据线,必须连接到 LTDC 数据线的 MSB
: f% ?$ @$ T1 s/ w# L/ D. D, R4 U3 K2 }$ l7 Q( o$ l
20210720100712790.png

7 Z; @5 Z" a. ]% W  a$ A; R
! N& I0 A4 \0 d( l) [2.图像处理单元
* `" v9 N1 z, s/ B% s7 ` 先从 AHB 接口获取显存中的图像数据,然后经过层 FIFO(有 2 个,对应 2 个层)缓存,每个层 FIFO 具有 64*32 位存储深度,然后经过像素格式转换器(PFC),把从层的所选输入像素格式转换为 ARGB8888 格式,再通过混合单元,把两层数据合并,混合得到单层要显示的数据,最后经过抖动单元处理(可选)后,输出给 LCD 显示。
. e: L, f4 W; Y& k& ^) W 混合单元首先将第一层与背景层进行混合,随后,第二层与第一层和第二层的混合颜色结果再次混合,完成混合后,送给 LCD显示。
' ~; N7 j! f+ t. K4 D/ E
/ _+ ~: J1 K, L- c
20210720102457112.png
; N$ @) T; s: x: W4 p! P
  P" o& N! p! P, A$ R, u
3.AHB 接口
) p' C# f7 o% q% s. D4 ]9 H 由于 LTDC 驱动 RGBLCD 的时候,需要有很多内存来做显存,比如一个 800480 的屏幕,按一般的 16 位 RGB565 模式,一个像素需要 2 个字节的内存,总共需要:800480*2=768K 字节内存,STM32 内部是没有这么多内存的,所以必须借助外部 SDRAM,而 SDRAM 是挂在AHB 总线上的,LTDC 的 AHB 接口,就是用来将显存数据,从 SDRAM 存储器传输到 FIFO 里面。  M" {) E( ~9 B, i+ Q' y# c! Q% k
1 `& J: q6 O, n1 L& y) p% i
4.LTDC相关寄存器及使用方法

2 ?* N* |9 b' k7 ]  N4 ALTDC 的各种配置寄存器以及状态寄存器,用于控制整个 LTDC 的工作参数,
: w& _' e# i# L# F2 F6 l* ^; q主要有:各信号的有效电平、垂直/水平同步时间参数、像素格式、数据使能等等。/ Q9 n! n/ d. [2 P) U+ Y
如果 RGBLCD 使用的是 DE 模式,需要设置如下参数,然后 LTDC会根据这些设置,自动控制 DE 信号。/ f# u. P& n# N4 s% Y( O
4 x& f8 k/ x: Y0 L& @5 M
LTCD全局控制寄存器 LTCD_GCR
+ H; y7 i9 s$ k, C
9 B  `0 J1 a' T: T
20210720104228854.png
' O1 [- Y% }8 A! K) y

0 X& d  C2 N& L) d9 R7 m
]V@HJS%I_Y[%1XLYT61%0@2.png

3 Y* ~% Z6 ]/ Y1 v0 r3 Q& ^
# z/ C+ F3 J2 `LTCD同步大小寄存器 LTDC_SSCR
" T0 n2 O1 y5 i0 ]* ^该寄存器用于设置垂直同步高度(VSH)和水平同步宽度(HSW)9 K; d# c: V/ z( S9 r

, Q; S) k5 S! x' Y, H: X; d' T- z
20210720104959506.png
7 I( U* o, @$ n1 u0 e
, B) k* D6 Y+ `6 k; n. v
0PRMT7%Y[QF2O{1W`AQ82~7.png
" G- l9 R, Q2 J: x' c

3 }2 t! Q  h0 H% D5 P9 M* I3 A. _
LTDC有效宽度配置寄存器 LTDC_AWCR
% G- L  b! N4 J3 l0 V  q这里所说的有效高度和有效宽度,是指 LCD 面板的宽度和高度,构成分辨率  G9 R5 B( l$ L" u0 N5 ~& l4 L% A0 Z
8 Q5 e2 N6 q4 s  f+ ^
20210720110024135.png

5 K$ B7 i1 M, q. L
5 p8 Y6 U: C7 C; ^/ h1 u
[AREI`HGZ@RRR{J@MJC8W]8.png
( Q2 G  @" E1 n" n$ I

" Y  s3 ^( n8 W& E' _8 X9 h     
8 B0 `( ]$ }9 B6 G8 P1 OLTDC 总宽度配置寄存器 LTDC_TWCR

8 T+ @8 K4 c# o0 z9 I' p  `6 y1 H9 T: x7 c6 I5 t
20210720110931326.png

7 ]3 U8 d, h, E9 F" n3 _
! H9 K, u5 o. Q( |3 O. a3 T
O6G8SGZNHK4ZYO{)JN[]USW.png
: j* W% J# g7 c2 l( u
2 v# i1 Z- F+ d0 T7 t+ o, G* B- S7 U  V
       ( O) W6 T/ e' y4 w7 I
LTDC 背景色配置寄存器 LTDC_BCCR
2 V+ K- V1 w* U8 ]% ]该寄存器定义背景层的颜色(RGB888),通过低 24 位配置,我们一般设置为全 0 即可。
& Q& e3 {' s" Y) I8 _4 P, Z- b; Q/ u
2 |' h8 ^7 G7 A  Q! P4 l. A
20210720111141846.png

2 d; ]9 c. p3 d6 F* X3 r% Y/ R. Z' @, \2 I6 f
LTDC当前位置状态寄存器 LTDC_CPSR
$ R% V" Z  K  M) I, E
6 a0 B9 |6 C1 I8 J- z  I; y9 R2 n8 z
a3355e745c2c73657ef826bf1a8f42f5.png

1 g: H4 g( a6 ]" @, F8 Q9 H4 o5 ]# s# ~
CXPOS[31~16]:返回当前X坐标位置' d3 g1 ^. }1 r7 N) V- W1 L7 b* K
CYPOS[15~0]:返回当前Y坐标位置
6 K9 D6 V6 I, ?3 ?  Q$ @/ T
% l! x2 T' {7 h9 DLTDC当前显示状态寄存器 LTDC_CDSR+ F( \7 Q9 u) D8 c
此寄存器返回由 HSYNC、VSYNC 和水平/垂直 DE 信号控制的当前显示阶段的状态
6 v8 A+ d6 l# J7 |. V5 N6 b4 ?1 [" y% `6 }* u* p. N, \" v' ]/ v6 J& x
c1e72a8f7ff1155cd5391d05ba83e42d.png
9 e" N6 V7 \7 J( n6 Q$ V
& k, N# `, m2 \# M& V
位 31:24 保留,必须保持复位值
& G9 j! t  Q% j# r6 |, a0 G位 3 HSYNCS:水平同步显示状态 (Horizontal Synchronization display Status)
4 N4 n+ ~3 O  L" K  o0 D0:低电平有效
/ v! S. f4 J4 G- j" ]# b1:高电平有效
$ t3 b2 y: L& P9 q3 e, @( _6 T位 2 VSYNCS:垂直同步显示状态 (Vertical Synchronization display Status)
$ @/ N4 [0 i0 W6 L  G# w7 _9 m0:低电平有效
: v1 @8 `  h/ ?1:高电平有效
! b- q9 Y& z, I6 T+ Q; G- S: L位 1 HDES:水平数据使能显示状态 (Horizontal Data Enable display Status)/ D3 x" v. D5 ^6 O4 C
0:低电平有效; f* h1 G5 r# p# D/ a# ~- ?4 V
1:高电平有效
' ^0 s# M) z4 c* ~位 0 VDES:垂直数据使能显示状态 (Vertical Data Enable display Status)
" e  d! F4 N- f! M6 V0:低电平有效' [0 a* c& e1 m! p9 s5 m; }
1:高电平有效
2 ]$ q( m, l/ F) w8 ?* V3 l5 u1 W  v& Y$ X+ }) k" E1 r( ]) M; x( Q& j
LTDC 的层颜色帧缓冲区地址寄存器 LTDC_LxCFBAR(x=1/2)
: W: I+ o# c2 m1 {/ p) E该寄存器用来定义一层显存的起始地址。STM32F767 的 LTDC 支持 2 个层,所以总共有两个寄存器,分别设置层 1 和层 2 的显存起始地址。) r- t; p2 A  }% S3 a* M

1 g8 t( x2 N& p+ K) x  r, B
20210720111336311.png

- F! h5 T$ C1 U. \
$ d2 ?/ Q& m8 i2 y6 \" RLTDC 的层像素格式配置寄存器 LTDC_LxPFCR(x=1/2)
, v" n9 Q5 V8 ]; A该寄存器只有最低 3 位有效,用于设置层颜色的像素格式,一般使用 RGB565 格式,即该寄存器设置为:010 即可。
+ K# [- m& V* K) K( D& y5 V$ p8 I4 Y
STQ}OUE_D7Z(33OZ_E@73.png
  o& |5 x( S- S

6 c2 [5 ]4 A6 l+ k- a& ~. E: [
$ O: _) ]4 I( b6 P# n      
: S! I# d" g) f- s! H" G9 B8 u3 QLTDC 的层恒定 Alpha 配置寄存器 LTDC_LxCACR(x=1/2)
- G6 m& [) }2 I7 m, ?! w/ G该寄存器低 8 位(CONSTA)有效,这些位配置混合时使用的恒定 Alpha。恒定 Alpha 由硬件实现 255 分频。
, T9 G$ ?8 d. h5 \. P9 q
3 T8 O' ]( F0 @! k& e8 e
20210720112235516.png
8 V3 U2 C. b" S; u3 \
! \& h9 r& U( t* H# ]) h  q8 E
LTDC 的层默认颜色配置寄存器 LTDC_LxDCCR(x=1/2)
6 r- H& D8 b* l
该寄存器定义采用 ARGB8888 格式的层的默认颜色。默认颜色在定义的层窗口外使用或在层禁止时使用。一般情况下,用不到,所以该寄存器一般设置为 0 即可。8 `; [' z* o2 C) h. k1 V
% g  o) O% M* x4 j
20210720112604555.png

, J- P# T6 m1 O9 e
7 [0 X8 B# I( m$ G" k8 [LTDC 层混合系数配置寄存器:LTDC_LxBFCR(x=1/2)
# [( ?5 A* Z" z+ b, Y+ _该寄存器用于定义混合系数:BF1 和 BF2。BF1=100 的时候,使用恒定的 Alpha 混合系数(由LTDC_LxCACR寄存器设置恒定Alpha值),BF1=110的时候,使用像素Alpha恒定Alpha。像素 Alpha 即 ARGB 格式像素的 A 值(Alpha 值),仅限 ARGB 颜色格式时使用。在 RGB565格式下,我们设置 BF1=100 即可。BF2 同 BF1 类似,BF2=101 的时候,使用恒定的 Alpha 混合系数,BF2=111 的时候,使用像素 Alpha恒定 Alpha。在 RGB565 格式下,我们设置 BF2=101即可。1 Y8 V$ Z; R; {( G  R$ Y
通用的混合公式为:BC=BF1C+BF2Cs: j4 x9 ?/ F' ?7 G
其中:BC=混合后的颜色;BF1=混合系数 1;C=当前层颜色,即我们写入层显存的颜色值;BF2=混合系数 2;Cs=底层混合后的颜色,对于层 1 来说,Cs=背景层的颜色,对于层 2 来说,Cs=背景层和层 1 混合后的颜色。$ ]6 a0 n8 }/ T2 r# B; L& q# e

# E; A/ S1 e7 l% c9 C
2021072011293763.png
& t1 Y; ~; M, X2 @% |2 Z7 [
$ T/ {1 A$ |, N* ^3 J
LTDC 的层窗口水平位置配置寄存器 LTDC_LxWHPCR(x=1/2)
( e, T/ b+ e; W6 o6 Z) @0 i3 h
该寄存器定义第 1 层或第 2 层窗口的水平位置,第一个和最后一个像素/ _2 G7 ~. f7 j& {) v, i- n
! W0 O4 G/ {9 ^7 u6 |6 O4 u' D
20210720113448290.png
; ^$ K! @* w: f' l

9 S$ \" \: }% C+ V: H4 X% aWHSTPOS:窗口水平起始位置,定义层窗口的一行的第一个可见像素,
. D2 J2 J# \. W1 hWHSPPOS:窗口水平停止位置,定义层窗口的一行的最后一个可见像素0 H) U9 g8 `$ ?" ^. e: K# n3 u
7 @4 m+ u0 V# K1 N; q0 o+ f
LTDC 的层窗口垂直位置配置寄存器 LTDC_LxWVPCR(x=1/2)

; }, h, H: B% @+ N/ O该寄存器定义第 1 层或第 2 层窗口的垂直位置(第一行或最后一行)
' z7 `8 X: E, B8 ~! c
5 l# c' {8 J8 Z; G
20210720133247145.png

" ^7 S0 G  p  M" R2 Y. i( t" W( U9 T2 Y9 A1 E
WVSTPOS:窗口垂直起始位置,定义层窗口的第一个可见行。5 I* O" c- x/ ]/ Y* ]3 H; {
WVSPPOS:窗口垂直停止位置,定义层窗口的最后一个可见行。) }' f. A9 v( G* Z) q5 V+ h; O
: G6 |# ]  X  U- w. M) k
LTDC 的层颜色帧缓冲区长度寄存器 LTDC_LxCFBLR(x=1/2)- Z  p# p+ u, s) e
该寄存器定义颜色帧缓冲区的行长和行间距。
' m. a0 e$ g  A" b$ e6 o# V9 u# j. m; s, ?9 z- T% [( _; c
20210720133802157.png

( Q- {8 u1 b* t- ]
- A3 H) g5 ]" RCFBLL:这些位定义一行像素的长度(以字节为单位)+3。
* F- N* m* e/ b, |, Z5 ]行长的计算方法为:有效宽度 * 每像素的字节数 + 3。
0 w( `* H- `2 X. P; E比如,LCD 面板的分辨率为 800480,有效宽度为 800,采用 RGB565 格式,那么 CFBLL 需要设置为:8002+3=1603。2 x" A. c9 N7 ]0 Q5 l
CFBP:这些位定义从像素某行的起始处到下一行的起始处的增量(以字节为单位)。
" Z, X: e# |, ^# N! l# I$ c这个设置,其实同样是一行像素的长度,对于 800480 的 LCD 面板,RGB565 格式,设置 CFBP 为:8002=1600 即可。
( X) m; \: q5 H; Q) e, X5 F4 ^& u
. r) T2 W9 M4 v8 d6 @1 y" JLTDC 的层颜色帧缓冲区行数寄存器 LTDC_LxCFBLNR(x=1/2)* m# _' m5 ]) J/ M2 w3 p
该寄存器定义颜色帧缓冲区中的行数。! f. K8 g* r5 M
比如,LCD 面板的分辨率为 800*480,那么帧缓冲区的行数为 480 行,则设置 CFBLNBR=480 即可; {. H. {. B' C9 v- P
- h4 u9 t. k3 h9 i/ L) D" c
20210720133424485.png

+ g1 k! V- C# L
2 b4 G# e6 U* a6 c! V- E5.时钟域! w/ m7 `/ I! v, h* l1 l
LTDC 有三个时钟域:AHB 时钟域(HCLK)、APB2 时钟域(PCLK2)和像素时钟域(LCD_CLK),
& \4 S/ k) X& {. Z8 n2 J& g5 DAHB 时钟域用于驱动 AHB 接口,读取存储器的数据到 FIFO 里面;
0 f: F- a3 ?8 d4 j8 \" _. R$ b" KAPB2 时钟域用于配置寄存器;" I5 t$ ]1 z- v' `' _
LCD_CLK像素时钟域则用于生成 LCD 接口信号,LCD_CLK 的输出应按照 LCD 面板要求进行配置。& b" K* T  \2 ~8 l9 S6 g9 q( z4 O# u
+ p5 F% Y- ?; k5 l
DMA2D
$ c: M& `' H8 |5 Y+ Y( S1 T- l为了提高STM32F767的图像处理能力,ST公司设计了一个专用于图像处理的专业 DMA,通过 DMA2D 对图像进行填充和搬运,可以完全不用CPU 干预,从而提高效率,减轻 CPU 负担。
. h3 v: |8 z$ T6 r" q* h3 g% {  R
9 _& W0 v1 A. W8 ?* n9 x7 E它可以执行下列操作:/ h( X9 O( G' m; d
用特定颜色填充目标图像的一部分或全部(可用于快速单色填充)
" f" G3 j; X. p. ]1 z! V将源图像的一部分(或全部)复制到目标图像的一部分(或全部)中(可用于快速图像填充)
1 b( x2 ^  m- V/ y& r% C2 k0 }通过像素格式转换将源图像的一部分(或全部)复制到目标图像的一部分(或全部)中& K9 {. R. _1 d- E2 D
将像素格式不同的两个源图像部分和/ 或全部混合,再将结果复制到颜色格式不同的部分或整个目标图像中
1 B( f. b- g4 t* M: `0 R/ l7 S: N$ y4 W' D3 a8 e% D
# K6 R- o6 O4 [3 G! G) j
DMA2D 有四种工作模式,通过 DMA2D_CR 寄存器的 MODE[1:0]位选择工作模式:
/ l" Q; `) [! N7 y/ O" ?* e1, 寄存器到存储器
9 S9 j5 l8 t- y5 Z" H; p0 \2, 存储器到存储器# Z( S; q" p4 y, C8 [( j$ @
3, 存储器到存储器并执行 PFC8 i- l- C9 s) ^8 L  g9 G
4, 存储器到存储器并执行 PFC 和混合
6 Z9 I) l3 i7 w  D  T1 f5 s" W
$ r* t7 w" O* w# ^$ ]4 R5 Y. C  u
) Q% _. s0 I; N2 r% e寄存器到储存器$ m5 U3 W' c4 X/ k  D; j
寄存器到存储器模式用于以预定义颜色填充用户自定义区域,也就是可以实现快速的单色
2 Q# K$ j" X; M% s填充显示,比如清屏操作。
, u* @2 B6 b4 m7 Q8 t' _9 F在该模式下:颜色格式在 DMA2D_OPFCCR 中设置,DMA2D 不从任何源获取数据,它只& M# P: f1 M1 [7 ~( |
是将 DMA2D_OCOLR 寄存器中定义的颜色写入通过 DMA2D_OMA 寻址以及 DMA2D_NLR 和
. ~0 ]; L* }# a0 T0 RDMA2D_OOR 定义的区域
: Z% M  i4 r  Z0 ~* G, h/ T: n
( P' {" N" i2 J- Z1 K( a4 x# N# ?9 U% o" \8 X5 w/ H
储存器到储存器
# |  s8 s1 p0 }- W/ I8 E9 v) a该模式下,DMA2D 不执行任何图形数据转换。前景层输入 FIFO 充当缓冲区,数据从
* K2 w9 w6 _) g8 PDMA2D_FGMAR 中定义的源存储单元传输到 DMA2D_OMAR 寻址的目标存储单元,可用于快, V  F7 j. I1 o7 D0 m
速图像填充。DMA2D_FGPFCCR 寄存器的 CM[3:0]位中编程的颜色模式决定输入和输出的每像
- n' `" g8 e9 J2 r+ ^" X; P素位数。对于要传输的区域大小,源区域大小由 DMA2D_NLR 和 DMA2D_FGOR 寄存器定义,
+ O. s! [+ c5 g: m: I0 ^2 a6 ~目标区域大小则由 DMA2D_NLR 和 DMA2D_OOR 寄存器定义。1 y5 g0 d- i5 e1 g) q

) F' D2 R3 m8 x, i2 f5 b) V# W& |* `" h6 S
以上两个工作模式,LTDC 在层帧缓存里面的开窗关系都一样的,经过如下三个寄存器的配置,就可以确定窗口的显示位置和大小。
$ d% m/ s9 `6 K7 h0 l9 M; I(1). 窗口显示区域的显存首地址由 DMA2D_OMAR 寄存器指定,/ D" x% f' Z4 e$ Q8 S. ]
(2).窗口宽度和高度由DMA2D_NRL 寄存器的 PL 和 NL 指定
# N: z$ i% o+ B, H1 \/ K6 N+ Y) b(3).行偏移(确定下一行的起始地址)由 DMA2D_OOR寄存器指定,: i3 ]9 W/ x; J; ?: S# L! V+ X  ^

' t- H' O/ N8 u9 K( e$ m
20210720170136697.png
# Q# G9 V, m9 s7 l/ a
( J7 E- g9 T+ v7 q$ V: I' ]
! O! k/ j. Z5 l+ }
在寄存器到存储器模式下,在开窗完成后,DMA2D 可以将 DMA2D_OCOLR 指定的颜色,
6 L: q8 Q1 ^# ~) ~6 F$ [自动填充到开窗区域,完成单色填充。
5 z. B1 u. N$ y/ M- A1 N7 e2 z: H
; f# C1 w! G; g9 v+ F
( m; l% \6 ?- X$ N在存储器到存储器模式下,需要完成两个开窗:前景层和显示层,完成配置后,图像数据从前景层拷贝到显示层(仅限窗口范围内),从而显示到 LCD 上面。显示层的开窗如上图所示,前景层也和上图类似,只是 DMA2D_OMAR 寄存器变成了DMA2D_FGMAR,DMA2D_OOR寄存器变成了DMA2D_FGOR,DMA2D_NRL则两个层共用,然后就可以完成对前景层的开窗,确定好两个窗口后,DMA2D 就将前景层窗口内的数据,拷贝到显示层窗口,完成快速图像填充。
. ~. K) t5 [$ t5 s" f1 [! ?: U
2 q8 H' q0 k; w: x% ^7 C9 r  J) d) ^8 @
DMA2D相关寄存器
3 U4 U& e! I& Z4 q8 ^8 v. g; cDMA2D控制寄存器 DMA2D_CR8 d0 V' X: m; n# B' z
该寄存器,主要是MODE 和 START 这两个设置% ~! q/ L% P0 F& R' I7 _# C

1 u9 i2 p# p, U3 D3 e4 B* ]4 f
20210720172154901.png
" d4 |1 F. Q2 n/ j
, Q" h- L- T2 ~# `% m8 d
MODE:表示 DMA2D 的工作模式,3 U# G4 n3 |+ j
00:存储器到存储器模式;01:存储器到存储器模式并执行 PFC;& h4 W+ G- m; d" f
10:存储器到存储器并执行混合;11,寄存器到存储器模式;
2 b9 F) M1 F& ]6 P7 }. mSTART:该位控制 DMA2D 的启动,在配置完成后,设置该位为 1,启动 DMA2D 传输。
9 ?$ j% a4 t/ i' C5 F& p
1 i+ m/ L7 E. K5 W/ `; tDMA2D输出 PFC 控制寄存器 DMA2D_OPFCCR$ M) K: _5 C% c8 x
该寄存器用于设置寄存器到存储器模式下的颜色格式
1 l( R% e0 B: B, Y/ |3 C3 i4 @0 j1 o8 V1 c$ K. S( F8 z# i4 }+ b
20210720172538112.png
0 |$ O0 y8 X( R/ K
( n8 N8 @) L4 C; t% i5 X
只有最低 3 位有效(CM[2:0]),表示的颜色格式有:
: A7 z$ {! P* R, P' J. j* W000,ARGB8888;001:RGB888;010:RGB565;0 G1 H% L: B- |
011:ARGB1555;100:ARGB1444。! E" j2 R6 f5 @3 z1 e
我们一般使用的是 RGB565 格式,所以设置 CM[2:0]=010 即可。0 m! N6 R4 s& G3 P+ V& l

+ w+ q. H5 P. a. A3 [) ~4 ADMA2D前景层 PFC 控制寄存器:DMA2D_FGPFCCR, p& g$ i/ S4 H$ V/ |4 R
; o0 v  @3 L9 D0 F  U/ e1 [
20210720173213773.png

) G1 T; [3 s1 T  Y/ n- y/ ~: Y1 [8 S9 w9 y3 M( p% l
该寄存器,低 4 位:CM[3:0],用于设置存储器到存储器模式下的颜色格式,这四个位表示的颜色格式为:
1 w5 Q5 f2 z2 C& b6 Y! i0000:ARGB8888;0001:RGB888;0010:RGB565;
+ G# s9 n- q7 d7 V9 G; \0011:ARGB1555;0100:ARGB4444;0101:L8;
$ x8 q$ ^  g: y9 \4 ~/ v0110:AL44;0111:AL88;1000:L4;1001:A8;1010:A4;* m5 j4 t& }' D
我们一般使用 RGB565 格式,所以设置 CM[3:0]=0010 即可。
+ S9 T0 M! P0 j8 B3 s  q4 G0 E( l# f
DMA2D输出偏移寄存器 DMA2D_OOR" F0 P6 @7 G# F+ p- E3 C6 @

* A9 P4 X1 h( K1 F
20210720174740982.png
3 e  C* p, `* h+ ]! a& L% A
该寄存器仅最低 14 位有效(LO[13:0]),用于设置输出行偏移,作用于显示层,以像素为" K7 J6 X9 z2 P8 [
单位表示。此值用于生成地址。行偏移将添加到各行末尾,用于确定下一行的起始地址。
8 c# \8 G* I5 h5 i# C同样的,还有前景层偏移寄存器:DMA2D_FGOR,该寄存器同 DMA2D_OOR 一样,也是
; K) H0 L7 s% C7 m: O低 14 位有效,用于控制前景层的行偏移,也是用于生成地址,添加到各行末尾,从而确定下一
" R1 b# `$ A- _1 T7 r1 a' c行的起始地址。
7 s- e! h( `# ~9 x6 U5 d7 w6 t3 V6 M  i) E
DMA2D输出存储器地址寄存器 DMA2D_OMAR
  ^* ^* l  W3 `; o: h* n
& L1 v/ E" g1 ]8 {
20210720175051288.png
; e: H: h4 t! {

4 K* _0 q; H8 d+ `7 ?该寄存器设置由 MA[31:0]设置输出存储器地址,也就是输出 FIFO 所存储的数据地址,该地址需要根据开窗的起始坐标来进行设置。以 800480 的 LCD 屏为例,行长度为 800 像素,假定帧缓存数组为:ltdc_framebuf,我们设置窗口的起始地址为:sx(<800),sy(<480),颜色格式为 RGB565,每个像素 2 个字节,那么 MA 的设置值应该为:
) |0 g) ~  V' ~+ D- U6 m: r*MA[31:0]= framebuf+2(800sy+sx)**
2 B- P! `0 x- a6 r* h+ x% `同样的,还有前景层偏移寄存器:DMA2D_ FGMAR,该寄存器同 DMA2D_OMAR 一样,  H" {# `6 b! Q% f
不过是用于控制前景层的存储器地址,计算方法同 DMA2D_OMAR。
' s  {" z2 G1 Z2 q* p, R0 Y2 m$ }
DMA2D行数寄存器 DMA2D_NLR
6 J5 }$ R: R9 F0 Z2 p% B
9 S7 x! R" M# s6 C
20210720180044872.png
& ?8 n! G$ X8 G* A
该寄存器用于控制每行的像素和行数,该寄存器的设置对前景层和显示层均有效,通过该寄存器的配置,就可以设置开窗的大小。其中:
" V: k$ n2 B0 {NL[15: 0]:设置待传输区域的行数,用于确定窗口的高度。
" H  v" g& u2 S* Y) |PL[13: 0]:设置待传输区域的每行像素数,用于确定窗口的宽度! l8 |# f' ]- L0 r) {+ {0 e: W- f7 q! q
7 F3 d7 V# Z5 f; q( \: a
DMA2D输出颜色寄存器 DMA2D_OCOLR8 S' @0 p& R7 R8 U
5 Q& Q7 C  W* |: p! ?8 s
20210720180520678.png
/ e* ?1 {  k5 m& i4 [; p
该寄存器用于配置在寄存器到存储器模式下,填充时所用的颜色值,该寄存器是一个 32位寄存器,可以支持 ARGB8888 格式,也可以支持 RGB565 格式。我们一般使用 RGB565 格式,比如要填充红色,那么直接设置 DMA2D_OCOLR=0XF800 就可以了。
7 P. k+ D/ z7 J3 `8 M3 E% Z9 X: i+ r1 {5 S; _( ]% f* p4 ?
DMA2D中断状态寄存器 DMA2D_ISR7 l& l2 E% F# J6 }& @

0 B/ ~/ X) s3 }, k
2021072018063162.png
2 }7 |1 K. G' Y( `
! z* v( P- m# Y6 X5 J# X
该寄存器表示了 DMA2D 的各种状态标识# J# R/ y3 ?# w0 }
TCIF 位,表示 DMA2D 的传输完成中断标志。当 DMA2D 传输操作完成(仅限数据传输)时此位置 1,表示可以开始下一次 DMA2D 传输了
) }# T8 D6 ^3 e: W0 XDMA2D 中断标志清零寄存器:DMA2D_IFCR,用于清除 DMA2D_ISR 寄存器对应位的标志。通过向该寄存器的第 1 位(CTCIF)写 1,可以用于清除 DMA2D_ISR 寄存器的 TCIF 位标志。1 j4 ?" h3 P! u- p6 Y' A& k; M7 F

, x' a& e8 O. l0 @4 a, P) H0 c5 W
LTDC具体使用步骤
7 {9 u  c+ q4 k  ~9 K1.使能 LTDC 时钟,并配置 LTDC 相关的 IO 及其时钟使能。3 ^8 N( T  J! n
使用 LTDC,当然首先得开启其时钟。+ R9 J( X5 ~; D) Z  ^1 i  o
然后需要把 LCD_R/G/B 数据线、LCD_HSYNC和 LCD_VSYNC 等相关 IO 口,全部配置为复用输出,并使能各 IO 组的时钟。1 C1 F7 ]& l8 k& f9 x- U  n( ^% [

) e" e; O; @5 [2 K" m: R
  1. //LTDC底层IO初始化和时钟使能
    - F& T1 D+ l3 d, J9 f
  2. //此函数会被HAL_LTDC_Init()调用
    : I7 m* `7 @' q% |" d
  3. //hltdc:LTDC句柄& |0 o) P7 e) q
  4. void HAL_LTDC_MspInit(LTDC_HandleTypeDef* hltdc)
    2 g9 x" n. G5 I- i, i/ {. U
  5. {/ H. y% C9 e' Q
  6.     GPIO_InitTypeDef GPIO_Initure;
    3 B& m0 p3 r8 S: g9 k" s4 j* P

  7. % `& v: X6 c" f7 ~( H
  8.     __HAL_RCC_LTDC_CLK_ENABLE();                //使能LTDC时钟1 O% N: c5 R# q
  9.     __HAL_RCC_DMA2D_CLK_ENABLE();               //使能DMA2D时钟
    $ n' @# X2 F3 B6 h
  10.     __HAL_RCC_GPIOB_CLK_ENABLE();               //使能GPIOB时钟, f$ w; m, R  x/ d. k
  11.     __HAL_RCC_GPIOF_CLK_ENABLE();               //使能GPIOF时钟
    * o; y$ z0 @4 u, l1 P
  12.     __HAL_RCC_GPIOG_CLK_ENABLE();               //使能GPIOG时钟
    7 I7 J$ _4 z1 d6 x' ^  J
  13.     __HAL_RCC_GPIOH_CLK_ENABLE();               //使能GPIOH时钟- t' A- q1 [6 S' H
  14.     __HAL_RCC_GPIOI_CLK_ENABLE();               //使能GPIOI时钟  w+ L2 L7 k; Q
  15. $ T! v, M5 H; T( }4 b
  16.     //初始化PB5,背光引脚, [! @; f3 ^; Y/ e' }
  17.     GPIO_Initure.Pin=GPIO_PIN_5;                //PB5推挽输出,控制背光( K1 i0 D2 @+ H1 k5 m
  18.     GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;      //推挽输出4 ^& p* W! z9 [4 o' u
  19.     GPIO_Initure.Pull=GPIO_PULLUP;              //上拉
    5 [8 B# s" R- u: a6 M) s+ B( S
  20.     GPIO_Initure.Speed=GPIO_SPEED_HIGH;         //高速
    " X& J, S, ]4 ^" H
  21.     HAL_GPIO_Init(GPIOB,&GPIO_Initure);
    0 ]. o7 @0 L9 L; I
  22. " g) H. |% v+ ^$ N) ?
  23.     //初始化PF10" l  }2 W1 Q* U$ p9 ]5 b1 c7 K4 G
  24.     GPIO_Initure.Pin=GPIO_PIN_10; 7 n4 j. {& s1 V1 x
  25.     GPIO_Initure.Mode=GPIO_MODE_AF_PP;          //复用* d& P3 L3 J0 v# D, B, C1 u5 F& E
  26.     GPIO_Initure.Pull=GPIO_NOPULL;
    ( v3 P( ^, `! h; E1 ]1 B" g
  27.     GPIO_Initure.Speed=GPIO_SPEED_HIGH;         //高速
    - g% p. x: d' C0 j
  28.     GPIO_Initure.Alternate=GPIO_AF14_LTDC;      //复用为LTDC
    ) l+ x. H" u' L9 x- M7 U3 E
  29.     HAL_GPIO_Init(GPIOF,&GPIO_Initure);
    # a2 q$ ^! ~6 \" e  d8 j, ?

  30. 3 m' m8 U7 k: W/ H, I5 ?# c% H
  31.     //初始化PG6,7,11
    ( l2 D6 ?" }- R; k% e$ c4 B
  32.     GPIO_Initure.Pin=GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_11;
    " h; Y# A. U3 A5 P. d% e
  33.     HAL_GPIO_Init(GPIOG,&GPIO_Initure);6 R" x6 U: B4 U+ X( L7 \

  34. + B% ]& f5 H2 l
  35.     //初始化PH9,10,11,12,13,14,15
    $ S2 o* g- D" q1 ?
  36.     GPIO_Initure.Pin=GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|\' d" L8 O3 P" O) Z! Y# }  Y
  37.                      GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
    7 J2 X3 `: \5 l6 i  w6 U5 Q
  38.     HAL_GPIO_Init(GPIOH,&GPIO_Initure);0 W' p5 E/ E3 O0 U: h: i# Z
  39. 1 k9 N- L( h  Z3 _* j
  40.     //初始化PI0,1,2,4,5,6,7,9,10" m) m! d& p# R- j7 u: h
  41.     GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|\: [$ O/ J! @# Q' e" r: Y8 z
  42.                      GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_10;' \  \; G, I9 Y2 g5 C
  43.     HAL_GPIO_Init(GPIOI,&GPIO_Initure); # U% V3 @' B4 a1 P9 [+ B
  44. }
复制代码
; _9 E6 \  E! B' p
2.设置LCD_CLK时钟
6 g7 u) C8 X- @" z1 ^; n$ z配置 LCD 的像素时钟,根据 LCD 的面板参数进行设置,LCD_CLK 由 PLLSAI进行配置,配置使用到的 HAL 库函数为:* ]) [! ~& C1 y
6 ?+ r! d5 y" K& y/ p  {+ O. J
  1.         //pllsain:SAI时钟倍频系数N,取值范围:50~432.  / R, m3 P  r0 C7 g
  2.         //pllsair:SAI时钟的分频系数R,取值范围:2~7, L' A& Z: N' `9 i" _- y
  3.         //pllsaidivr:LCD时钟分频系数,取值范围:0~3,对应分频2~16
    + K: V) T5 e- Q
  4.         //假设:外部晶振为25M,pllm=25的时候,Fin=1Mhz.* {5 Y3 z- V2 {
  5.         //例如:要得到20M的LTDC时钟,则可以设置:pllsain=400,pllsair=5,pllsaidivr=1
    " Y% L. {7 ]: W5 I: T
  6.         //Fdclk=1*396/3/2*2^1=396/12=33Mhz
      {- w( V- C# J% ?9 h
  7.     RCC_PeriphCLKInitTypeDef PeriphClkIniture;
    * G! I6 ~! u: a" y4 ^  X
  8. : `7 C/ W* |$ K* w' e9 ?1 }
  9.     //LTDC输出像素时钟,需要根据自己所使用的LCD数据手册来配置!9 S8 p/ u/ x! U
  10.     PeriphClkIniture.PeriphClockSelection=RCC_PERIPHCLK_LTDC;       //LTDC时钟4 U- R+ p* o/ A' C, ^  N3 _7 J) O1 w
  11.     PeriphClkIniture.PLLSAI.PLLSAIN=pllsain;/ x  h/ f. s; U8 @
  12.     PeriphClkIniture.PLLSAI.PLLSAIR=pllsair;
    , h% k* }5 B% V9 e" o7 Q
  13.     PeriphClkIniture.PLLSAIDivR=pllsaidivr;# F. R' Y$ h, i& e7 s
  14.         HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
复制代码
3 r. F: u# u% k. t1 Z$ C2 q
3.设置RGBLCD相关参数,并使能LTDC
9 D. Q- \5 n" I3 A& @" L
  1. typedef struct4 f$ S: n3 ~. }
  2. {' I3 }) X  ^' \$ J
  3. uint32_t HSPolarity;                         //水平同步极性
    5 h: P: W' D8 l/ v+ Y+ f: a
  4. uint32_t VSPolarity;                         //垂直同步极性
    3 }: R5 }5 o0 V9 p
  5. uint32_t DEPolarity;                         //数据使能极性' S8 j: n: v! d
  6. uint32_t PCPolarity;                         //像素时钟极性
    1 Y- ?+ @/ ?( q. G* ]) k
  7. uint32_t HorizontalSync;                 //水平同步宽度 4 U* P$ u5 f6 q* E% u
  8. uint32_t VerticalSync;                 //垂直同步高度7 {% z- e$ K  ^
  9. uint32_t AccumulatedHBP;                 //水平同步后沿宽度: x6 D/ {7 S! N' \; v/ u% }" L
  10. uint32_t AccumulatedVBP;                 //垂直同步后沿高度
    ( S0 r9 i0 W. e' i$ O+ M# a
  11. uint32_t AccumulatedActiveW;         //累加有效宽度   M4 J" h2 \4 N: u! [2 M
  12. uint32_t AccumulatedActiveH;         //累加有效高度3 I/ }% g0 |: j- E2 v
  13. uint32_t TotalWidth;                         //总宽度
    . C5 @% v1 b$ j9 E) p* k
  14. uint32_t TotalHeigh;                         //总高度) ]7 C4 |! E' K# z
  15. LTDC_ColorTypeDef Backcolor;         //屏幕背景层颜色 , x1 g9 Q0 @5 p- e: j% r
  16. } LTDC_InitTypeDef;0 F6 q4 G; c6 u9 z6 e( Q

  17. % ^  D! [; S3 r/ Q$ Z
  18. typedef struct
    5 T  s) b  y1 q: Y
  19. {$ N4 ~# ], y5 K& d1 `' Z& I
  20.   LTDC_TypeDef                *Instance;                /*Instance变量是LTDC_TypeDef结构体指针类型*/
    8 K4 Z& h0 n! O/ P! f+ X
  21.   LTDC_InitTypeDef            Init;                     /*用来初始化LTDC的结构体变量*/
    9 k1 C5 w' [2 f, I9 H7 ^; m
  22.   LTDC_LayerCfgTypeDef        LayerCfg[MAX_LAYER];      /*保存LTDC层配置参数*/
    1 @0 H, y. v' [3 Q5 O
  23.   HAL_LockTypeDef             Lock;                     /*锁状态*/1 I# A( H  l6 e; Y7 E$ q
  24.   __IO HAL_LTDC_StateTypeDef  State;                    /*LTDC的状态*/
    ' {7 d4 _, g, |# }, l4 H
  25.   __IO uint32_t               ErrorCode;                /*错误处理*/' J1 `% `. Z3 F" [
  26. } LTDC_HandleTypeDef;
    6 d5 g$ ]9 ]2 U0 N8 d) k
  27. 6 [( m8 J6 s6 R$ s
  28. LTDC_HandleTypeDef  LTDC_Handler;                                   //LTDC句柄
    6 m5 y6 U% J' G; `+ n9 `
  29. 2 y5 R  F- J7 p- \
  30. LTDC_Handler.Instance=LTDC;: C. [0 a% g$ F7 i) Q  v
  31. LTDC_Handler.Init.HSPolarity=LTDC_HSPOLARITY_AL;                 //水平同步极性" T6 \! t/ I  K1 ~+ z
  32. LTDC_Handler.Init.VSPolarity=LTDC_VSPOLARITY_AL;                 //垂直同步极性
    ( B: I, E9 w7 \6 i/ r
  33. LTDC_Handler.Init.DEPolarity=LTDC_DEPOLARITY_AL;                 //数据使能极性
    % X  F$ {- r: Z% [, p" b
  34. LTDC_Handler.Init.PCPolarity=LTDC_PCPOLARITY_IPC;                 //像素时钟极性# C0 N! l% C+ H. V: D
  35. LTDC_Handler.Init.HorizontalSync=10-1;                                         //水平同步宽度3 \+ e: _4 G- y
  36. LTDC_Handler.Init.VerticalSync=2-1;                                         //垂直同步宽度9 L( q% l0 T' Q: u- [! R: z
  37. LTDC_Handler.Init.AccumulatedHBP=10+20-1;                                 //水平同步后沿宽度
    3 N& `& }! ^3 Y7 P2 u* {  Q1 j  o
  38. LTDC_Handler.Init.AccumulatedVBP=2+2-1;                                 //垂直同步后沿高度7 e7 Z, C0 @0 g! z1 A: J
  39. LTDC_Handler.Init.AccumulatedActiveW=10+20+480-1;                 //有效宽度
    + K2 w3 G' n6 U4 k( R7 X, u" J
  40. LTDC_Handler.Init.AccumulatedActiveH=2+2+272-1;                 //有效高度( r/ ]! P8 i/ K
  41. LTDC_Handler.Init.TotalWidth=10+20+480+10-1;                         //总宽度" E8 P2 y3 G9 u$ Q) V
  42. LTDC_Handler.Init.TotalHeigh=2+2+272+4-1;                                 //总高度
    & Q7 B4 V, m$ R3 v/ {- P
  43. LTDC_Handler.Init.Backcolor.Red=0;                                                 //屏幕背景层红色部分
    3 D; y6 z) g4 K* m# H
  44. LTDC_Handler.Init.Backcolor.Green=0;                                         //屏幕背景层绿色部分0 Y7 h( I; \3 B/ h
  45. LTDC_Handler.Init.Backcolor.Blue=0;                                         //屏幕背景色蓝色部分
    ! Q5 ]0 A" q# T0 p; v
  46. HAL_LTDC_Init(<DC_Handler);                                                         //设置 RGBLCD 的相关参数,并使能 LTDC,会调用HAL_LTDC_MspInit
复制代码

$ c& {0 O9 ^3 `# n, ?4.设置 LTDC层参数* z: T( E7 b8 _' Z
  1. //layerx:层值,0/1.& L/ n$ e* V2 x! h# K
  2. //bufaddr:层颜色帧缓存起始地址/ j- Z" `5 u, o
  3. //pixformat:颜色格式.0,ARGB8888;1,RGB888;2,RGB565;3,ARGB1555;4,ARGB4444;5,L8;6;AL44;7;AL88
    , O' b' I# Q2 U; {) x
  4. //alpha:层颜色Alpha值,0,全透明;255,不透明
      i9 ^' ^1 ~; T
  5. //alpha0:默认颜色Alpha值,0,全透明;255,不透明. [! R1 _. ]* d' x. v
  6. //bfac1:混合系数1,4(100),恒定的Alpha;6(101),像素Alpha*恒定Alpha
    / X# ~9 `$ m, d# E3 D  F
  7. //bfac2:混合系数2,5(101),恒定的Alpha;7(111),像素Alpha*恒定Alpha
    ) H8 o# M; I9 C, T: p
  8. //bkcolor:层默认颜色,32位,低24位有效,RGB888格式3 t: u$ {+ e  m+ d* S. o
  9. void LTDC_Layer_Parameter_Config(u8 layerx,u32 bufaddr,u8 pixformat,u8 alpha,u8 alpha0,u8 bfac1,u8 bfac2,u32 bkcolor)
    $ V  Z. Y+ g9 X# ?4 R
  10. {
    ) R& n0 Y$ F5 B+ ~
  11.     LTDC_LayerCfgTypeDef pLayerCfg;
    2 H- D7 @/ a) t% r
  12. : [/ }. e* m1 P2 F
  13.     pLayerCfg.WindowX0=0;                                   //窗口起始X坐标  ]* h7 L2 v) W
  14.     pLayerCfg.WindowY0=0;                                   //窗口起始Y坐标
    1 _$ u: w$ V% u3 K6 Q9 W% d
  15.     pLayerCfg.WindowX1=lcdltdc.pwidth;                      //窗口终止X坐标
    , M: A4 p! z/ M
  16.     pLayerCfg.WindowY1=lcdltdc.pheight;                     //窗口终止Y坐标
    ! `3 h! z4 }" N# x( h& n
  17.     pLayerCfg.PixelFormat=pixformat;                        //像素格式7 {8 W* ~' K. V8 v+ N
  18.     pLayerCfg.Alpha=alpha;                                  //Alpha值设置,0~255,255为完全不透明8 b  w3 }1 ]2 ^! q  m  X4 F3 X3 f, e
  19.     pLayerCfg.Alpha0=alpha0;                                //默认Alpha值
    . o1 X+ _% E; x
  20.     pLayerCfg.BlendingFactor1=(u32)bfac1<<8;                //设置层混合系数5 Z* D" ^0 R* E& A* q
  21.     pLayerCfg.BlendingFactor2=(u32)bfac2<<8;                //设置层混合系数
    : ^" S" N: j9 P$ b$ O+ n
  22.     pLayerCfg.FBStartAdress=bufaddr;                        //设置层颜色帧缓存起始地址+ V- t( ]+ A0 R- ?
  23.     pLayerCfg.ImageWidth=lcdltdc.pwidth;                    //设置颜色帧缓冲区的宽度   
    6 ^4 A9 v, J9 w; H
  24.     pLayerCfg.ImageHeight=lcdltdc.pheight;                  //设置颜色帧缓冲区的高度
    . E0 [) Y9 b% s. L# E( v1 E. ^
  25.     pLayerCfg.Backcolor.Red=(u8)(bkcolor&0X00FF0000)>>16;   //背景颜色红色部分7 d2 ^/ Y% ?5 R, u: ~! b
  26.     pLayerCfg.Backcolor.Green=(u8)(bkcolor&0X0000FF00)>>8;  //背景颜色绿色部分; b* M0 B8 A& e1 O5 ]8 e3 S
  27.     pLayerCfg.Backcolor.Blue=(u8)bkcolor&0X000000FF;        //背景颜色蓝色部分
    8 ]/ ]7 z+ N& R$ c* \) p
  28.     HAL_LTDC_ConfigLayer(<DC_Handler,&pLayerCfg,layerx);  //设置所选中的层
    7 n$ i6 b2 \9 l, V7 {
  29. }
    * i1 W$ C1 r5 b1 |; Q: @/ L
  30. ) R+ X" ?. \+ O4 K. Q
  31. //在init时调用% t1 `2 n/ B$ B+ T, K! q% b# L
  32. LTDC_Layer_Parameter_Config(0(u32)ltdc_framebuf[0],LCD_PIXFORMAT,255,0,6,7,0X000000);  //层参数配置
复制代码
. K& B9 H7 i  n7 B3 A' k
5.设置LTDC层窗口, O$ `3 H& R: P( q7 o
  1. //layerx:层值,0/1.
    , \' I6 g" n2 }8 M+ e
  2. //sx,sy:起始坐标9 u7 U/ _/ n, Q5 Q
  3. //width,height:宽度和高度6 h% [1 ]/ B9 A$ \' F- Q
  4. void LTDC_Layer_Window_Config(u8 layerx,u16 sx,u16 sy,u16 width,u16 height)
    ! L' Q& g- M/ ~; z+ ]
  5. {
    + L* G) q  d9 S. L, a, j
  6.     HAL_LTDC_SetWindowPosition(<DC_Handler,sx,sy,layerx);                                  //设置窗口的位置! x3 I2 V' H0 C( I! w  r
  7.     HAL_LTDC_SetWindowSize(<DC_Handler,width,height,layerx);                                //设置窗口大小   
    + K6 @+ c2 {/ N  M
  8. }9 B0 u) E. _! P+ X6 G

  9. " h. ^5 U! j7 c* c5 e* F( k
  10. //在init时调用
    * ?& O- X( r* ]6 E. h
  11. LTDC_Layer_Window_Config(0,0,0,lcdltdc.pwidth,lcdltdc.pheight);             //层窗口配置,以LCD面板坐标系为基准
复制代码
$ [" ~. p2 _( I1 p9 @# l' Q
完成了 LTDC 的配置,可以控制 RGBLCD 显示了。. w) T- ?) y4 J9 e( r

/ M9 m7 h- T  F" J2 ]使用DMA2D完成颜色填充
+ j4 C/ h/ J; n0 }2 k/ ~  Y使用官方提供的 HAL 库 DMA2D 相关库函数进行颜色填充效率极为低下,大量时间浪费在函数的入栈出栈以及过程处理,所以在项目开发中一般都不会使用 DMA2D 库函数进行颜色填充# _5 M" O( i0 I" ~1 l* t; z
$ Y% Y" ?% z  ^! ~9 z
1)使能 DMA2D 时钟,并先停止 DMA2D。, E2 ~' A. U0 R+ v5 e! y7 s
要使用 DMA2D,先得开启其时钟。然后 DMA2D 在配置其相关参数的时候,需要先停止DMA2D 传输。 使能 DMA2D 时钟和停止 DMA2D 方法为:
" ^7 i1 n1 p3 f6 r
  1. __HAL_RCC_DMA2D_CLK_ENABLE(); //使能 DM2D 时钟5 g  j3 b: ^! `- J+ t
  2. DMA2D->CR&=~DMA2D_CR_START; //停止 DMA2D
复制代码

/ f4 u& K8 ~! g2)设置 DMA2D 工作模式。. \# L9 G% u8 A) b  {  \- H
通过 DMA2D_CR 寄存器,配置 DMA2D 的工作模式。我们用了寄存器到存储器模式和存储器到存储器这两个模式。
" I4 b$ v6 `, [% g6 [" Q3 R  J寄存器到存储器模式设置:$ e; |, _4 H* W3 L! x- x2 u
  1. DMA2D->CR=DMA2D_R2M; //寄存器到存储器模式
复制代码

- K" ?! v/ o7 O9 ^6 ~* x存储器到存储器模式设置:5 B. R+ n4 I5 \7 j* ~) A6 i5 U+ i
  1. DMA2D->CR= DMA2D_M2M; //存储器到存储器模式
复制代码
, ?, S6 ~) _; O5 U$ X3 q1 ^
3)设置 DMA2D 的相关参数。: I/ F7 T# L# n3 N  @
这一步,我们需要设置:颜色格式、输出窗口、输出存储器地址、前景层地址(仅存储器到存储器模式需要设置)、颜色寄存器(仅寄存器到存储器模式需要设置)等,由:DMA2D_OPFCCR、DMA2D_FGPFCCR、DMA2D_OOR、DMA2D_FGOR 、DMA2D_OMAR、DMA2D_FGMAR 和 DMA2D_NLR 等寄存器进行配置。具体配置过程请参考实验源码。
. _0 r' n; P* h2 |
3 m/ K8 i3 a" y: ^1 l4)启动 DMA2D 传输。
. S; N3 y. U1 @/ L通过 DMA2D_CR 寄存器配置开启 DMA2D 传输,实现图像数据的拷贝填充,方法为:
  L0 W& U9 n8 k8 Y  o! u4 F' V3 h  B
DMA2D->CR|=DMA2D_CR_START; //启动 DMA2D
, h  `4 Q" |' X* o1( N. {3 @0 j$ Q; O3 j* }: |, R
5)等待 DMA2D 传输完成,清除相关标识。
; u" _; E" B  f  ~最后,在传输过程中,不要再次设置 DMA2D,否则会打乱显示,所以一般在启动 DMA2D后,需要等待 DMA2D 传输完成(判断 DMA2D_ISR),在传输完成后,清除传输完成标识(设置 DMA2D_IFCR),以便启动下一次 DMA2D 传输。
1 j) ^7 h6 c: c  a! U& t% q4 \( V6 {! O/ A4 s- t) L( S
  1. while((DMA2D->ISR&DMA2D_FLAG_TC)==0) ; //等待传输完成) o& o; [- a6 R# _/ x
  2. DMA2D->IFCR|=DMA2D_FLAG_TC; //清除传输完成标志
复制代码
. ?. ~% T2 F8 N$ F
通过以上几个步骤,我们就完成了 DMA2D 填充) S% |& |) \* {- O  J. e& ?

2 y- |( y* v1 }+ h9 w. N; R使用示例* M! M- R% B. @; x$ [8 |
  1. //LCD LTDC重要参数集
    0 n/ t: |. ]5 n+ B
  2. typedef struct  
    1 ^9 G1 {( H7 h. I( }6 j+ ?* T5 ]7 R
  3. {
    & x2 K, n7 W6 P7 F; e" E2 ?
  4.     u32 pwidth;         //LCD面板的宽度,固定参数,不随显示方向改变,如果为0,说明没有任何RGB屏接入- q, b7 @9 C- b( E, U  T! {
  5.     u32 pheight;        //LCD面板的高度,固定参数,不随显示方向改变2 |  }: ^8 d) l3 R6 K; {
  6.     u16 hsw;            //水平同步宽度 Horizontal synchronization width& u0 |7 r3 T1 C! ]* |" w1 c
  7.     u16 vsw;            //垂直同步宽度 Vertical synchronization width* J! S# K; ?! B
  8.     u16 hbp;            //水平后廊" m- C# D# `. z9 Q3 \- Q
  9.     u16 vbp;            //垂直后廊4 z1 M6 T! `" `8 H
  10.     u16 hfp;            //水平前廊! h* Z7 k7 R6 W
  11.     u16 vfp;            //垂直前廊, G6 a7 D) P2 J
  12.     u8 activelayer;     //当前层编号:0/1% _) q& |2 H" P* ^
  13.     u8 dir;             //0,竖屏;1,横屏;$ K- ~" ]* ?8 G6 g% i  @# @
  14.     u16 width;          //LCD宽度
    7 l: u: `1 D0 ?2 w' J- ?
  15.     u16 height;         //LCD高度
    $ H" C$ Q6 o4 Y' I1 v, Q
  16.     u32 pixsize;        //每个像素所占字节数
    ! L$ B4 p' H) q4 I7 t' Y. b. g( [
  17. }_ltdc_dev;
    ; G6 w4 u6 R3 K
  18. ; ~+ Y. c+ U& }- V, n; F+ M6 X
  19. _ltdc_dev lcdltdc;                //管理LCD LTDC的重要参数
    : \8 N, o) g' C

  20. / J1 k/ k2 z1 U# f
  21. //LTDC填充矩形,DMA2D填充, O- J$ n1 [+ p1 W1 J$ T8 M
  22. //(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
    9 N8 k5 R, i% H7 h+ E
  23. //注意:sx,ex,不能大于lcddev.width-1;sy,ey,不能大于lcddev.height-1!!!
    - o: L. C: r7 X) v
  24. //color:要填充的颜色
    1 }+ z' N. ^* T1 C3 g- m
  25. void LTDC_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u32 color)
    ) V* h$ J5 U  Z! N1 w
  26. { " ~% i/ y6 H& G: o
  27.     u32 psx,psy,pex,pey;                        //以LCD面板为基准的坐标系,不随横竖屏变化而变化
    5 a( x1 O) m8 i5 m& f1 l0 F
  28.     u32 timeout=0; 5 R7 N# X/ T3 D9 M! J. O  q( Y
  29.     u16 offline;$ t# u5 O! w6 f
  30.     u32 addr; 6 \6 N8 }8 q/ i. A9 @9 n
  31.     //坐标系转换) \4 p) p( ^7 x4 W2 J; A/ t
  32.     if(lcdltdc.dir)                             //横屏4 d& _. n4 x  C- N8 b4 M/ j
  33.     {7 }1 t7 M: e0 [, p
  34.         psx=sx;psy=sy;
    2 {& O4 J. ~9 r. b
  35.         pex=ex;pey=ey;8 @' f5 I' r9 X. U' q
  36.     }else                                       //竖屏1 X5 o& r0 _* \5 Z7 t9 E( I
  37.     {( p" N- g; V; ^3 f2 w# L
  38.         psx=sy;psy=lcdltdc.pheight-ex-1;4 E/ @6 x2 e/ r7 ?$ C3 G* v
  39.         pex=ey;pey=lcdltdc.pheight-sx-1;
      n4 }1 ~& y. |8 K: ?+ L
  40.     } 5 W  |+ m& z+ F0 v4 w8 N3 m
  41.     offline=lcdltdc.pwidth-(pex-psx+1);  i: C$ }; s( s9 V0 c
  42.     addr=((u32)ltdc_framebuf[lcdltdc.activelayer]+lcdltdc.pixsize*(lcdltdc.pwidth*psy+psx));
    5 B. h& L# v& @  `
  43.     RCC->AHB1ENR|=1<<23;                        //使能DM2D时钟) e9 D: s, x/ Y( O
  44.     DMA2D->CR=3<<16;                            //寄存器到存储器模式% V6 d# V+ z; L# H+ {  I5 f$ {
  45.     DMA2D->OPFCCR=LCD_PIXFORMAT;                //设置颜色格式
    * f0 c. ^1 m/ M) e. |
  46.     DMA2D->OOR=offline;                         //设置行偏移
    4 L& x: U, ~  z
  47.     DMA2D->CR&=~(1<<0);                         //先停止DMA2D
    $ H3 l( w; X5 U" u5 q1 h
  48.     DMA2D->OMAR=addr;                           //输出存储器地址6 V9 M- ]! |; P
  49.     DMA2D->NLR=(pey-psy+1)|((pex-psx+1)<<16);   //设定行数寄存器
    * s8 c5 y! Z0 ?. K) \6 k. z
  50.     DMA2D->OCOLR=color;                         //设定输出颜色寄存器
    0 C5 |7 r2 W' V2 i9 s$ b5 l, ^
  51.     DMA2D->CR|=1<<0;                            //启动DMA2D( U% d9 T" n, X4 M' Q
  52.     while((DMA2D->ISR&(1<<1))==0)               //等待传输完成8 g: H& c+ V1 ^& o
  53.     {& Q* s! d$ \8 F0 W0 t
  54.         timeout++;- ]* i( B1 K9 v7 k, ~. y8 S5 c
  55.         if(timeout>0X1FFFFF)break;              //超时退出; l0 M7 q4 l; Y3 n: x$ n
  56.     }  
    , b8 b& p( P5 ]& v5 G
  57.     DMA2D->IFCR|=1<<1;                          //清除传输完成标志6 o$ d2 M" X/ o; n
  58. }! M8 j* q  ~- m$ |

  59. / `% u0 m% L& l  l: J# ]
  60. //LCD清屏
    % a! r5 b; X+ G2 O( \' g
  61. //color:颜色值8 B, H" C+ P% |( Z6 g7 j) _' ?9 `
  62. void LTDC_Clear(u32 color)
    + ]) p; z  p; c4 ^& ?7 g
  63. {+ ^  |) r4 W, I( x
  64.     LTDC_Fill(0,0,lcdltdc.width-1,lcdltdc.height-1,color);
    ( G# i; h2 C5 a5 m6 G* U1 v
  65. }
    " B; B" k" p9 p- _4 ^  r' y# Z
  66. , B( P7 [/ I- d+ N$ d# o: A8 Y: v/ u

  67. 0 _+ ?  P9 C! b! _3 I! [
复制代码

8 Z" N* U) d7 H! L% d; v4 B$ d  ~$ s% F. B' L1 P, H& l, L( F( Q
)0J3WVNZQ8DQ6O089(M6FJW.png
收藏 评论0 发布时间:2021-12-13 08:50

举报

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