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