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