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