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