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