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