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