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