需要提前准备好SDRAM驱动,如果没有SDRAM可以进行纯色彩测试,底层时钟,IO操作相关看注释,我使用的是寄存器封装的。3 w, k( [) g F$ P) N$ A$ n8 n4 o
* C6 s" E% \# O! y V) ~* v5 I
- /*************************************************************************************************************
8 F5 P6 Q$ D- {; ] - * 文件名 : stm32f7_ltdc.c
1 F2 A, S) @6 k9 H8 ^) V |4 ^ - * 功能 : STM32F7 外部RGB LCD驱动
% C* U6 w" z! A B1 N - * 创建时间 : 2019-09-12
" `+ \7 Y( d8 X( } - * 最后修改时间 : 2019-09-121 {. q& d% w, c1 R
- * 详细: $ M# |8 `& p) @; ]' z* ^2 s6 t
- *************************************************************************************************************/
( n% o* N9 C5 p- m3 @ b0 [) w. d - #include "stm32f7_ltdc.h"
1 V6 x0 I. j" z) A# s - #include "SYSTEM.H"
, P; [5 B3 q1 {$ N7 r* c - #include "stm32f7_sdram.h"
; \5 ^4 h1 K" q3 w/ V" C% p - #include "DMA2D.h") i8 d( A$ s. G$ L! V& h
% k# X! _- ^7 m- K1 n u( Y- 4 b6 M% W V0 ^8 t- e
- u32 g_LTDC_BUFF_RGB888[2][LTDC_HEIGHT][LTDC_WIDTH] __attribute__ ((at(Bank5_SDRAM_ADDR))); //需要SDRAM支持,LCD帧缓冲区,RGB888格式
! L0 p' `# z* D& Q* V, x - 9 [7 B& ^8 f' E, A" |
( x1 L( O! e3 i0 L; L% g. h+ J5 ?9 |- //记录全局层配置信息7 S7 q0 [2 B% y! g& v: V
- typedef struct) G/ l2 \6 M( X+ }
- {
4 Y1 W5 p/ j! C: O; P) K - u16 sx; //层开始X坐标,从0开始
+ e# Q) l( h; G+ C0 h( f - u16 sy; //层开始Y坐标,从0开始
* F: T4 s; `/ Q) L, ~9 C3 ? - u16 width; //层宽度5 G, g+ _; @ h
- u16 height; //层高度3 ]6 @9 r' o$ S& {
- u32 *pFrameBuff; //帧缓冲区指针,需要进行初始化
$ r) I( q# a4 [! \: o( l - }LTDC_LayerConfig;+ p D& L2 ]& a4 Q4 J% k
" o8 S8 G0 i; g8 e
' }4 d! j, Q7 z+ g4 c- ! a, M7 Y+ w! D! i& w
- //全局的LTDC配置信息3 } @8 I/ E0 X7 s( ]1 z/ }
- typedef struct
# N# p8 x/ J9 y w6 L1 l( G - {6 I' M' p/ s0 r
- u16 lcd_width; //显示器宽度6 G& p1 K7 P; M' E% N4 C
- u16 lcd_height; //显示器高度
/ U& I: J, \- I8 l3 t, X - LTDC_LayerConfig LayerConfig[2]; //层信息9 x" _" M+ @& ]1 V& z' i
- }LTDC_ConfigData;( a( S) A2 I# d! G+ `* S
- # F- b N# F/ v* f6 s6 d6 _3 h
- 3 r6 r( ]0 o4 q8 \
- static LTDC_ConfigData sg_LTDC_ConfigData; //记录全局的LCD配置6 t& G9 X( X+ G% f7 L; S
- & K2 V0 u! q# q
- $ C5 _8 U3 b& \% G) m* G
- //显示屏信息; g4 g ^5 d- C, M% t
- typedef struct
6 |; H1 V% D% G( G' @. k: T - {
" ?9 L7 i/ |: s - u16 Width; //面板宽度,单位:像素$ A, M6 A, \( g% L% ^" J5 I6 ]- G
- u16 Height; //面板高度,单位:像素
: ?0 h n {. k3 l L( S - u8 Thbp; //水平后廊( w( H& I+ ]2 d# y; Q
- u8 Thfp; //水平前廊2 ~! B! U/ b+ p. S. i
- u8 Thw; //水平同步宽度. \, D0 C: w9 P$ H5 d; B2 j
- u8 Tvbp; //垂直后廊: L6 d b$ Z4 X# S, D
- u8 Tvfp; //垂直前廊1 b7 k0 K0 }3 D( ^5 l
- u8 Tvw; //垂直同步宽度" a& J) [9 g1 b# d6 Q8 `* q* H. x
- u8 DCLK; //时钟速度,MHz
' F/ ^. s; X/ w+ }1 r9 } f J -
7 l5 u B. G5 g7 M" r5 O1 x - u8 HSPOL; //水平同步极性,0:低电平有效;1:高电平有效8 F" k6 M7 _( R( p- `# D6 W
- u8 VSPOL; //垂直同步极性,0:低电平有效;1:高电平有效
( |0 M& `1 k& m1 u$ }+ j( `) h - u8 DEPOL; //数据使能极性,0:低电平有效;1:高电平有效
* d0 J' y3 f) h# w/ f7 z - bool PCPOL; //像素时钟反向
$ W3 R5 _: V. G& L7 @3 \ - }LTDC_INFO_TYPE; Z/ g9 U# e( n5 B* M. l
! [7 r5 `* P5 m( n
7 \4 n7 a# `5 p( k- LTDC_INFO_TYPE DefaultLCD_Info =
) r: l' b! Z: g. S" o& p$ t - {8 P; ^+ H, h/ L+ F! x+ @7 r
- 480, //面板宽度,单位:像素
" m, o! q' I$ R* l0 o - 272, //面板高度,单位:像素* B: l% p1 K) A7 W( V4 p0 \
- 41, //水平后廊
0 Z) a ~) ~# a$ k3 O% m - 8, //水平前廊$ {, B6 d/ H: K" N& W- c8 z
- 2, //水平同步宽度
) I2 @. T1 D# B - 2, //垂直后廊
9 |6 ?! h% N* @, Z - 4, //垂直前廊& M0 ]8 m* w4 c1 D9 X
- 10, //垂直同步宽度. b f+ A& s" P
- 9, //时钟速度,MHz
7 h! l5 V& v5 Z9 r% y4 K - 0, //水平同步极性,0:低电平有效;1:高电平有效
: K: W# j+ D' U i, [5 P - 0, //垂直同步极性,0:低电平有效;1:高电平有效
3 d1 E8 j& w0 l; B4 G6 C# ]/ S - 1, //数据使能极性,0:低电平有效;1:高电平有效2 Q* l$ a/ I# J5 G2 ]: H
- FALSE, //像素时钟反向
& l* M6 v1 z/ N! i/ Y - };
: S' }3 y: z9 A3 W( U
5 _7 w1 Q5 G9 _2 k- bool LTDC_ClockInit(u16 ClockFreq); //STM32F4 LTDC时钟初始化 @. a4 q. @: l) l: C
5 i2 A! I# i% `. L z- p8 ^5 T- P- 6 Y' \% W) w" f' P4 i' K
- /*************************************************************************************************************************- B& i' i9 m- ]& R( Y% `2 w9 E
- * 函数 : void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha)8 X( b) Q# {5 c
- * 功能 : LTDC 层窗口尺寸设置(会自动根据窗口尺寸以及像素格式设置帧缓冲区大小)3 ]* n$ A) k ~3 i7 d0 p
- * 参数 : LayerIndex:层选择(0-1);sx,sy:起始坐标;width,height:宽度和高度0 Y' ?0 Z9 v; ?- {' h. X3 P$ V, k
- * 返回 : 无- n& x) y6 U6 N- t% [
- * 依赖 : 底层宏定义8 ?- E4 ~8 Z+ }9 K- b
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>$ q0 I! i0 \& V+ `2 H8 r' d
- * 时间 : 2019-10-28) S* h/ [& Z) F# |( t1 b" T8 F, H
- * 最后修改时间 : 2019-10-28
% W6 n9 [% U; @ - * 说明 : 不会使能层,不会更新层,只设置配置,需要刷新层配置后更新
3 B) Z$ M3 w0 \- }3 [4 E& D - *************************************************************************************************************************/
( O) N* v, w* o) w; M - void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha): |5 p8 `. r! ]
- {1 m9 Z. {% x* y7 ^/ ^; \" h' L
- u32 temp;7 [- R1 N, m {2 i" P/ P, L
- u8 pixformat=0;
~, |# t/ Y. n, W( ` - ) y4 s. b( h* P; A4 E- O
- if(LayerIndex==0)
+ }: }$ W/ |2 H7 {1 R# g2 z5 y( S - {5 h3 l5 Y/ ~1 x
- //基本配置# {( j# Z& L0 V; p
- LTDC_Layer1->CFBAR = FrameBuff; //设置层颜色帧缓存起始地址
1 g: F2 W# }% `& D4 T' ~ S - LTDC_Layer1->PFCR = LTDC_PIXEL_FORMAT; //设置层颜色格式
; W% Y+ j$ y5 y) U8 J. F - LTDC_Layer1->CACR = Alpha; //常数 Alpha,255分频;设置255,则不透明$ H! r( E" R9 G+ I' u9 p
- LTDC_Layer1->DCCR = 0x00; //设置默认颜色:透明的黑色) b$ S$ V! B# N9 r$ B
- LTDC_Layer1->BFCR = ((u32)6<<8)|7; //设置层混合系数+ l1 ^, N- I" r- P
- //配置窗口
1 c7 J/ ~9 J' w& A8 F- L' q) S - temp = (sx+width+((LTDC->BPCR&0X0FFF0000)>>16))<<16;
9 B5 }8 \9 P1 e' l* m0 F8 p - LTDC_Layer1->WHPCR = (sx+((LTDC->BPCR&0X0FFF0000)>>16)+1)|temp;//设置行起始和结束位置
2 Y8 d) W/ w* s) f' o% G+ r5 i - temp = (sy+height+(LTDC->BPCR&0X7FF))<<16; 5 \) l' l. G9 o& `- U, ^) H
- LTDC_Layer1->WVPCR = (sy+(LTDC->BPCR&0X7FF)+1)|temp; //设置列起始和结束位置
7 Q1 L' X; u9 d% q7 ^5 R7 w - pixformat = LTDC_Layer1->PFCR&0X07; //得到颜色格式) f3 f; L; b0 V4 V4 S& i
- if(pixformat == 0)temp=4; //ARGB8888,一个点4个字节. N. b. l% b8 {2 C+ r
- else if(pixformat == 1)temp=3; //RGB888,一个点3个字节
) W8 S: m8 w4 ]* a$ d& ? - else if(pixformat==5||pixformat==6)temp=1; //L8/AL44,一个点1个字节
3 E2 v& n& o# l2 b - else temp=2; //其他格式,一个点2个字节 o5 G* w0 b$ q1 I* m/ z C. S
- LTDC_Layer1->CFBLR = (width*temp<<16)|(width*temp+3); //帧缓冲区长度设置(字节为单位)
/ R+ R* P+ W; L - LTDC_Layer1->CFBLNR = height; //帧缓冲区行数设置 3 n8 q& C& q4 Y l
-
* K4 `2 Q m% X9 ]" J5 ] - //记录层窗口大小位置信息# E# {$ N2 U. k/ ^7 t
- sg_LTDC_ConfigData.LayerConfig[0].sx = sx; # k% k `7 G9 o, |- _6 `' _/ ~
- sg_LTDC_ConfigData.LayerConfig[0].sy = sy;
- E7 p+ N8 e* B. j6 ]$ V# e - sg_LTDC_ConfigData.LayerConfig[0].width = width; ( G; R% n s4 l* o* m$ V& z
- sg_LTDC_ConfigData.LayerConfig[0].height = height;
) x& @7 J5 w- S+ v5 q5 ]( | - }else
1 M- N3 i+ F' p1 E; c! ^4 F - {# J* I- ?7 M1 j3 I+ R& W8 ^) t
- //基本配置- R1 l7 K8 G( r/ A, b
- LTDC_Layer2->CFBAR = FrameBuff; //设置层颜色帧缓存起始地址
. p- M' ^7 F9 C/ [( a; s - LTDC_Layer2->PFCR = LTDC_PIXEL_FORMAT; //设置层颜色格式
8 u8 J% ]1 R9 s$ U0 V( m - LTDC_Layer2->CACR = Alpha; //常数 Alpha,255分频;设置255,则不透明
1 M4 h% ^3 @: J* z! b* d+ M( E - LTDC_Layer2->DCCR = 0x00; //设置默认颜色:透明的黑色, d, y1 c# p, p) E$ Y! d
- LTDC_Layer2->BFCR = ((u32)6<<8)|7; //设置层混合系数4 s3 H) D2 I) H
- //配置窗口; d$ X$ e5 G) B% I
- temp = (sx+width+((LTDC->BPCR&0X0FFF0000)>>16))<<16;
' V* C3 \6 u. a, i& g. i) h0 G$ X - LTDC_Layer2->WHPCR = (sx+((LTDC->BPCR&0X0FFF0000)>>16)+1)|temp; //设置行起始和结束位置 V4 o6 Y6 |! ~2 ]
- temp = (sy+height+(LTDC->BPCR&0X7FF))<<16;
' d7 D' o- x+ n$ n) M0 O - LTDC_Layer2->WVPCR = (sy+(LTDC->BPCR&0X7FF)+1)|temp; //设置列起始和结束位置" g$ k: Z3 _, [+ F& U' o/ h& j- V
- pixformat = LTDC_Layer2->PFCR&0X07; //得到颜色格式
. E' }( ?3 V% X4 V7 b$ t! x! j - if(pixformat == 0)temp=4; //ARGB8888,一个点4个字节
' j8 ]% }8 b3 f/ r/ v' m - else if(pixformat == 1)temp=3; //RGB888,一个点3个字节
) _) C; @' I9 |9 j+ R - else if(pixformat == 5||pixformat==6)temp=1; //L8/AL44,一个点1个字节3 _( ?7 t O( N8 x! p& y
- else temp = 2; //其他格式,一个点2个字节
& e+ z5 u7 }. h$ Q! r! v - LTDC_Layer2->CFBLR = (width*temp<<16)|(width*temp+3); //帧缓冲区长度设置(字节为单位)
# x4 _5 B, X' j. L# Q0 \ - LTDC_Layer2->CFBLNR = height; //帧缓冲区行数设置
# ^" O/ A+ u6 M9 `- { -
8 ~5 W: b( Q. o; E5 v3 A9 I - //记录层窗口大小位置信息3 M" r1 {+ W7 p6 d2 _
- sg_LTDC_ConfigData.LayerConfig[1].sx = sx;
7 w9 Y* H- Y" F( }, B6 ^2 x: _ - sg_LTDC_ConfigData.LayerConfig[1].sy = sy; 9 D' W: K' c) s2 q
- sg_LTDC_ConfigData.LayerConfig[1].width = width; 7 q( l5 X4 p$ I0 |7 F! ?
- sg_LTDC_ConfigData.LayerConfig[1].height = height;
6 p6 q* h; w% S( N" E5 L1 K - }+ O% H$ E. y4 E$ Y |5 K
- }
+ I& X- U- b5 S, N - % B: m3 |& r5 ^6 C
- ; k3 s; m( {3 p
- ( L- g# G, K) n4 i8 U1 ~/ |" ]" a- w6 W
- /*************************************************************************************************************************
2 Q) j( g% {: y" N* | - * 函数 : void LTDC_Init(void)
. }3 }* M: r. I0 l: I - * 功能 : LTDC 接口初始化4 L, A$ E x" _, Q6 S, g* B) w) f
- * 参数 : 无
, [7 |% x% t3 a1 ] - * 返回 : 无; ^. r4 s" j# z( ~
- * 依赖 : 底层宏定义" |. I# e) `! Z# _
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>5 o: @9 q/ Y, Z" ~* }' V
- * 时间 : 2019-09-08( y; V! S! u I9 j9 g
- * 最后修改时间 : 2019-09-08/ y5 {: M; a6 ~; S' O7 v
- * 说明 : 用于初始化STM32F7 LTDC 接口
* S# N1 l% w$ h( S+ b n - *************************************************************************************************************************/
# [4 K5 ^! y; L - void LTDC_Init(void)
8 Z3 M Z1 F: u- }4 d - { l+ n t; N8 G z
- u32 temp;$ j9 S; Z4 A- G: R& A/ A
-
5 D$ d' g& k# Z3 _' z - SYS_DeviceClockEnable(DEV_LTDC, TRUE); //LTDC时钟使能
4 u0 `/ \( X' c5 n4 A+ ^8 X q - SYS_DeviceReset(DEV_LTDC); //STM32F7外设复位5 S1 T J, ~7 O4 t. A* u
- SYS_DeviceClockEnable(DEV_GPIOE, TRUE); //使能GPIOE时钟3 M! [5 m, `9 D2 n# L4 Z/ e. t
- SYS_DeviceClockEnable(DEV_GPIOG, TRUE); //使能GPIOG时钟7 _: D1 b6 }( s% q
- SYS_DeviceClockEnable(DEV_GPIOJ, TRUE); //使能GPIOJ时钟
+ ]- {# D9 \( z2 O z - SYS_DeviceClockEnable(DEV_GPIOK, TRUE); //使能GPIOK时钟: i% ^2 A# h) a4 {, M/ i* Y
- SYS_DeviceClockEnable(DEV_GPIOI, TRUE); //使能GPIOI时钟- C& r& f% y0 \$ k# x0 w
# {+ b" H g, t/ c, z0 O- 4 U5 B! U5 v: }" }
- //初始化IO7 M4 K/ s8 E$ y7 C- `0 X- M( ]
- SYS_GPIOx_Init(GPIOE, BIT4, AF_PP_OPU, SPEED_100M); //PE4. f* P6 N4 x4 {1 o/ q$ V
- SYS_GPIOx_Init(GPIOG, BIT12, AF_PP_OPU, SPEED_100M); //PG12
* V, t& @" }& {5 U! d - SYS_GPIOx_Init(GPIOJ, 0Xffff&(~BIT12), AF_PP_OPU, SPEED_100M); //PJ0~11/13/14/15
4 B" ~) i! q9 T* g) P! \ - SYS_GPIOx_Init(GPIOK, BIT0|BIT1|BIT2|BIT4|BIT5|BIT6|BIT7, AF_PP_OPU, SPEED_100M); //PK0/1/2/4/5/6/7
5 P9 V, O) p7 G6 c( d - SYS_GPIOx_Init(GPIOI, BIT9|BIT10|BIT14|BIT15, AF_PP_OPU, SPEED_100M); //PI9/10/14/15# |9 I( e' y+ M3 Y# Z, U
-
8 I. Y( ^$ F# c: Z. S ^ - SYS_GPIOx_SetAF(GPIOE, 4, AF14_LTDC); //PE4,AF14
$ Q- C2 Q- R1 J G1 a( Y - SYS_GPIOx_SetAF(GPIOG, 12, AF14_LTDC); //PG12,AF14
4 b$ W$ S7 @6 [" U9 G: X - SYS_GPIOx_SetAF(GPIOJ, 0, AF14_LTDC); //PJ0,AF14# A8 Z3 k% O; X: c6 V2 X% {
- SYS_GPIOx_SetAF(GPIOJ, 1, AF14_LTDC); //PJ1,AF144 g) V4 z. r. Z. O
- SYS_GPIOx_SetAF(GPIOJ, 2, AF14_LTDC); //PJ2,AF14
' X- C9 g4 q C% @7 ?' } - SYS_GPIOx_SetAF(GPIOJ, 3, AF14_LTDC); //PJ3,AF14
( @; e. p+ s. h) B - SYS_GPIOx_SetAF(GPIOJ, 4, AF14_LTDC); //PJ4,AF149 d; w% w$ W2 B* h+ |8 T
- SYS_GPIOx_SetAF(GPIOJ, 5, AF14_LTDC); //PJ5,AF140 j. ?* W I8 f1 }
- SYS_GPIOx_SetAF(GPIOJ, 6, AF14_LTDC); //PJ6,AF143 s7 p' ]: t, w5 ^% Y2 H
- SYS_GPIOx_SetAF(GPIOJ, 7, AF14_LTDC); //PJ7,AF14
" S2 O) N% q$ r) | - SYS_GPIOx_SetAF(GPIOJ, 8, AF14_LTDC); //PJ8,AF14
% e# S9 B9 }$ G) }/ K. p2 n. x - SYS_GPIOx_SetAF(GPIOJ, 9, AF14_LTDC); //PJ9,AF14
: R* a" c- o: R - SYS_GPIOx_SetAF(GPIOJ, 10, AF14_LTDC); //PJ10,AF14
5 |* [8 Q5 @5 [% q8 {4 ^ - SYS_GPIOx_SetAF(GPIOJ, 11, AF14_LTDC); //PJ11,AF14- y: U/ a) @8 n/ f' A- p
- SYS_GPIOx_SetAF(GPIOJ, 13, AF14_LTDC); //PJ13,AF148 {8 y' y8 c2 c+ f
- SYS_GPIOx_SetAF(GPIOJ, 14, AF14_LTDC); //PJ14,AF145 y) K: S2 _/ P
- SYS_GPIOx_SetAF(GPIOJ, 15, AF14_LTDC); //PJ15,AF14! {5 y# D( d3 `6 {$ c2 A% g
- ! C ?' C) P7 c% x% c
- SYS_GPIOx_SetAF(GPIOK, 0, AF14_LTDC); //PK0,AF14% R- e. e3 j( n' r4 V" A
- SYS_GPIOx_SetAF(GPIOK, 1, AF14_LTDC); //PK1,AF14
& A9 U9 M1 O: c' j7 y$ j* u - SYS_GPIOx_SetAF(GPIOK, 2, AF14_LTDC); //PK2,AF14
) Q& e5 X0 [6 A9 B5 ? - SYS_GPIOx_SetAF(GPIOK, 4, AF14_LTDC); //PK4,AF14% O* Y& C$ L6 x0 f
- SYS_GPIOx_SetAF(GPIOK, 5, AF14_LTDC); //PK5,AF14
: H( V7 I( H- S4 i. K - SYS_GPIOx_SetAF(GPIOK, 6, AF14_LTDC); //PK6,AF14
5 u( u" E' |9 l' A7 _+ R' c - SYS_GPIOx_SetAF(GPIOK, 7, AF14_LTDC); //PK7,AF14
1 Q% B9 s: `& c! i" n1 T -
4 c6 [) j0 b. Y! I0 f - SYS_GPIOx_SetAF(GPIOI, 9, AF14_LTDC); //PI9,AF14
7 [( f5 Z+ H- A/ Z( v' T8 O- | - SYS_GPIOx_SetAF(GPIOI, 10, AF14_LTDC); //PI10,AF14
# z: y* p* U( i! s% x - SYS_GPIOx_SetAF(GPIOI, 14, AF14_LTDC); //PI14,AF14
. y7 V1 m& D; g* l* V - SYS_GPIOx_SetAF(GPIOI, 15, AF14_LTDC); //PI15,AF14
Q' Z) c& b! G. o - 3 `2 h0 Q5 u; l
- LTDC_ClockInit(DefaultLCD_Info.DCLK); //设置像素时钟 9Mhz & ]% e+ ?8 ~" H& V
- //设置LTDC 全局控制寄存器 (LTDC_GCR)
0 _+ u, L* l h- F; ^& X - temp = 0;
$ c8 g; v$ D$ ?* J* q: F - temp |= (DefaultLCD_Info.HSPOL&0x01) << 31; //水平同步极性
& E0 N9 j, w$ g8 W - temp |= (DefaultLCD_Info.VSPOL&0x01) << 30; //垂直同步极性% H+ l8 U/ G$ O7 j4 K# V: j
- temp |= (DefaultLCD_Info.DEPOL&0x01) << 29; //数据使能极性
0 e4 o2 I0 t; h0 U: e - temp |= (DefaultLCD_Info.PCPOL&0x01) << 28; //像素时钟极性
1 q9 E5 v2 Y2 ?, q) D) W - LTDC->GCR = temp;
" X, X& b: q' f5 U$ O - //LTDC 后沿配置寄存器 (LTDC_BPCR)- t; U/ h# K3 Y' ^: |
- temp = (DefaultLCD_Info.Tvw + DefaultLCD_Info.Tvbp - 1) << 0; //这些位定义累加水平后沿宽度(水平同步像素加水平后沿像素减 1)。# H/ Z. E7 g* z
- temp |= (DefaultLCD_Info.Thw + DefaultLCD_Info.Thbp - 1) << 16; //这些位定义累加垂直后沿宽度(垂直同步行加垂直后沿行减 1)。5 |3 B( U* l# _- X
- LTDC->BPCR=temp; # a, O5 M. M# }* \6 N
- 2 p) n/ x. ^2 |& i3 F' S
- //LTDC 有效宽度配置寄存器 (LTDC_AWCR)# z1 y6 D3 J5 U
- temp=(DefaultLCD_Info.Tvw+DefaultLCD_Info.Tvbp+DefaultLCD_Info.Height-1)<<0; //累加有效高度=垂直脉宽+垂直后沿+垂直分辨率-1
& m! F" L; Q" x/ C - temp|=(DefaultLCD_Info.Thw+DefaultLCD_Info.Thbp+DefaultLCD_Info.Width-1)<<16; //累加有效宽度=水平脉宽+水平后沿+水平分辨率-1
- C$ U& ^. g8 I7 o! B* K" z6 _9 ^ - LTDC->AWCR=temp;
! j* X' H+ F5 z& C. Y/ V - //LTDC 总宽度配置寄存器 (LTDC_TWCR). z5 U+ s! i0 N, b2 j& x& b v9 m2 Z
- temp=(DefaultLCD_Info.Tvw+DefaultLCD_Info.Tvbp+DefaultLCD_Info.Height+DefaultLCD_Info.Tvfp-1)<<0; //总高度=垂直脉宽+垂直后沿+垂直分辨率+垂直前廊-1
4 x' s) ]( N3 ^2 @ - temp|=(DefaultLCD_Info.Thw+DefaultLCD_Info.Thbp+DefaultLCD_Info.Width+DefaultLCD_Info.Thfp-1)<<16; //总宽度=水平脉宽+水平后沿+水平分辨率+水平前廊-1
1 [7 ~( f, B3 z8 K: `5 N; ^ - LTDC->TWCR=temp;
$ d7 l. M2 J7 O: ^9 N
2 u" W0 _9 m1 d4 a/ h" b' ~$ Y- //背景设置
% O* z( s; r T# V8 y - LTDC->BCCR=0xffffff; //设置背景层颜色寄存器(RGB888格式)
7 B# e b0 n8 y1 r( V - LTDC_Enable(TRUE); //开启LTDC% _5 T, Z5 M* y- {7 s! ?: [. d
- //初始化层1' Z& c5 }, k1 f% I
- LTDC_SetLayerConfig(0, 0, 0, LTDC_WIDTH, LTDC_HEIGHT, (u32)g_LTDC_BUFF_RGB888[0], 255);
+ J+ x% G8 [* A( J3 z - //初始化层23 u1 q9 n' H- h: \
- LTDC_SetLayerConfig(1, 0, 0, LTDC_WIDTH, LTDC_HEIGHT, (u32)g_LTDC_BUFF_RGB888[1], 255);' I* K* ?% _3 R& a$ ^1 p" p' `( ?6 w
- LTDC_Clear(0, 0xFF000000); //清屏层1-不透明的黑色: S! i8 {' d* _1 y5 A, Z& |9 @
- LTDC_Clear(1, 0x00000000); //清屏层2-透明的黑色6 u: t( O: F2 U' q! Q6 ]1 B& s
- LTDC_LayerEnable(0, TRUE); //使能层1
, e& A6 R" r/ T" G) b. Q8 G& y E7 C - LTDC_LayerRefreshConfig(); //LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)
1 |- b% V+ n& ]% T3 h% s2 e" K - LCD_DispIoInit(); //初始化DISP引脚-启动显示
m+ E- U/ _0 |3 D' U - }$ m7 j, u1 W" F
; a' j' X7 T8 a0 t% Y5 p- /*************************************************************************************************************************6 s4 x7 @5 Y% Q( b; q
- * 函数 : void LTDC_LayerRefreshConfig(void)$ R: Y: |) }. h1 Y) T- f- ]
- * 功能 : LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)
4 J. @2 `9 g+ Y- ~ - * 参数 : 无
* f3 |6 A# D2 A - * 返回 : 无
; ]9 k* i% s" @ - * 依赖 : 底层宏定义
% d. y* m: e( `5 L) x - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
3 P; N( u/ @% _; E. y# B - * 时间 : 2019-10-299 K: p { z5 r
- * 最后修改时间 : 2019-10-29
! V& j7 M! h8 g0 ^: N! c - * 说明 : 修改层配置后必须重新加载,否则不会生效
* Q4 p+ \7 W# M9 E3 P' e. Z - *************************************************************************************************************************/
/ X) v2 {5 b$ a; x) b A/ u - void LTDC_LayerRefreshConfig(void)6 e% F; V' ]6 n9 v3 c9 y
- {
8 t) l0 c: [, Q - LTDC->SRCR|=1<<0; //重新加载配置-必须重新加载,否则上面的层不会更新,折腾好久才发现,叫啥影子寄存器重载,也不说清楚5 t* \8 n+ f: P- m
- }
! Q$ k$ a1 I+ a( A' a7 I6 A
0 l! D# J7 F. R3 Z$ @8 R+ ?- /*************************************************************************************************************************
/ V1 `0 P. K2 P F' B4 F' y! h - * 函数 : void LTDC_Enable(bool Enable)
- f, J& \! r9 r$ ^ - * 功能 : LTDC使能设置- \, K. o/ I9 a/ l
- * 参数 : Enable:TRUE:使能;FALSE:失能3 W/ w4 H L& Q8 S( q
- * 返回 : 无
0 o4 _/ l' T2 f, A - * 依赖 : 底层宏定义
" n) {$ @) a5 i" c# o+ v5 { - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
8 a2 ]# c, ^ Y) j6 e* f, v - * 时间 : 2019-10-295 c( J& t+ y9 O- l; R+ H4 B
- * 最后修改时间 : 2019-10-299 N0 V' N8 z' V# w8 F+ j9 s6 F4 X
- * 说明 : 8 E& |* D8 h+ j$ Z# p. N
- *************************************************************************************************************************/! a% W% b0 ?2 E# N4 g+ l5 C- b/ L
- void LTDC_Enable(bool Enable)
* I& n, z1 ~- ~& K! {5 s4 y7 o - {2 |$ Q. ?5 y! d- s8 V
- if(Enable)4 Z9 [% q+ A' u( U& G$ w8 ^
- {; x6 @' y) W7 N) q" S: H% E
- LTDC->GCR |= BIT0; //打开LTDC" X+ n9 ~2 ?% Q1 R* w
- }) V8 C* d% R% q) k3 J, N+ R9 o9 `
- else
% y1 H" A5 i( j) s% K - {
, u/ c; j( W7 @/ U - LTDC->GCR &= ~BIT0; //关闭LTDC* w: r2 P3 H* M* i2 Q- u
- }9 F( g$ X# m6 N* k, n5 M* z9 f- m; n
- }* z+ D3 Q3 F9 `+ V. v' c4 I7 S
- . C4 a8 W' y# [. N
- /*************************************************************************************************************************1 h2 q, u7 Q. l$ R. e
- * 函数 : void LTDC_LayerEnable(u8 LayerIndex, bool Enable)
* ^1 m' s' k4 |/ M8 F- l8 T0 z: d - * 功能 : LTDC 层使能设置& l% W$ w. V5 | R
- * 参数 : LayerIndex:层选择0-1;Enable:TRUE:使能;FALSE:失能/ d/ { _' a) l' v5 q/ x% f5 z" F
- * 返回 : 无
3 s' o' V' v! N% ^8 ? - * 依赖 : 底层宏定义) b* p+ ] ^3 S( |6 P
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>, l4 ]$ S6 d. p6 Q6 Q
- * 时间 : 2019-10-29
! v% A# t: s- K( x2 }' d1 H! `) ]7 y - * 最后修改时间 : 2019-10-29% n' t1 x' j( U, P( Q/ Z. y
- * 说明 :
& u( L1 L2 x& Y+ q6 w# S - *************************************************************************************************************************/2 g8 ]5 d8 Q y$ W' c7 `; i
- void LTDC_LayerEnable(u8 LayerIndex, bool Enable)
& o8 L) @/ v" ~! v! Z. V - {
% D/ G y5 c) w$ W6 ]: E$ C - if(Enable)# \* C7 d4 K* S: I |
- {
7 D* L) {0 C# x$ i: m5 U: N0 { - if(LayerIndex == 0) //层16 w( o$ l* K1 Y2 o O: e
- {7 n: T9 y# ?8 U% n; D) }, V; o# N. X
- LTDC_Layer1->CR |= BIT0; //使能层12 V2 n7 e3 I" |% `
- }
' B& `" u% ]+ j - else
# ^! s1 R& r! u& P8 @% {1 ] - {$ u: i, M5 \) }0 i( B: t d
- LTDC_Layer2->CR |= BIT0; //使能层2) F; e. w9 P3 w
- }
* N9 l1 J* u, W1 z2 _9 g f8 | - }
% i: q5 E% s" d- A/ i - else, z! D/ J4 ~$ u& B+ k
- {
7 C3 N1 v( V8 N3 ~+ Z - if(LayerIndex == 0) //层1$ N. _ H3 b( k) Z9 _9 }
- {
+ d- S9 s) Y8 A - LTDC_Layer1->CR &= ~BIT0; //失能层1# ]) \7 F; J) ^ N& p5 K5 f
- }
+ ^, B5 o: p& r - else
4 D% X/ d% i, Y& u - {; W' M/ u& D) `+ G; c
- LTDC_Layer2->CR &= ~BIT0; //失能层2
% P9 y& H' R* _9 B7 P- W& y: s. A - }- V8 O/ O. J( B: i6 u0 i: b
- }- g+ T3 O6 v* c8 h
- }
7 h; C: H5 R- j5 W) c
0 ~- Y; R- p9 ~# T. P- 4 d0 S/ s+ G1 C1 m ]! E
- ' A" I/ {6 o8 p2 U0 R9 z+ Q4 f
- . a) ^; `) F- Z6 c; a3 j2 F
- /*************************************************************************************************************************2 E) z6 _8 a4 u/ O+ A
- * 函数 : bool LTDC_ClockInit(u16 ClockFreq) 1 ~9 `7 @4 y0 w( z
- * 功能 : STM32F7 LTDC时钟初始化& j. }0 Y/ l6 [7 x( b! C+ F
- * 参数 : ClockFreq:时钟频率,2-168MHZ5 L8 g% I! H/ e+ \* g; g6 A* |/ E
- * 返回 : 是否设置成功) } W" j$ a) i
- * 依赖 : 底层宏定义( [* Q! z5 K( i8 S4 k) \
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
9 g/ V; c3 P: q' ~" I - * 时间 : 2019-10-28
! C; l/ p* c4 S; W - * 最后修改时间 : 2019-10-28: v) I6 O# W( n; T9 `( P% Y& s
- * 说明 : 输入时钟频率在系统主时钟初始化之后就会设置为1MHz,通过设置SAI PLL实现LTDC所需频率,VCO频率范围:49~4328 [: K, Z7 T( a q+ q7 Y( U4 Z
- *************************************************************************************************************************/% n; k( V& o. \0 T
- bool LTDC_ClockInit(u16 ClockFreq)+ b2 n: Y, f6 n k
- {
) ~+ B4 L1 R* U! M$ }7 Y6 ^ - u32 TimeOut = 0;
* G1 V7 G: b5 v' @& A9 z# d9 u* H - u32 VCO;
( F. i- I4 A$ m# s/ c6 B - u32 PLLSAIR; //PLLSAICFGR[30:28]
7 K) e' C- `- ^8 n - u32 PLLSAIDIVR; //DCKCFGR1[17:16]- ~! o# v. G/ }1 v6 c6 z
- u32 temp;
$ ^' |7 ?/ o7 q% ` - 6 K1 c* Q, n" H# a2 h6 x. l
- if(ClockFreq < 1)ClockFreq = 1;, y( y% r1 i9 i
- if(ClockFreq > 100) ClockFreq = 100;- b4 }: h' A9 t- G0 A& o! X. F" D
- ! d- y( O* P+ ]# W7 c- g
- RCC->CR &= ~(1<<28); //关闭SAI时钟 ( |2 ?! q0 |8 F- ^. ]
- TimeOut = 0;
% U( c7 M! k0 }+ V2 c - while(RCC->CR&(1<<29)) //等待关闭成功
8 ]* v, ~; F T9 z0 M; a' |; U) o' t - {( ?5 ]/ g) T5 ~. J
- nop;; W# U" b; u1 D$ x9 B; z1 W
- TimeOut ++;5 Q1 T1 U4 _4 r) c. S1 U
- if(TimeOut > 0xFFFF) return FALSE; //关闭超时
: `7 \$ E L2 ~0 j. D' q, S' e - }
}; l g) @5 n0 W- f - //计算分频与VCO频率,通过PLLSAICFGR[30:28]可以设置2-7分频# \$ S' s5 ?! }
- //通过PLLSAICFGR[17:16]可以设置00:2 01:4 10:8 11:16分频
: U8 {- B6 Z) [ E& y - //通过PLLSAICFGR[14:6]可以设置为49-432MHz的VCO频率5 b$ f: {4 s! j! r
- if(ClockFreq <= 6)* `& E) x D4 u
- {' v5 J; E5 }% R
- PLLSAIR = 4; //4分频# B) t% a( I1 i& a4 z& ^6 B) _
- PLLSAIDIVR = 3; //16分频# B# p( z9 z2 y [" x0 k1 T/ |
- VCO = ClockFreq * PLLSAIR * 16; //VCO范围:64-384;
0 k- A; J% W1 }( V0 H: z w+ w: C$ H - }
1 ]+ y! E- O4 ^) _9 H6 a" t! p - else if(ClockFreq <= 13)$ n) S9 w& I! z( W
- {5 @/ v. h" q$ O+ E
- PLLSAIR = 4; //4分频* T0 C+ Q. t9 ?! m
- PLLSAIDIVR = 2; //8分频
& [* i2 P/ B: t/ j4 \ - VCO = ClockFreq * PLLSAIR * 8; //VCO范围:224-416;
9 m# p- Y& d) o/ t# q - }
4 B# \* e, u$ B2 ~/ k8 n - else if(ClockFreq <= 26)" H% C" ^2 H9 H9 p7 \0 T& f% _
- {& }+ d# U* @/ i" r% Q
- PLLSAIR = 2; //2分频
" Q8 r$ M7 g s - PLLSAIDIVR = 2; //8分频) q( ?( E$ S5 G& w) O
- VCO = ClockFreq * PLLSAIR * 8; //VCO范围:224-416;6 Y' w7 o% j# G8 i+ c
- }
3 H7 ^" v9 F0 ^ D( l - else if(ClockFreq <= 52)( H' h9 A' u3 J/ `7 m2 E( p X7 a3 P$ G
- {8 o1 J, E! [; m: u& n
- PLLSAIR = 2; //2分频
$ n! {. m* }( s3 g - PLLSAIDIVR = 1; //4分频
' b( M. e- G0 ]. Y2 j, x0 a5 [ - VCO = ClockFreq * PLLSAIR * 4; //VCO范围:216-416;
- ~& o2 m! Z6 W) I - }
) t3 C7 B% @0 y O! N. }' C - else if(ClockFreq <= 104) D( T3 U, v# q& D7 N
- {
4 h" k- s* n0 c. ~9 }. C6 A - PLLSAIR = 2; //2分频
" k! w$ y# \9 v c5 V$ n - PLLSAIDIVR = 0; //2分频3 s5 l# ?1 G: p* m& p4 I; Y, G
- VCO = ClockFreq * PLLSAIR * 2; //VCO范围:212-416;5 Q/ _. O5 T4 X1 D) D
- }
2 q6 Y' Q' |# z, h& Q- f8 N - //设置PLLSAICFGR
9 R+ `' V e& Z - temp = RCC->PLLSAICFGR;5 v- j: I: V+ D" x2 z0 H( A. j
- temp &= ~((3<<28) | (0x1FF<<6)); //清除之前的设置/ I, g. @, t1 b
- temp |= PLLSAIR << 28; //设置分频PLLSAICFGR[30:28]
! d0 H- A6 |: U+ ^0 C0 k- v- i2 R4 T - temp |= VCO << 6; //设置VCO
$ \9 H0 _( q7 o% }$ A - RCC->PLLSAICFGR = temp;0 ^, z/ K8 E9 a5 `0 H& j
- //设置DCKCFGR1. b2 `' }$ u. b. t9 [8 v8 ]6 Q; j0 ^
- temp = RCC->DCKCFGR1;
! Q% D9 w) w S K( {' t - temp &= ~(3<<16); //清除之前的设置; {# n/ }2 w( _; K. F/ U
- temp |= PLLSAIDIVR << 16; //设置分频DCKCFGR1[17:16]5 W3 {$ k K$ J& }6 Q- E
- RCC->DCKCFGR1 = temp;
7 { p. G$ p/ \/ r i - //启动时钟
3 n$ h# P( \9 i- M* n - RCC->CR |= 1<<28; //启动SAI时钟
6 ]: `* z3 v0 |8 m! E- k* ] - TimeOut = 0;
( x! { Q7 s+ X - while((RCC->CR&(1<<29)) == 0) //等待开启成功: O! n9 h1 c' Y( A% Q* \
- {
4 k0 V* l |: T) E$ ^ - nop;0 K: b, j; v/ a' |1 B
- TimeOut ++;
' d5 ^ p8 }- | - if(TimeOut > 0xFFFF) return FALSE; //开启超时5 ?) V9 l8 h, E
- }
) E! [+ t+ e% p8 z) p -
. o7 j$ \8 o7 P- R% a2 V1 R - return TRUE;
, r4 D) z" w$ g; [# I" t! o! b6 q( S - }4 m' E7 K$ g; G. c
- - \7 J6 a3 i. J
- 4 D& I' Q% g, U- x: g( w* g
- /*************************************************************************************************************************) U) F- p, M1 _+ e/ C7 z d _) q
- * 函数 : void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color)
1 v7 o* q2 E' G. F; R - * 功能 : 矩形填充(使用DMA2D)& j5 {+ d+ { v" U& l/ [; b
- * 参数 : LayerIndex:层选择0-1;sx,sy:开始坐标;ex,ey:结束坐标,color:需要填充的颜色- h8 D6 A4 C; V
- * 返回 : 无9 n5 o$ P2 W# P! O. ?, R
- * 依赖 : 底层宏定义
! h9 g' m* [. \: X# E% U - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
+ M) \$ N* @3 m# y7 N - * 时间 : 2019-10-30& J& i; ~# ?: k
- * 最后修改时间 : 2019-10-30 {' b, E& {8 h2 p7 Z" _
- * 说明 : 采用DMA2D实现3 R1 F* v0 E2 \. Z4 \! f
- *************************************************************************************************************************/
6 V1 p8 f# t5 u3 E2 G( D - void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color)& W4 ~2 G* U9 p) l. s/ d& S, d [$ D
- {
( _) Q7 |3 ~. V# g3 i7 Z% l" i3 z - DMA2D_FillColorToFGRAM((u32)&g_LTDC_BUFF_RGB888[LayerIndex][sy][sx], ex-sx+1, ey-sy+1, LTDC_WIDTH-(ex-sx+1), DMA2D_COLOR_ARGB8888, color); //DMA2D进行单色填充
5 ~$ M* l. n7 ~ x G% x - DMA2D_WaitTransferComplete(500); //等待DMA2D传输完成6 g2 `1 W5 ^/ H" V( G2 d7 e) e
- }
1 @6 x4 ^* ?( Q - & A! ?1 x; D( u# ~% L
- / _" |! f& k' Q5 \9 A$ `
- /*************************************************************************************************************************
4 t: q/ H- G! K; g - * 函数 : void LTDC_Clear(u8 LayerIndex,u32 color)
1 D; i7 H& G- M% X0 S8 A" r - * 功能 : 清屏(使用DMA2D)9 m3 \; {+ w- m) v: N) F& A
- * 参数 : LayerIndex:层选择0-1;color:需要填充的颜色
% Q% [% U8 H( A& D: s+ g4 z - * 返回 : 无
3 J& Q$ }2 z1 a% q f - * 依赖 : 底层宏定义; D3 g9 f/ R& s: z6 t9 M7 T! W
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
l6 S3 I- }4 p* o - * 时间 : 2019-10-302 O+ e3 P: ]9 I& E' Y: O
- * 最后修改时间 : 2019-10-300 J1 o, ~6 ?! b8 S2 v' ^7 ^
- * 说明 : 采用DMA2D实现1 X4 v! m6 Q6 N& n) f
- *************************************************************************************************************************/
; E9 V! A+ W( Q5 r* x2 H - void LTDC_Clear(u8 LayerIndex,u32 color)# k/ c) Z) ~* D) Z
- {
; @' E5 s7 b7 t# ]. v - DMA2D_FillColorToFGRAM((u32)&g_LTDC_BUFF_RGB888[LayerIndex][0][0], LTDC_WIDTH, LTDC_HEIGHT, 0, DMA2D_COLOR_ARGB8888, color); //DMA2D进行单色填充
) E& a8 J% h6 I; }( s9 m - SYS_DelayMS(5);% e' O) @6 u7 {, y
- DMA2D_WaitTransferComplete(500); //等待DMA2D传输完成
: B( d Z: e* I' P. q5 [' g! |7 W - }
% ^- p5 o7 S5 q) J8 A: H2 i" Z
9 Y0 M3 @" y; _) T+ K; W7 ?3 V
- [ K! {. g) ?4 Z- M0 ]( d- /*************************************************************************************************************************1 Y* ^$ E' Z% r* b
- * 函数 : void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr) {% N& l( `# v# a+ G1 a
- * 功能 : 矩形图像填充(相同坐标范围传输,要求源图像与目标显示器分辨率一致,使用DMA2D)
+ z( f" _& F. T/ {6 W4 v9 _ - * 参数 : LayerIndex:层选择0-1;sx,sy:开始坐标;ex,ey:结束坐标,ImageAddr:需要填充的图像地址6 T' T8 ~- ] [# x/ }
- * 返回 : 无4 h) K" a7 }$ c$ h; u* }
- * 依赖 : 底层宏定义
8 z% q( R' Z' ?' }: c - * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>/ w( B& x6 I9 T( B& S% U0 s
- * 时间 : 2019-10-30$ p, ^& \" V- _
- * 最后修改时间 : 2019-10-30' U0 e0 d" Z/ I( k
- * 说明 : 采用DMA2D实现,将源图像指定位置传输到现存,要求源图像与显存大小一致
+ w& q& k) l8 n. r: O* y - *************************************************************************************************************************/! m5 g9 [, P) l5 ~- M+ W" I
- void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr)* s' P8 ~/ i0 ?0 B/ o, m2 c
- {$ K" j/ x7 ~! p2 o5 n) q
- DMA2D_FillImageToFGRAM(ImageAddr+sy*LTDC_WIDTH+sx, (u32)&g_LTDC_BUFF_RGB888[LayerIndex][sy][sx], ex-sx+1, ey-sy+1, LTDC_WIDTH-(ex-sx+1), LTDC_WIDTH-(ex-sx+1), DMA2D_COLOR_ARGB8888);//DMA2D进行矩形图形填充' `: ~1 ~" G, V% }
- DMA2D_WaitTransferComplete(500);9 Q; w0 A( x* J @. N. M
- }
复制代码- /*************************************************************************************************************( v) _" C, m2 r* Z: ^ F
- * 文件名 : stm32f7_ltdc.h
1 x0 @3 {/ I8 M; Y* \0 I - * 功能 : STM32F7 外部RGB LCD驱动 V$ C# W" i {$ u* l$ V( v2 y
- * 作者 : <a href="mailto:cp1300@139.com">cp1300@139.com</a>
/ n# }( {7 ~1 T6 R9 W# S- A, O - * 创建时间 : 2019-09-12
! _0 m5 y4 g1 \# | - * 最后修改时间 : 2019-09-12
& e7 P; ], z8 U& h; E4 } - * 详细: 4 _# R- j1 t- Y, z
- *************************************************************************************************************/
+ s% j9 {2 t. w6 U2 U0 O) q+ V% P - #ifndef __STM32F7_LTDC_H_
( d/ N2 r- E: V' b+ j. g - #define __STM32F7_LTDC_H_ 5 F& X+ R% C( m$ O1 L# Q: X* \
- #include "system.h"
9 G$ m. Y9 }, r& S' O1 L - #include "DMA2D.h"
, Z1 T$ I6 k& i" l! A2 j& d
& o2 M" V) V* t K# h- #define LTDC_WIDTH 4805 e$ F, D+ B, {: H5 w
- #define LTDC_HEIGHT 272! m7 o# c/ Y i- b
- 1 `: F# Q, Y- L+ }2 Q1 j: h+ F
4 @2 U6 a0 j4 K* h- extern u32 g_LTDC_BUFF_RGB888[2][LTDC_HEIGHT][LTDC_WIDTH];
. \" D. `2 D9 L4 d* j3 g; X8 S5 k - + O: N6 f: i, h& J7 q5 H
- //像素格式定义
1 p6 [+ Q8 u- h- g( y: E - typedef enum
; V% U, r% ~3 d8 R* A8 v9 G - {
. Z v: n6 d" f - LTDC_ARGB8888 = 0,7 i: O n% n/ B/ O% x5 a8 F9 R
- LTDC_RGB888 = 1,2 |% j3 j, g3 |
- LTDC_RGB565 = 2,7 H3 f) Q* J- |5 k" U
- /*LTDC_ARGB1555 = 3,
+ f1 z9 J" E' u% ?1 T7 i+ D& L - LTDC_ARGB4444 = 4,. h! c. e( y' J
- LTDC_L8 = 5, //8 位 Luminance
, C2 H* v9 [. @2 C6 V) `/ a, l5 m - LTDC_AL44 = 6, //4 位 Alpha,4 位 Luminance+ h3 p9 ~3 [& U5 |9 F& ?* e, R! p; f
- LTDC_AL88 = 7, //8 位 Alpha,8 位 Luminance*/2 k6 L8 \: q: D! y
- }LTDC_PixelFormat;- T7 K1 G5 N1 g% \5 C
- #define LTDC_PIXEL_FORMAT LTDC_ARGB8888 //选择ARGB8888格式2 E5 a; q5 T: L
- [$ J5 j. X) y- H
0 M: R; |; e" }- 5 P: s" K9 G- \& W, x
+ L9 C' U2 u# R8 s Q1 Z6 [. N; c- //画点函数32bit ARGB8888格式; _& c6 }# t4 \ W
- __inline void LTDC_DrawPoint(u8 LayerIndex, u16 Xpos,u16 Ypos,u32 ARGB8888_Color)# I% J% l8 M+ d s& I0 {9 v7 [( E
- {/ a0 Q7 B/ {" A+ \( L W0 |
- g_LTDC_BUFF_RGB888[LayerIndex][Ypos][Xpos] = ARGB8888_Color;
; G3 b8 h/ @0 d - }/ p. T# ]/ y y7 \
* l2 C/ t g/ [. |6 c- //初始化DISP引脚9 W, \, M- \: ^' ?4 g
- __inline void LCD_DispIoInit(void)
8 D0 C" a! ~& C* Y' Q - {) \) o9 q& h, k- r! p* e
- SYS_GPIOx_Init(GPIOI, BIT12, OUT_PP, SPEED_25M); //PI12 LCD_DISP H:正常模式;L:低功耗 ) e N) {% P$ y& U
- PIout(12) = 1; //DISP = H 2019-10-16:一直忽略将此引脚置为高电平,调试走了很多弯路4 C" N5 X5 S+ c w. a2 u4 ]
- }' o4 O1 ^+ {3 L8 o0 w0 V( E
- / T+ X* |& a6 g
- void LTDC_Enable(bool Enable); //LTDC使能设置
0 ?5 {9 r, }2 T! u - void LTDC_Init(void); //LTDC 接口初始化/ ^" x0 ?+ G8 y3 X H
- void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha);//LTDC 层窗口尺寸设置7 Z; {; |( C" F6 K: X4 p. {4 l
- void LTDC_LayerEnable(u8 LayerIndex, bool Enable); //LTDC 层使能设置
7 T& K0 i7 g x - void LTDC_LayerRefreshConfig(void); //LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)1 x$ E* l& C3 m2 B; `
6 B" I8 w' w4 E4 N7 u- //图形相关API& s3 d( B) T$ M8 b) ~! r
- void LTDC_DrawPoint(u8 LayerIndex, u16 Xpos,u16 Ypos,u32 ARGB8888_Color); //画点函数32bit ARGB8888格式
& @, @( [8 Q+ r) f - void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color); //矩形填充(使用DMA2D)
0 g4 a: [5 w) ]$ \* J) [ - void LTDC_Clear(u8 LayerIndex,u32 color); //清屏(使用DMA2D)) I& g# D5 j% i1 q% w" S
7 Q. r8 _9 O1 A( `2 Q5 I- void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr);//矩形图像填充(相同坐标范围传输,要求源图像与目标显示器分辨率一致,使用DMA2D)
复制代码 ) s* z/ I: z/ V, \
! u0 }" o( A+ M7 }$ o7 R7 E1 W
#endif //__STM32F7_LTDC_H_
1 G) ?6 h4 x$ ]! U, Q
s5 E M1 |( d- {) C
) l7 z+ z/ V2 B0 c0 H! x2 k
* F& ~) L( W. w0 c$ l% c4 w |