你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32f746gdiscovery LTDC 驱动

[复制链接]
STMCU小助手 发布时间:2021-12-14 10:49
需要提前准备好SDRAM驱动,如果没有SDRAM可以进行纯色彩测试,底层时钟,IO操作相关看注释,我使用的是寄存器封装的。
" @+ j# f: `5 V  s2 n8 A2 i  n$ c" _. m* n2 e, N% i
  1. /*************************************************************************************************************! J) c& ?. e. k4 r
  2. * 文件名                :        stm32f7_ltdc.c% P* Q" e) \/ y7 ~; O" A5 R' t
  3. * 功能                        :        STM32F7 外部RGB LCD驱动0 e; g8 x4 ]; b; D
  4. * 创建时间                :        2019-09-12
    9 n* V. J) K* |0 y7 |
  5. * 最后修改时间        :        2019-09-12$ r! S& ]. L$ C+ _$ f
  6. * 详细:        
    6 Z2 H5 ?9 e  \) e2 J% t: W
  7. *************************************************************************************************************/        ( e  X6 K( g; Y3 \" w
  8. #include "stm32f7_ltdc.h"
    4 |' I! L& ~, T- ^$ F, t9 i
  9. #include "SYSTEM.H"
    & s/ u; Q: P! o) e9 V
  10. #include "stm32f7_sdram.h". W# A. X/ v3 o. j1 T0 c
  11. #include "DMA2D.h"
    - g% u6 s* _  d$ Z3 |  F
  12. + U  N/ {% k4 @; }' ?' t
  13. ! {8 Q' y4 I- F8 M( x3 I2 D8 w
  14. u32 g_LTDC_BUFF_RGB888[2][LTDC_HEIGHT][LTDC_WIDTH]  __attribute__ ((at(Bank5_SDRAM_ADDR)));                //需要SDRAM支持,LCD帧缓冲区,RGB888格式
    , d) m: G" w+ b, r% f6 ]3 D* J- K
  15. ( K8 i5 U+ \8 }; r# x

  16. ( A$ E# D! g, u1 J' r+ H1 _
  17. //记录全局层配置信息
    4 V4 `) J4 Z7 c) K$ C+ @% F  Y
  18. typedef struct
    % h) J, y7 ^; O/ X0 c7 N7 F4 s
  19. {
      u0 F* Y. }* r/ @4 d! d& b% r3 a
  20.         u16 sx;                                        //层开始X坐标,从0开始
    + i  P$ j8 D+ T  S9 b5 h
  21.         u16 sy;                                        //层开始Y坐标,从0开始
    " q5 p) R% F  ^. i/ n3 |* g
  22.         u16 width;                                //层宽度# v8 ~  h% a5 e, t
  23.         u16 height;                                //层高度, O  Y* l( f- v+ I2 p- ~
  24.         u32 *pFrameBuff;                //帧缓冲区指针,需要进行初始化6 |. i9 g1 I9 w% ~
  25. }LTDC_LayerConfig;
    4 c! j( d$ w2 m/ y2 P- g' m

  26. 7 k1 E, I# Q+ I9 m8 ^) R7 E

  27. 6 x: {9 f% N  p7 Z9 C

  28. 6 G! F: b) s+ V5 G+ v* ]
  29. //全局的LTDC配置信息
    ' l3 F  m( u! {# o# i. ]* I, t1 L
  30. typedef struct/ B. i* v1 O( \6 f* S
  31. {
    ' v  U7 ~6 n/ v& x: b/ H
  32.         u16 lcd_width;                                                //显示器宽度( `$ ]; a' o, a! S7 g0 M9 \5 ^# H
  33.         u16 lcd_height;                                                //显示器高度
      B- S# C* N: S0 U
  34.         LTDC_LayerConfig LayerConfig[2];        //层信息& j  W$ ?; B+ k7 ~. K2 @! {
  35. }LTDC_ConfigData;
    ' J7 Q# V* A" W, @

  36. $ M: M+ K9 w: {) Y8 J7 u& j
  37. & T2 R# d1 k5 w+ I8 i" m$ T
  38. static LTDC_ConfigData sg_LTDC_ConfigData;        //记录全局的LCD配置8 u1 x8 w' s5 S# x$ i! h
  39. 2 i9 m0 G4 u8 a1 e
  40. 7 e9 U% o# ]8 Q# `  R+ S& V
  41. //显示屏信息: G5 p. {; j" x6 x* H/ @5 {( Y
  42. typedef struct
      j- q. N2 P$ x2 T. G
  43. {- R8 D: G: G2 ~7 O7 h- V% k9 i
  44.         u16         Width;                //面板宽度,单位:像素' B) Z0 c9 e. l5 u7 d; \8 G3 M
  45.         u16         Height;                //面板高度,单位:像素
    4 K$ j7 q" Z5 Z( }" E: q3 }; [7 b8 k
  46.         u8          Thbp;                //水平后廊
    6 p9 E3 z( x& s2 j8 \- `
  47.         u8          Thfp;                //水平前廊
    ( m3 M+ K7 L; v
  48.         u8          Thw;                //水平同步宽度
    ) {/ ^' F2 v' l
  49.         u8          Tvbp;                //垂直后廊
    % f1 H( S# F- [5 ]
  50.         u8          Tvfp;                //垂直前廊
    / C: Z( p$ ~1 |' I2 w
  51.         u8          Tvw;                //垂直同步宽度* F0 _, ?; q7 T. V
  52.         u8          DCLK;                //时钟速度,MHz2 z' L$ H! q4 b% h( B% X
  53.         3 x. F( N" P" N
  54.         u8                HSPOL;                //水平同步极性,0:低电平有效;1:高电平有效
    0 c# @9 m$ q5 }) O7 }
  55.         u8                VSPOL;                //垂直同步极性,0:低电平有效;1:高电平有效
    % Q. t; U9 U& J  w- h
  56.         u8                DEPOL;                //数据使能极性,0:低电平有效;1:高电平有效
    & I1 T6 }: {- H
  57.         bool        PCPOL;                //像素时钟反向
    ; `4 m; o5 @# Q  s
  58. }LTDC_INFO_TYPE;
    0 Z. Y+ Y1 R0 p
  59. 7 @5 Y* j5 H" C3 ^" M- V, g

  60. ( R* j: R9 `3 s3 |
  61. LTDC_INFO_TYPE DefaultLCD_Info =
    $ U: L7 y! w" x7 K" ^3 q5 X
  62. {' I0 y" o" M* ?& f' w
  63.         480,        //面板宽度,单位:像素' }) a# I4 N1 g
  64.         272,        //面板高度,单位:像素" ^3 d/ ]. w" |' z3 N. U4 o
  65.         41,                //水平后廊: G: @5 U  [( @
  66.         8,                //水平前廊( ]4 |5 H$ g3 G
  67.         2,                //水平同步宽度& F/ s7 x8 U, u0 S5 V1 [* p
  68.         2,                //垂直后廊
    ( s0 }' P5 ?8 R+ ~; M* D% u1 E
  69.         4,                //垂直前廊
    6 I9 o) X7 n! Y* `  F
  70.         10,                //垂直同步宽度
    5 v6 U/ H* c; _+ G
  71.         9,                //时钟速度,MHz4 J# @' x) x3 Y- Y. g
  72.         0,                //水平同步极性,0:低电平有效;1:高电平有效- F/ m1 M7 N. y1 V- q& q5 |% b
  73.         0,                //垂直同步极性,0:低电平有效;1:高电平有效! z8 X& J4 Z2 J# R5 J9 k
  74.         1,                //数据使能极性,0:低电平有效;1:高电平有效- Q# G7 M  ~$ W' c/ V" {# q' X" g
  75.         FALSE,        //像素时钟反向; _/ v! Z5 a# {* [2 \
  76. };1 x4 P% J0 u, p# P" n

  77. / {2 @& t/ ?3 I' I: e
  78. bool LTDC_ClockInit(u16 ClockFreq);                                                        //STM32F4 LTDC时钟初始化
    2 d3 v' X$ l) u+ `+ g
  79. 6 Z7 @" G' g4 Y7 g* p  q$ @
  80. & J. {6 i. \" e/ D2 w, d& d, |
  81. /*************************************************************************************************************************9 n- t. F4 A" ]+ g5 E$ ~
  82. * 函数        :                        void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha), h/ u! f4 {. T2 s& I* I+ S3 u! T( L
  83. * 功能        :                        LTDC 层窗口尺寸设置(会自动根据窗口尺寸以及像素格式设置帧缓冲区大小), L3 V5 B2 A, L; A8 V
  84. * 参数        :                        LayerIndex:层选择(0-1);sx,sy:起始坐标;width,height:宽度和高度1 }' ?" P, c# z3 U
  85. * 返回        :                        无
    & G- \1 ]* C8 `7 a9 |
  86. * 依赖        :                        底层宏定义
    # n: [# U, m) o( q$ O
  87. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    4 b9 |$ S2 c3 O8 d' q
  88. * 时间        :                        2019-10-28
    1 J8 e" \/ O2 U4 `# k9 |" c
  89. * 最后修改时间 :         2019-10-28
    9 |6 T- F' D( C
  90. * 说明        :                         不会使能层,不会更新层,只设置配置,需要刷新层配置后更新& Q8 t8 Q5 _2 ^  q3 q
  91. *************************************************************************************************************************/
    4 z/ E5 r$ U2 R
  92. void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha)
    " Y* q* z8 w; ~# c: n
  93. {5 [# h3 |5 p* w3 W
  94.         u32 temp;$ z5 [# w5 G4 b2 N; d
  95.         u8 pixformat=0;
    - P# C- W3 K& w; {$ \# T+ {' B
  96.         
    % c/ v4 _% |: C$ H
  97.         if(LayerIndex==0)
    $ p- j; \/ Y" r7 ]7 @! v/ C
  98.         {
    ( o0 w' Y* X: B" R
  99.                 //基本配置
    : O" ^6 J  K: x( B$ h& M
  100.                 LTDC_Layer1->CFBAR = FrameBuff;                                                                        //设置层颜色帧缓存起始地址
    1 R- l3 k& U  c8 J1 n
  101.                 LTDC_Layer1->PFCR = LTDC_PIXEL_FORMAT;                                                        //设置层颜色格式8 A+ N/ [7 V/ D* Q4 |/ C
  102.                 LTDC_Layer1->CACR = Alpha;                                                                                //常数 Alpha,255分频;设置255,则不透明
      [: h( P1 g! p* K1 D2 G
  103.                 LTDC_Layer1->DCCR = 0x00;                                                                                //设置默认颜色:透明的黑色
    % w" m4 c% o" `* z3 L% q+ n
  104.                 LTDC_Layer1->BFCR = ((u32)6<<8)|7;                                                                //设置层混合系数; s& V+ f# D5 h1 ?$ h( C2 x
  105.                 //配置窗口& @& \  O# O  ?6 ]9 W6 }
  106.                 temp = (sx+width+((LTDC->BPCR&0X0FFF0000)>>16))<<16; " Q) ^! S4 ~0 E1 Y* i' a6 H4 ?3 S
  107.                 LTDC_Layer1->WHPCR = (sx+((LTDC->BPCR&0X0FFF0000)>>16)+1)|temp;//设置行起始和结束位置 ' r6 Q$ T4 g7 Z. L4 K9 r4 g
  108.                 temp = (sy+height+(LTDC->BPCR&0X7FF))<<16; ) _) |; m/ [" p
  109.                 LTDC_Layer1->WVPCR = (sy+(LTDC->BPCR&0X7FF)+1)|temp;                        //设置列起始和结束位置
    1 R. w) p" N; U# b# z9 Y5 M- b( o
  110.                 pixformat = LTDC_Layer1->PFCR&0X07;                                                                //得到颜色格式
    . b; ?9 N# x* W9 |8 X, {8 ~
  111.                 if(pixformat == 0)temp=4;                                                                                //ARGB8888,一个点4个字节
    4 ^! x9 }8 r* }9 `" @
  112.                 else if(pixformat == 1)temp=3;                                                                        //RGB888,一个点3个字节
    - d9 a. T+ ~. u- k9 l6 G
  113.                 else if(pixformat==5||pixformat==6)temp=1;                                                //L8/AL44,一个点1个字节
    & ]% g* J  v) ]+ w3 Y5 u  F/ z
  114.                 else temp=2;                                                                                                        //其他格式,一个点2个字节
    % _4 ^' L. h; T( X) s
  115.                 LTDC_Layer1->CFBLR = (width*temp<<16)|(width*temp+3);                        //帧缓冲区长度设置(字节为单位)
    , G# u% i  v( X: T
  116.                 LTDC_Layer1->CFBLNR = height;                                                                        //帧缓冲区行数设置        
    1 V4 v  P0 `; m8 p% t1 V9 I# ^
  117.                
    . k8 ]9 v  m, o2 }
  118.                 //记录层窗口大小位置信息
    1 B; ?. m* e, F; e, B: e# _# Z& W
  119.                 sg_LTDC_ConfigData.LayerConfig[0].sx = sx;               
    ! K$ I$ s, G; X4 ?% C$ z) W, n6 H
  120.                 sg_LTDC_ConfigData.LayerConfig[0].sy = sy;        0 b# J* a' R7 d' U* U3 Z
  121.                 sg_LTDC_ConfigData.LayerConfig[0].width = width;        ; I+ U3 r/ Z2 a6 V
  122.                 sg_LTDC_ConfigData.LayerConfig[0].height = height;        
    # z. M+ g; ]! m8 b
  123.         }else
    ' G: J/ M( |) }# y3 S( S( m
  124.         {
    8 s9 p2 t- n  a5 o6 r
  125.                 //基本配置2 j' {* Y6 ~4 d  l* Z1 \
  126.                 LTDC_Layer2->CFBAR = FrameBuff;                                                                        //设置层颜色帧缓存起始地址
    ! B/ m$ i) \- `' F
  127.                 LTDC_Layer2->PFCR = LTDC_PIXEL_FORMAT;                                                        //设置层颜色格式( U6 N4 ], B5 T9 b1 M; K+ V
  128.                 LTDC_Layer2->CACR = Alpha;                                                                                //常数 Alpha,255分频;设置255,则不透明
    0 O$ W; W& B( P
  129.                 LTDC_Layer2->DCCR = 0x00;                                                                                //设置默认颜色:透明的黑色. c7 M; e4 n: n  x: K; s1 d
  130.                 LTDC_Layer2->BFCR = ((u32)6<<8)|7;                                                                //设置层混合系数8 M# c- o% |: z) P
  131.                 //配置窗口% i/ M6 m) u: r: J5 @
  132.                 temp = (sx+width+((LTDC->BPCR&0X0FFF0000)>>16))<<16;
    , m3 r& W7 p) N' U
  133.                 LTDC_Layer2->WHPCR = (sx+((LTDC->BPCR&0X0FFF0000)>>16)+1)|temp;        //设置行起始和结束位置
    ) u8 L" c, ?  m
  134.                 temp = (sy+height+(LTDC->BPCR&0X7FF))<<16;
    : `% H) X  C7 I2 _. g8 J- `  n
  135.                 LTDC_Layer2->WVPCR = (sy+(LTDC->BPCR&0X7FF)+1)|temp;                        //设置列起始和结束位置
    6 ^* U8 B2 `. B/ o
  136.                 pixformat = LTDC_Layer2->PFCR&0X07;                                                                //得到颜色格式
    ) ^! g0 a) X: ~5 c4 V  A) v! }# g; i
  137.                 if(pixformat == 0)temp=4;                                                                                //ARGB8888,一个点4个字节
    . x% \5 Z8 a6 u+ {
  138.                 else if(pixformat == 1)temp=3;                                                                        //RGB888,一个点3个字节
    1 d8 \  K9 A/ z$ a" N. F" m
  139.                 else if(pixformat == 5||pixformat==6)temp=1;                                        //L8/AL44,一个点1个字节4 \% G. y; X! I  u4 x7 o" A
  140.                 else temp = 2;                                                                                                        //其他格式,一个点2个字节
    + h+ N9 C; h; U5 q3 m+ z3 y
  141.                 LTDC_Layer2->CFBLR = (width*temp<<16)|(width*temp+3);                        //帧缓冲区长度设置(字节为单位)9 @$ V0 U2 |) |- z2 W8 \, O- H+ G, P  w
  142.                 LTDC_Layer2->CFBLNR = height;                                                                        //帧缓冲区行数设置        5 C' E& ^( G. o7 D( D5 g# R# g
  143.                
    3 S, M! d- }/ m# U( c) w
  144.                 //记录层窗口大小位置信息
    4 m/ W2 @. a4 ^& b3 V' }9 C
  145.                 sg_LTDC_ConfigData.LayerConfig[1].sx = sx;                + L2 Z, v  r8 C: L$ n" T  s
  146.                 sg_LTDC_ConfigData.LayerConfig[1].sy = sy;        8 X" n, ]2 r: N7 W9 ^( [. W
  147.                 sg_LTDC_ConfigData.LayerConfig[1].width = width;        $ C8 @- }) m& N
  148.                 sg_LTDC_ConfigData.LayerConfig[1].height = height;                  O" c5 _4 J6 y: _" R, ~8 E  M
  149.         }
      L7 C" u0 J! K/ Y% h2 Y$ E
  150. }
      `' p9 U+ t+ q1 t  E5 I& \2 r
  151. ; ^# y- x0 I; I! u, z! H. F/ D

  152. * i* t2 _" z3 q) d! s; s2 D$ X
  153. 6 z+ t( e5 h4 J
  154. /*************************************************************************************************************************% q- n' _2 M& p2 R1 J& b0 h' o! \
  155. * 函数        :                        void LTDC_Init(void). s; b, c( \0 Y$ R0 j
  156. * 功能        :                        LTDC 接口初始化0 k- a7 l! g. D: [: d
  157. * 参数        :                        无4 r( T- r3 f# i2 a5 ?3 K! y
  158. * 返回        :                        无# v4 _' \6 B1 j) B
  159. * 依赖        :                        底层宏定义
    $ q/ }! m8 V% f, F8 E
  160. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    . S' F( e. C8 o3 @, B- r$ f- j& k
  161. * 时间        :                        2019-09-08
    4 e/ s/ `9 G: \, S6 Z
  162. * 最后修改时间 :         2019-09-08
    5 |- I( [! P9 W( R* W' M
  163. * 说明        :                         用于初始化STM32F7 LTDC 接口
    - b5 [* e3 k+ O; h
  164. *************************************************************************************************************************/  
    : L- l$ t5 q$ d& G  q
  165. void LTDC_Init(void)
    : d  S4 ]2 r- X% p- T8 n
  166. {1 k1 n$ ~, Z/ R2 u, S8 n9 q, d0 ?( c
  167.         u32 temp;
    % w* ?7 A, Z& v; N4 Q
  168.         
    & ]# i7 X" m9 J3 J) u/ Z
  169.         SYS_DeviceClockEnable(DEV_LTDC, TRUE);        //LTDC时钟使能/ ~0 v! G* t! m6 g. A- Z1 j
  170.         SYS_DeviceReset(DEV_LTDC);                                //STM32F7外设复位( r6 T+ i2 R4 a2 |4 H* l! s
  171.         SYS_DeviceClockEnable(DEV_GPIOE, TRUE);        //使能GPIOE时钟
    6 a. i: F* |8 u) K; L/ \* z
  172.         SYS_DeviceClockEnable(DEV_GPIOG, TRUE);        //使能GPIOG时钟$ j; w7 A7 j1 f- p/ `- c6 |/ F
  173.         SYS_DeviceClockEnable(DEV_GPIOJ, TRUE);        //使能GPIOJ时钟: z, i7 \) n! X. ]/ ?
  174.         SYS_DeviceClockEnable(DEV_GPIOK, TRUE);        //使能GPIOK时钟
    5 V( Z2 r, a* A9 V  k- g* k
  175.         SYS_DeviceClockEnable(DEV_GPIOI, TRUE);        //使能GPIOI时钟
    8 \3 |$ m9 A; X9 o" p1 k
  176. ' P9 e: L& a3 ~% `$ ]2 m" h, u
  177.         
    ! e: o! \' L7 ~  Z
  178.         //初始化IO
    ' I' L' u) V* E# G+ u) j0 H  ^
  179.         SYS_GPIOx_Init(GPIOE, BIT4, AF_PP_OPU, SPEED_100M);                                                                                //PE4
    . T) V9 E" W# \8 v2 \
  180.         SYS_GPIOx_Init(GPIOG, BIT12, AF_PP_OPU, SPEED_100M);                                                                        //PG12
    , Q, L" R; m7 q4 }6 x( {& w
  181.         SYS_GPIOx_Init(GPIOJ, 0Xffff&(~BIT12), AF_PP_OPU, SPEED_100M);                                                        //PJ0~11/13/14/15
    3 j( P1 ]# G1 F3 f8 N, x5 R2 Q
  182.         SYS_GPIOx_Init(GPIOK, BIT0|BIT1|BIT2|BIT4|BIT5|BIT6|BIT7, AF_PP_OPU, SPEED_100M);                //PK0/1/2/4/5/6/7
    6 R; b7 A  @: h7 q+ V  i
  183.         SYS_GPIOx_Init(GPIOI, BIT9|BIT10|BIT14|BIT15, AF_PP_OPU, SPEED_100M);                                        //PI9/10/14/15  K: l' d+ \+ D* v3 ]! k$ K" Y' r
  184.         * t& r. d; F* t% i# d* z
  185.         SYS_GPIOx_SetAF(GPIOE, 4, AF14_LTDC);                //PE4,AF14        1 `1 }2 y1 d3 }6 E6 _1 x; s
  186.          SYS_GPIOx_SetAF(GPIOG, 12, AF14_LTDC);                //PG12,AF14        5 |; E) x5 n2 X- a% r
  187.         SYS_GPIOx_SetAF(GPIOJ, 0, AF14_LTDC);                //PJ0,AF14
    8 I- @0 G$ r/ J9 k0 Q& l
  188.         SYS_GPIOx_SetAF(GPIOJ, 1, AF14_LTDC);                //PJ1,AF14: i- v! F& v2 {6 X- ?& E
  189.         SYS_GPIOx_SetAF(GPIOJ, 2, AF14_LTDC);                //PJ2,AF14$ A7 q1 f4 g5 R- }9 @& x$ F* w
  190.         SYS_GPIOx_SetAF(GPIOJ, 3, AF14_LTDC);                //PJ3,AF14) ?0 a) }+ D% i% s
  191.         SYS_GPIOx_SetAF(GPIOJ, 4, AF14_LTDC);                //PJ4,AF14/ p' }2 m3 M: ~
  192.         SYS_GPIOx_SetAF(GPIOJ, 5, AF14_LTDC);                //PJ5,AF14" _$ B' H; q4 c2 D' S
  193.         SYS_GPIOx_SetAF(GPIOJ, 6, AF14_LTDC);                //PJ6,AF14
    - K! u, Q' |; z3 {0 n3 G% @3 N
  194.         SYS_GPIOx_SetAF(GPIOJ, 7, AF14_LTDC);                //PJ7,AF14
    7 w% R/ I% [( J; F3 K7 d
  195.         SYS_GPIOx_SetAF(GPIOJ, 8, AF14_LTDC);                //PJ8,AF14$ A/ R% r8 _  R0 a0 z$ a: P
  196.         SYS_GPIOx_SetAF(GPIOJ, 9, AF14_LTDC);                //PJ9,AF14
    2 y1 O5 @" |5 f. }6 |
  197.         SYS_GPIOx_SetAF(GPIOJ, 10, AF14_LTDC);                //PJ10,AF14' h" Q5 k6 T) R* c
  198.         SYS_GPIOx_SetAF(GPIOJ, 11, AF14_LTDC);                //PJ11,AF14) q! B" b. U' S
  199.         SYS_GPIOx_SetAF(GPIOJ, 13, AF14_LTDC);                //PJ13,AF14
    + J/ Y9 v7 @1 i% ?
  200.         SYS_GPIOx_SetAF(GPIOJ, 14, AF14_LTDC);                //PJ14,AF14( z4 @& o2 _2 N( o1 D" d
  201.         SYS_GPIOx_SetAF(GPIOJ, 15, AF14_LTDC);                //PJ15,AF14
    ) @* I& N# U* f( O
  202.         
    8 m6 ^# \# J) R5 b+ d! L: P
  203.         SYS_GPIOx_SetAF(GPIOK, 0, AF14_LTDC);                //PK0,AF14
    + |9 ^) c& |8 a& J: k
  204.         SYS_GPIOx_SetAF(GPIOK, 1, AF14_LTDC);                //PK1,AF14% j3 C# }0 }3 s* f* y  z! s$ V
  205.         SYS_GPIOx_SetAF(GPIOK, 2, AF14_LTDC);                //PK2,AF14
    2 _* |2 w7 n/ J2 d( O/ i
  206.         SYS_GPIOx_SetAF(GPIOK, 4, AF14_LTDC);                //PK4,AF14( c0 h% K# A( o( z
  207.         SYS_GPIOx_SetAF(GPIOK, 5, AF14_LTDC);                //PK5,AF14
    # ?' @; M* f9 f- r
  208.         SYS_GPIOx_SetAF(GPIOK, 6, AF14_LTDC);                //PK6,AF14
    # s0 X+ I' K( u* Q
  209.         SYS_GPIOx_SetAF(GPIOK, 7, AF14_LTDC);                //PK7,AF149 Z8 `  [) p3 Y0 ]% A7 G$ g
  210.         " N* M% N) r6 M7 e: v' w5 B
  211.          SYS_GPIOx_SetAF(GPIOI, 9, AF14_LTDC);                //PI9,AF14+ r4 t3 f! f6 e; o0 k0 l7 ]9 f
  212.          SYS_GPIOx_SetAF(GPIOI, 10, AF14_LTDC);                //PI10,AF14 0 b' O' M/ A# f3 P
  213.         SYS_GPIOx_SetAF(GPIOI, 14, AF14_LTDC);                //PI14,AF14
    1 K: E' X$ V. b8 `% d; ^' I% D
  214.          SYS_GPIOx_SetAF(GPIOI, 15, AF14_LTDC);                //PI15,AF14
    ! m5 U% ^4 }% t) P
  215.         
    % [8 F" R* `9 {- i
  216.         LTDC_ClockInit(DefaultLCD_Info.DCLK);                 //设置像素时钟  9Mhz " e0 V( S. B) O1 V  {$ ?- o
  217.         //设置LTDC 全局控制寄存器 (LTDC_GCR)2 n* i2 W) V0 T  A9 F1 {+ K
  218.         temp = 0;
    . j0 v) k" y/ c, V
  219.         temp |= (DefaultLCD_Info.HSPOL&0x01) << 31;        //水平同步极性
    # e) e$ }! a2 V
  220.         temp |= (DefaultLCD_Info.VSPOL&0x01) << 30;        //垂直同步极性
    * t: o+ \+ k, p2 r' V+ ?) j1 z
  221.         temp |= (DefaultLCD_Info.DEPOL&0x01) << 29;        //数据使能极性
    . U; G! @9 u, U
  222.         temp |= (DefaultLCD_Info.PCPOL&0x01) << 28;        //像素时钟极性/ R4 g6 n' \& p0 a3 v+ m
  223.         LTDC->GCR = temp;
    % O3 B: _! N/ |$ ]6 K
  224.         //LTDC 后沿配置寄存器 (LTDC_BPCR)
    / }6 u7 i1 R" E( j0 o$ B1 {6 d
  225.         temp = (DefaultLCD_Info.Tvw + DefaultLCD_Info.Tvbp - 1) << 0;        //这些位定义累加水平后沿宽度(水平同步像素加水平后沿像素减 1)。2 G! a( e) ^, x! ], W1 F% A
  226.         temp |= (DefaultLCD_Info.Thw + DefaultLCD_Info.Thbp - 1) << 16;        //这些位定义累加垂直后沿宽度(垂直同步行加垂直后沿行减 1)。! o; N* a, h8 C5 C- Y4 [/ I
  227.         LTDC->BPCR=temp;        
    $ m% N" d7 D* q, n% J. y
  228.         . |' l, M& L+ K' C4 l( w# ^+ o* r3 g# }
  229.         //LTDC 有效宽度配置寄存器 (LTDC_AWCR)
    & c- w1 W. a) i$ X/ b- I
  230.         temp=(DefaultLCD_Info.Tvw+DefaultLCD_Info.Tvbp+DefaultLCD_Info.Height-1)<<0;        //累加有效高度=垂直脉宽+垂直后沿+垂直分辨率-1
    4 c, K6 }# f" o& ~
  231.         temp|=(DefaultLCD_Info.Thw+DefaultLCD_Info.Thbp+DefaultLCD_Info.Width-1)<<16;        //累加有效宽度=水平脉宽+水平后沿+水平分辨率-1, W8 E( p; _; m$ A$ ]2 G
  232.         LTDC->AWCR=temp;        
    $ f" Y; M4 R$ H1 Y
  233.         //LTDC 总宽度配置寄存器 (LTDC_TWCR)
    ( P  N" y3 p9 F( ~) C' ~
  234.          temp=(DefaultLCD_Info.Tvw+DefaultLCD_Info.Tvbp+DefaultLCD_Info.Height+DefaultLCD_Info.Tvfp-1)<<0;        //总高度=垂直脉宽+垂直后沿+垂直分辨率+垂直前廊-1
    / x% S4 }: v/ A5 x
  235.         temp|=(DefaultLCD_Info.Thw+DefaultLCD_Info.Thbp+DefaultLCD_Info.Width+DefaultLCD_Info.Thfp-1)<<16;        //总宽度=水平脉宽+水平后沿+水平分辨率+水平前廊-1
    , I! C5 }. @3 G
  236.         LTDC->TWCR=temp;                                
    * N1 W+ }. v4 `( Z; M3 [' |1 ~
  237. 0 P- |6 y  k" h1 ]+ Q2 [
  238.         //背景设置
    5 z/ a4 x' \) M! g4 f. s, b
  239.         LTDC->BCCR=0xffffff;                                //设置背景层颜色寄存器(RGB888格式)
    4 M) Q( }6 p( n9 h9 l
  240.         LTDC_Enable(TRUE);                                        //开启LTDC- d% d& R* [6 J/ d
  241.         //初始化层13 ~7 v1 a. ?0 B' A
  242.         LTDC_SetLayerConfig(0, 0, 0, LTDC_WIDTH, LTDC_HEIGHT, (u32)g_LTDC_BUFF_RGB888[0], 255);& L8 n" ]  r, Y- ]) R1 `0 z- k
  243.         //初始化层2) Q" \# \% R8 X3 c1 r, r4 Q& x
  244.         LTDC_SetLayerConfig(1, 0, 0, LTDC_WIDTH, LTDC_HEIGHT, (u32)g_LTDC_BUFF_RGB888[1], 255);
    " t6 u! V8 s: _0 ~: u9 e0 Y
  245.         LTDC_Clear(0, 0xFF000000);                        //清屏层1-不透明的黑色
    * u  W* [1 N4 _" g
  246.         LTDC_Clear(1, 0x00000000);                        //清屏层2-透明的黑色+ R& f' I7 N2 ^" v( t5 z1 r
  247.         LTDC_LayerEnable(0, TRUE);                        //使能层1
    0 ?9 p9 v% o9 K7 F! J3 g
  248.         LTDC_LayerRefreshConfig();                        //LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)
    , R9 D/ }+ \4 p# K3 i- S$ h
  249.         LCD_DispIoInit();                                        //初始化DISP引脚-启动显示: ?3 j6 E: {9 E9 m3 t; T) t5 I
  250. }0 k5 S' u9 R: ?

  251. , A6 c8 m2 Z* W% w7 ]1 ]
  252. /*************************************************************************************************************************
    1 n0 g6 [8 A  L0 U0 a
  253. * 函数                        :        void LTDC_LayerRefreshConfig(void)4 l9 v$ A" g* d) T1 l" h
  254. * 功能                        :        LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)7 a$ c) _, p# u& \3 S
  255. * 参数                        :        无! q+ i" F  I- m+ _# i
  256. * 返回                        :        无
    % Z# G0 w& [8 S9 f5 x5 a
  257. * 依赖                        :        底层宏定义
    $ y7 @3 j- z( e
  258. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    7 l) f9 v1 T% d. u* J+ c( V( r9 }
  259. * 时间                        :        2019-10-29
    ; q: ]1 `, y# C/ w
  260. * 最后修改时间         :         2019-10-297 ^- k+ G& T: P6 b8 ~" w
  261. * 说明                        :        修改层配置后必须重新加载,否则不会生效
      U5 v8 d' G. U/ M: A2 t6 _5 v. N
  262. *************************************************************************************************************************/# e, E9 ~; h( |+ c! I! W6 Z+ ^" g
  263. void LTDC_LayerRefreshConfig(void)- Z5 {! a9 h) a! B$ [
  264. {
    8 Z' ~, P9 S& i8 m5 V
  265.         LTDC->SRCR|=1<<0;                                                        //重新加载配置-必须重新加载,否则上面的层不会更新,折腾好久才发现,叫啥影子寄存器重载,也不说清楚6 I/ @* A2 f0 b% U9 c: M
  266. }
    & i, b. d* X/ d  O4 N

  267. 3 N5 s+ H6 S3 l7 E
  268. /*************************************************************************************************************************
    " L! m: K+ e- ^% M+ W# E' e
  269. * 函数                        :        void LTDC_Enable(bool Enable)7 Y1 H3 o7 Z1 W5 W" n
  270. * 功能                        :        LTDC使能设置
    8 v! {& S& h- e% e3 e8 ]
  271. * 参数                        :        Enable:TRUE:使能;FALSE:失能5 |- ~0 G) K# s( _+ V( O' u
  272. * 返回                        :        无
      X" u3 d* V0 Q" W8 f
  273. * 依赖                        :        底层宏定义  B! I+ D3 N8 j, ^
  274. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    " V) w8 V3 ?( k/ v, b: q$ D( P
  275. * 时间                        :        2019-10-29
    6 {$ w" ]& P; M  o
  276. * 最后修改时间         :         2019-10-29
    ' {/ _. n) Y- G$ @
  277. * 说明                        :        * |6 ^, O7 z7 }- R! S' P# M! X
  278. *************************************************************************************************************************/
    5 N  G$ P& S) O* _0 l' N
  279. void LTDC_Enable(bool Enable)
    $ {5 K! X/ ^5 r5 t. G/ O
  280. {
    5 h; o! ^" J6 @0 K. t8 t5 K% l# J
  281.         if(Enable)  B3 i1 K: H+ J2 G% I5 U
  282.         {
    % y! q& }  Y' a% ~) \: V
  283.                 LTDC->GCR |= BIT0;                                        //打开LTDC
    / x9 \- C" t  Z* i
  284.         }: U0 U# y4 [# \$ L; J
  285.         else
    ) {* `0 L8 \1 N9 i/ f8 ?6 h
  286.         {1 o5 P% d7 N0 \3 T% f$ x
  287.                 LTDC->GCR &= ~BIT0;                                        //关闭LTDC  \8 W6 [. S  f4 h
  288.         }8 a( Z  U/ [) A3 D, ^
  289. }# k. z" \6 I4 w& O6 D. S

  290. 7 K" g$ y: Z' Z, n+ \6 }/ y
  291. /*************************************************************************************************************************
    4 b8 @' e9 d5 Z1 |
  292. * 函数                        :        void LTDC_LayerEnable(u8 LayerIndex, bool Enable)
    * _5 n. k& }5 `' u4 a4 d2 B
  293. * 功能                        :        LTDC 层使能设置0 A! y' j" C. c, }. o' w. \) ?
  294. * 参数                        :        LayerIndex:层选择0-1;Enable:TRUE:使能;FALSE:失能) F0 @! [( l( W7 Y
  295. * 返回                        :        无# w# \9 S" a" v% I% _
  296. * 依赖                        :        底层宏定义
    # b: t& n5 j" ^; m" S( h
  297. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    . @* [# n' u! `8 A' g9 k
  298. * 时间                        :        2019-10-29
    + d7 Q3 S- j# r
  299. * 最后修改时间         :         2019-10-29: y: V& j8 {5 A; i
  300. * 说明                        :        " z5 l; g% ]' V" Z& ?' p# j
  301. *************************************************************************************************************************/
      @4 V8 X, m& x) P% \. H
  302. void LTDC_LayerEnable(u8 LayerIndex, bool Enable)
    3 u7 D! P  Q; l1 u" W* \( Z3 I' b6 r( X' a
  303. {
    6 f4 \  ?  e" ]
  304.         if(Enable)
    * O; ^! o' _- v6 x9 A1 n$ }
  305.         {5 ]% R% _5 r% e# }. L. d) W
  306.                 if(LayerIndex == 0)                                        //层10 K2 ~9 a2 ]; }: ~- k9 c1 j
  307.                 {% f7 b1 D5 E- M) _8 t$ k
  308.                         LTDC_Layer1->CR |= BIT0;                //使能层1
    * v+ v0 p0 a4 L& \0 R( u
  309.                 }' u$ U: k/ ?1 ^& M7 z$ x& I
  310.                 else
    : c# H) {  v' G) K
  311.                 {) C4 ?7 Z, T  t+ I) e
  312.                         LTDC_Layer2->CR |= BIT0;                //使能层2  Z: U  M# n0 g0 V
  313.                 }. H$ Y( e& J5 d- a9 V% @, j
  314.         }: Y+ k, ]1 R+ x' \
  315.         else  A! p; j/ o+ U6 y  P8 |/ c2 o' k
  316.         {5 U! ^) o# v6 o# X/ m' g8 I5 N
  317.                 if(LayerIndex == 0)                                        //层1
    - O+ A1 k& i& W9 ^1 N
  318.                 {
    6 ?( Z# G4 s2 l  f- o8 p" e  o  V: W
  319.                         LTDC_Layer1->CR &= ~BIT0;                //失能层1* |3 X& c$ ^6 A* b+ H) f- o& C% j7 s4 V
  320.                 }2 v0 b% O" u! H: O
  321.                 else
    ' R# a5 S6 n; ?* D7 u& P9 U
  322.                 {
    2 u- A* |7 U. N- _
  323.                         LTDC_Layer2->CR &= ~BIT0;                //失能层2
    0 j. d/ P0 |- w- I
  324.                 }
    & u. y6 G# n2 W  z
  325.         }9 b* a9 r6 H2 w7 h) s; |7 p$ ]$ v
  326. }) s0 @) K/ ?8 m
  327. 2 g/ s; ^( L4 y6 F0 {

  328. . d* ~% q" Q4 |  a  M/ w7 z

  329. & P/ l# ?' k2 X3 a

  330. % a& _8 Z# W" o* ?
  331. /*************************************************************************************************************************
    - l. ?4 @+ s+ g3 e! ?4 x
  332. * 函数                        :        bool LTDC_ClockInit(u16 ClockFreq)                        6 f5 U3 Y% D, g2 d* L! n
  333. * 功能                        :        STM32F7 LTDC时钟初始化& F. T  M, x$ O5 {
  334. * 参数                        :        ClockFreq:时钟频率,2-168MHZ
    ( o- \1 z1 X1 d6 R* w
  335. * 返回                        :        是否设置成功5 t/ W1 r8 P: {* G. H8 c4 A2 }% a
  336. * 依赖                        :        底层宏定义* `9 \8 t- k6 Q
  337. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    8 A3 g* x6 ~9 Q: d
  338. * 时间                        :        2019-10-28
      Z8 o+ v% b5 X9 G- i; a' _
  339. * 最后修改时间         :         2019-10-28
    5 I6 A% ?' x% n
  340. * 说明                        :        输入时钟频率在系统主时钟初始化之后就会设置为1MHz,通过设置SAI PLL实现LTDC所需频率,VCO频率范围:49~432
    6 r6 u9 G; {: S2 X  O& @" t- J& g
  341. *************************************************************************************************************************/0 k$ s- }# f: u+ K. W% M9 Q
  342. bool LTDC_ClockInit(u16 ClockFreq)2 x  L# g' p2 {. c4 y2 b6 D# o
  343. {
    , @' B- o2 k2 U; C5 B
  344.         u32 TimeOut = 0;
    0 Y/ K( N' k  W( }6 \
  345.         u32 VCO;; _: p" j; L) f0 k4 W# K
  346.         u32 PLLSAIR;                //PLLSAICFGR[30:28]& Y/ |5 p6 p( A& f' E1 ?  P2 @
  347.         u32 PLLSAIDIVR;                //DCKCFGR1[17:16]# V0 ]5 j6 `" q3 m' M" D# |% |
  348.         u32 temp;. v6 H  Y. R# D4 E& v0 v+ S6 |1 j
  349.         
    " H( \% _, o4 S3 Y0 _$ k
  350.         if(ClockFreq < 1)ClockFreq = 1;8 V6 ^& \0 k. v; }: y/ m* C) C& x
  351.         if(ClockFreq > 100) ClockFreq = 100;# K& d, x3 b6 C2 d7 U
  352.         / Q3 r: e8 C3 a2 x1 j) G2 s/ ~) S- ~
  353.         RCC->CR &= ~(1<<28);                                                //关闭SAI时钟 8 f  {: G8 x! R6 u% ]1 z
  354.         TimeOut = 0;3 M: h, E& v" \- f0 L& p4 Z
  355.         while(RCC->CR&(1<<29))                                                //等待关闭成功
    , h9 m8 X2 D: r+ M+ A
  356.         {1 o& b' _8 B8 Z
  357.                 nop;
    9 @9 K. |) a1 h! i" T' z0 T2 h
  358.                 TimeOut ++;! W) m7 |# j$ j3 e  d+ |
  359.                 if(TimeOut > 0xFFFF) return FALSE;                //关闭超时
    ( D: X. p" V, e5 A1 N- ]! D
  360.         }
    & x3 P2 t' f* D" P1 k' c0 E
  361.         //计算分频与VCO频率,通过PLLSAICFGR[30:28]可以设置2-7分频+ g9 N- S) Z$ t! v5 n! P
  362.         //通过PLLSAICFGR[17:16]可以设置00:2 01:4 10:8 11:16分频
    3 d' L3 q" x- |% y
  363.         //通过PLLSAICFGR[14:6]可以设置为49-432MHz的VCO频率
    1 S2 o- Z( ^$ E2 _: I4 D# ^
  364.         if(ClockFreq <= 6)1 T8 c3 b7 `: R, y
  365.         {
    . y0 A8 t! b# z; ]: `/ z) ]
  366.                 PLLSAIR = 4;        //4分频' s0 n7 k1 q/ j4 j
  367.                 PLLSAIDIVR = 3;        //16分频
    3 r, u' I% }" j# R, x/ I, m
  368.                 VCO = ClockFreq * PLLSAIR * 16;                        //VCO范围:64-384;
    5 }0 `$ X) t  n% Q: r4 y
  369.         }* N7 P& n" A  o& w3 Z
  370.         else if(ClockFreq <= 13)* E+ x$ R7 h7 E1 }7 ~: r
  371.         {( t6 }* N) V# [! ]
  372.                 PLLSAIR = 4;        //4分频
    ' E8 T# V$ P! ~' G: b% T9 @
  373.                 PLLSAIDIVR = 2;        //8分频9 V0 U4 A* ]  W0 y9 {* Y' @1 K
  374.                 VCO = ClockFreq * PLLSAIR * 8;                        //VCO范围:224-416;
    + Q/ x3 `! m4 ~, i
  375.         }
    ) ]' T0 M0 a6 j
  376.         else if(ClockFreq <= 26)
    ; x4 {& L5 R8 _% U! e
  377.         {
    1 ~4 p2 l5 ^" N2 I3 K
  378.                 PLLSAIR = 2;        //2分频
    + {8 J8 f( ]0 k! J2 N% r; F# V
  379.                 PLLSAIDIVR = 2;        //8分频
    0 U9 Q# Q% B) g8 u  T
  380.                 VCO = ClockFreq * PLLSAIR * 8;                        //VCO范围:224-416;# y# t0 t% E0 Y# Z
  381.         }# }7 ~4 v4 F. W  R
  382.         else if(ClockFreq <= 52)
    ! o+ p9 T+ _! X& k
  383.         {) S7 n1 E' e8 Z1 w
  384.                 PLLSAIR = 2;        //2分频' n, e. E# ?* G& X' t
  385.                 PLLSAIDIVR = 1;        //4分频; Q4 y9 C4 p0 r$ m2 @2 K. h+ c5 P: O8 y
  386.                 VCO = ClockFreq * PLLSAIR * 4;                        //VCO范围:216-416;
    , N0 \$ q$ b. r
  387.         }! Y% K8 U2 |( m4 L4 [
  388.         else if(ClockFreq <= 104)7 q% i2 P& Z8 `+ I
  389.         {
    . v4 p% U& K5 [/ }
  390.                 PLLSAIR = 2;        //2分频; ?3 X5 U& ^" Z3 F
  391.                 PLLSAIDIVR = 0;        //2分频: p4 x0 r8 S+ r' x4 a& j- g( C
  392.                 VCO = ClockFreq * PLLSAIR * 2;                        //VCO范围:212-416;3 W& t& a7 M, |! t
  393.         }
    * g5 ]& ~8 a/ ]+ b* z5 }' b0 E
  394.         //设置PLLSAICFGR3 j- j" y. S. v, T
  395.         temp = RCC->PLLSAICFGR;
      k0 ~4 F% c- C# P7 a& s
  396.         temp &= ~((3<<28) | (0x1FF<<6));                        //清除之前的设置
    1 |$ F2 V) I6 W1 g" n% q
  397.         temp |= PLLSAIR << 28;                                                //设置分频PLLSAICFGR[30:28]
    / q) b, n$ u% _- A1 P& L* c
  398.         temp |= VCO << 6;                                                        //设置VCO
    ( a* g, K$ m* i! v
  399.         RCC->PLLSAICFGR = temp;
    4 y8 X) o2 A, F9 g8 E4 K( a1 A& ]  _( U4 `
  400.         //设置DCKCFGR1
    , i# K7 ?) c# R- F+ U* _* W
  401.         temp = RCC->DCKCFGR1;
    ' g3 [0 u8 r+ A' N. @) v+ N+ Z
  402.         temp &= ~(3<<16);                                                        //清除之前的设置
    5 C. _2 ?" P1 T% z: p
  403.         temp |= PLLSAIDIVR << 16;                                        //设置分频DCKCFGR1[17:16]! z0 X, h& i! K
  404.         RCC->DCKCFGR1 = temp;
    5 M/ w  p! G3 B, ^- S* y
  405.         //启动时钟' @# H; Q  B: X3 z: x
  406.         RCC->CR |= 1<<28;                                                        //启动SAI时钟
    8 [" U) x0 \4 r- Q7 M5 x
  407.         TimeOut = 0;
    0 Z* Q- x( _7 }% W
  408.         while((RCC->CR&(1<<29)) == 0)                                //等待开启成功6 a4 _: G! x# O# Y- o: S
  409.         {- W9 q0 K& t) X8 S! G9 |4 i
  410.                 nop;% G' ?9 ^" j; b  J8 R
  411.                 TimeOut ++;
    $ U  d% l, C( G9 U" f+ W5 w
  412.                 if(TimeOut > 0xFFFF) return FALSE;                //开启超时5 R0 h/ q, [  C9 u# R, U7 z
  413.         }
    " D0 B: m; v. f* ^2 E! e$ N3 E
  414.         $ c% V; E7 w8 E4 e2 P& |
  415.         return TRUE;: {7 n7 z5 g) Y$ |! g4 Y5 j3 }
  416. }
    - j! k: H, C) _3 M1 v
  417. & D; t  t0 A( r- E. B

  418. ; I$ F! S, q  I; p! M1 w2 G" U
  419. /*************************************************************************************************************************
    , n+ F8 u1 E2 t
  420. * 函数                        :        void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color)        ; g* R) b! U7 G0 Q$ t
  421. * 功能                        :        矩形填充(使用DMA2D)( k4 p5 s( Y! }9 I# \1 ]$ G* d) U
  422. * 参数                        :        LayerIndex:层选择0-1;sx,sy:开始坐标;ex,ey:结束坐标,color:需要填充的颜色% c) [% T  c% h8 g" i3 e
  423. * 返回                        :        无2 P! F) O, o. }: D. m
  424. * 依赖                        :        底层宏定义7 e! ~2 S1 y* ?: P9 [4 a, [
  425. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>7 N! K+ R( ?3 k: Y6 n
  426. * 时间                        :        2019-10-30
    2 H$ y$ h$ K* {/ \, ~2 k  U
  427. * 最后修改时间         :         2019-10-30; c4 j0 q) T  v, I) I! U& {  r, @3 s
  428. * 说明                        :        采用DMA2D实现
    5 Y+ Q# _; z0 A7 v0 L2 C
  429. *************************************************************************************************************************/
    $ ]( [) d: K: S# T- |
  430. void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color)1 Z( |/ x; U1 f9 N
  431. {. c/ @, Q, v9 H" {
  432.         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进行单色填充/ |2 o& g& l" k  P0 P: k9 b
  433.         DMA2D_WaitTransferComplete(500);                                                                                                                                                                                                                                //等待DMA2D传输完成
    ( D/ W0 X' c( J$ ^0 \! s
  434. }
    3 A* C: k1 |' e

  435. & n' X  e/ O( v7 E9 F. ^2 E1 n* C

  436. ) c, x/ a- S' J4 H0 e! X
  437. /*************************************************************************************************************************6 U: r7 P* Z0 e; j1 P4 j$ K
  438. * 函数                        :        void LTDC_Clear(u8 LayerIndex,u32 color)7 J# R; p' @/ E  V% i& {
  439. * 功能                        :        清屏(使用DMA2D)+ t- b6 t( c# R) _) G  Z5 i
  440. * 参数                        :        LayerIndex:层选择0-1;color:需要填充的颜色
    # X- ~! U. g% `/ Z) e: x2 \+ _
  441. * 返回                        :        无
    7 j! d1 z0 ]! N, k
  442. * 依赖                        :        底层宏定义1 Q4 C0 U' Q2 ~8 Z- E0 k
  443. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    ' s# Z2 q2 B  ^+ ^' k) i( N( @: S. I
  444. * 时间                        :        2019-10-30, e6 r* B2 V- D, ]2 P  E7 M( a
  445. * 最后修改时间         :         2019-10-30
    3 D; ?+ e. T& h# z6 A. s
  446. * 说明                        :        采用DMA2D实现: d. N: q1 m# u' X- P. ~
  447. *************************************************************************************************************************/9 @' I, k5 m# [  d, q6 t
  448. void LTDC_Clear(u8 LayerIndex,u32 color)
    % f, G9 \6 W) f8 l5 v. z! S
  449. {2 K" a4 j8 T/ K2 l7 a9 e& N7 Z4 p7 _
  450.         DMA2D_FillColorToFGRAM((u32)&g_LTDC_BUFF_RGB888[LayerIndex][0][0], LTDC_WIDTH, LTDC_HEIGHT, 0,  DMA2D_COLOR_ARGB8888, color);                                        //DMA2D进行单色填充: j$ `8 \" m* i/ T" |. q, X
  451.         SYS_DelayMS(5);
    ( r2 z2 Y. z: H. J( e
  452.         DMA2D_WaitTransferComplete(500);                                                                                                                                                                                                                                //等待DMA2D传输完成' o& [# Y+ F0 v' d5 y1 `: ?, k
  453. }9 ]0 B0 ~( h1 @
  454. 2 ]5 ]) U% J5 S' K: R/ t! B0 q, `9 A! D6 Y
  455. ) W/ z: Y) @4 ]" T/ O
  456. /*************************************************************************************************************************  U! i* u7 [3 k" {; m
  457. * 函数                        :        void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr): Y7 Q0 ?( \0 ^: K+ d& z( Y* \
  458. * 功能                        :        矩形图像填充(相同坐标范围传输,要求源图像与目标显示器分辨率一致,使用DMA2D)
    4 h  a6 ~4 `' I3 ~, l3 F  g
  459. * 参数                        :        LayerIndex:层选择0-1;sx,sy:开始坐标;ex,ey:结束坐标,ImageAddr:需要填充的图像地址
    ; J9 D7 P* w2 c* @
  460. * 返回                        :        无
    " z5 U/ L' K7 `0 k$ f2 t
  461. * 依赖                        :        底层宏定义
    ) s/ [7 f6 B/ V1 N* y
  462. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    " t% _8 v+ m) i7 {4 |
  463. * 时间                        :        2019-10-30* J- }( r/ D  `# \+ V% d- s: j5 W
  464. * 最后修改时间         :         2019-10-30
    1 E  x% V' C* D, ^. T
  465. * 说明                        :        采用DMA2D实现,将源图像指定位置传输到现存,要求源图像与显存大小一致
    2 d" k5 y& D3 G" }$ [5 N$ Y
  466. *************************************************************************************************************************/9 _* p% B/ [) v" W- r, r" k7 M# w
  467. void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr)
    ; m# R5 D1 }; ^+ ]* Z. b+ r7 ]7 X
  468. {/ D7 {9 h8 n5 d* t. u- X
  469.         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进行矩形图形填充1 s5 h, o, |  I- S( F. e
  470.         DMA2D_WaitTransferComplete(500);( |% @( f5 b- q$ C0 m' X( _
  471. }
复制代码
  1. /*************************************************************************************************************
    5 [- g# ^+ v; W; j; N
  2. * 文件名                :        stm32f7_ltdc.h
    # Q& \1 e' b6 E+ K
  3. * 功能                        :        STM32F7 外部RGB LCD驱动
    9 |7 B8 m8 G' c, |% c; q- A/ N$ v
  4. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>4 x! Z- l7 r* H
  5. * 创建时间                :        2019-09-12' ^+ M, T# \$ i( H3 a3 i. T6 U
  6. * 最后修改时间        :        2019-09-12
    : r& O- \) [! L$ ?: T
  7. * 详细:        9 J% B( T4 W' O
  8. *************************************************************************************************************/                / S% c, ]! F* p% {% N
  9. #ifndef __STM32F7_LTDC_H_+ Z1 t" X2 ]  b2 f; S9 S5 U* O
  10. #define        __STM32F7_LTDC_H_           " L$ L9 r) J7 l* L  ^
  11. #include "system.h"1 I( A! Q  V! N
  12. #include "DMA2D.h": K3 C" W: j2 t* g2 r9 ?  p* a
  13. ) \3 l# s) h1 M( C4 t6 r, w: ~2 ?
  14. #define LTDC_WIDTH                480  z3 s2 j6 k% x  j9 H$ A
  15. #define LTDC_HEIGHT                272
    % }6 M8 v( B3 y7 J' h+ `$ J0 P

  16. ( `' a/ k2 V8 h
  17.   ^  \9 G& ?+ O0 N  ^5 y9 S
  18. extern u32 g_LTDC_BUFF_RGB888[2][LTDC_HEIGHT][LTDC_WIDTH];. D4 B2 h5 q; n

  19. * b$ Z, O/ D" _* Y- R/ V: F( b
  20. //像素格式定义0 z+ k- h* i, {* b) F, s
  21. typedef enum
    / L: [/ G5 ~. n, v7 G
  22. {: q1 D( m. F; o
  23.         LTDC_ARGB8888         = 0,  B1 {3 e5 D. r/ i  |
  24.         LTDC_RGB888         = 1,
    / N% j  n6 h2 Q3 p5 c
  25.         LTDC_RGB565         = 2,
    / Q' w+ d: j) @& M' E) ], r% `
  26.         /*LTDC_ARGB1555         = 3,
    8 g+ W/ E9 H! k6 I4 H6 \
  27.         LTDC_ARGB4444         = 4,& @' @! j3 d- C* C3 r2 f% O1 ^
  28.         LTDC_L8                 = 5,        //8 位 Luminance- C4 ~  `# Y# f* Q; H
  29.         LTDC_AL44                 = 6,        //4 位 Alpha,4 位 Luminance
    3 K2 ^% q( ^/ H$ l8 j
  30.         LTDC_AL88                 = 7,        //8 位 Alpha,8 位 Luminance*/
    ; ]5 Q; R+ t# P+ I% a4 r
  31. }LTDC_PixelFormat;6 y7 g$ x' G1 r( b$ Y2 h$ s
  32. #define LTDC_PIXEL_FORMAT                LTDC_ARGB8888                //选择ARGB8888格式
    : u5 B% Y+ ^$ s$ \9 |2 D
  33. - o3 \" _7 b% }  o6 v$ f

  34. " _; ^$ l  h3 l, T& ^: p  A

  35. + `7 E, q& R. N. a/ l# e, h/ L) r
  36. / q! r( m4 s+ R/ @+ j( R' f( J* R$ T. ^
  37. //画点函数32bit ARGB8888格式
    ! \! U/ R+ U- l) I- X: d4 y, X
  38. __inline void LTDC_DrawPoint(u8 LayerIndex, u16 Xpos,u16 Ypos,u32 ARGB8888_Color)2 i2 \! d# Q7 U) _9 A" T
  39. {/ s- [/ P! j) I7 I
  40.         g_LTDC_BUFF_RGB888[LayerIndex][Ypos][Xpos] = ARGB8888_Color;
    3 Y0 {4 c# |/ U6 Z, f
  41. }
    0 ]* F+ M) V7 p$ l% g% @& y
  42. 7 L- C6 [1 H3 x( l$ S/ q( b
  43. //初始化DISP引脚
    # C, a* i9 k" h; d4 v
  44. __inline void LCD_DispIoInit(void)) X* l* c+ C, D! o$ q
  45. {) f5 F, y% B% D" z4 k; k+ @* B
  46.         SYS_GPIOx_Init(GPIOI, BIT12, OUT_PP, SPEED_25M);                                                                                                //PI12 LCD_DISP H:正常模式;L:低功耗                                                        
    ) O- c  Y/ ^- H
  47.         PIout(12) = 1;                                                                                                                                                                        //DISP = H  2019-10-16:一直忽略将此引脚置为高电平,调试走了很多弯路
    : M- K: t: q" q
  48. }$ J. Y2 I5 T: [7 L
  49. , M( ]! H* L$ f5 s
  50. void LTDC_Enable(bool Enable);                                                                                                                                                //LTDC使能设置
    : H  L1 F% [' ~: i/ W7 L
  51. void LTDC_Init(void);                                                                                                                                                                //LTDC 接口初始化! Z& L9 Y( W+ o$ o& M7 H
  52. void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha);//LTDC 层窗口尺寸设置! S/ k5 s& r6 x/ P3 t/ |
  53. void LTDC_LayerEnable(u8 LayerIndex, bool Enable);                                                                                                        //LTDC 层使能设置
    0 t) E" Z0 m. d
  54. void LTDC_LayerRefreshConfig(void);                                                                                                                                        //LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)
    - U: Z# q9 {" S6 ?9 `$ A
  55. . K; ]3 b) b8 ?
  56. //图形相关API' @( A8 X, u- h) _1 s
  57. void LTDC_DrawPoint(u8 LayerIndex, u16 Xpos,u16 Ypos,u32 ARGB8888_Color);                                                        //画点函数32bit ARGB8888格式
    + B$ h7 A! G& J0 p; ^$ s; q1 W
  58. void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color);                                                                //矩形填充(使用DMA2D)7 R2 {6 W- {( ~, r5 ]3 |
  59. void LTDC_Clear(u8 LayerIndex,u32 color);                                                                                                                        //清屏(使用DMA2D)% \" B+ P1 t+ I, W
  60. $ G  t& z9 P  c/ ~( C: K$ e
  61. void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr);//矩形图像填充(相同坐标范围传输,要求源图像与目标显示器分辨率一致,使用DMA2D)
复制代码

1 a' g) [: m9 |' g! T  Y1 d( {
, R. `8 J" L! D$ g+ V) s3 |) y2 N# r#endif //__STM32F7_LTDC_H_
5 N$ O& Z: b' i2 t+ C8 z* f2 @# {
1 j/ _6 ?; A( v" W  W& @" M3 y$ n0 n. `! b" \; \! K$ n

6 x1 ]( g  q* |4 k
收藏 评论0 发布时间:2021-12-14 10:49

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版