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