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

【经验分享】STM32f746gdiscovery LTDC 驱动

[复制链接]
STMCU小助手 发布时间:2021-12-14 10:49
需要提前准备好SDRAM驱动,如果没有SDRAM可以进行纯色彩测试,底层时钟,IO操作相关看注释,我使用的是寄存器封装的。) B8 }8 _; p& i3 i, x, e: N
. M6 H% x0 z, \3 ^; E) {) u- L* Z
  1. /*************************************************************************************************************' @5 P* R  M8 I, I! N# f$ @
  2. * 文件名                :        stm32f7_ltdc.c
    " _; i/ p+ {7 f8 Y- {  O
  3. * 功能                        :        STM32F7 外部RGB LCD驱动
    + l- f# @) y  \; ~; A
  4. * 创建时间                :        2019-09-12+ q8 j/ n  \# p; e$ U8 @
  5. * 最后修改时间        :        2019-09-12. [3 z0 G" R5 O- n, m
  6. * 详细:        2 a4 J8 e7 X# V2 a5 ^. G; `# Y( @
  7. *************************************************************************************************************/        
    5 r% p( \% A0 `1 f3 @
  8. #include "stm32f7_ltdc.h"
    ' J& w7 M7 E) s% @. e% j
  9. #include "SYSTEM.H" 7 [& U7 l" [+ C5 c5 C$ @* d
  10. #include "stm32f7_sdram.h"" x& B& s1 R; |/ w* D5 P/ }
  11. #include "DMA2D.h"
    / v  m7 f6 W" M" O
  12. % J; F- t5 C1 Z& n

  13.   H, j; o) d4 W8 Y1 [# V8 h# F" }
  14. u32 g_LTDC_BUFF_RGB888[2][LTDC_HEIGHT][LTDC_WIDTH]  __attribute__ ((at(Bank5_SDRAM_ADDR)));                //需要SDRAM支持,LCD帧缓冲区,RGB888格式+ k* U! {, r& a

  15. ; {; J! l, o' R- s8 i
  16. 8 O5 V2 K( g  H
  17. //记录全局层配置信息
    ' D, d8 f0 S+ c% V9 q& I  n
  18. typedef struct8 {4 `# @0 i6 F3 P
  19. {
    * _# U" o* Z# _# X0 r
  20.         u16 sx;                                        //层开始X坐标,从0开始
    8 z: z/ L# L7 j, b$ g
  21.         u16 sy;                                        //层开始Y坐标,从0开始
    + T: \- f+ `! H5 p5 L' `: P) q
  22.         u16 width;                                //层宽度
    1 r7 I! D7 H$ b9 A; p
  23.         u16 height;                                //层高度
    7 [' j- @4 |: |6 h5 s' ?
  24.         u32 *pFrameBuff;                //帧缓冲区指针,需要进行初始化% L! F$ W  E2 Z
  25. }LTDC_LayerConfig;
    $ f4 R3 k7 ?0 L9 [

  26. ! G# e% X. A* f2 q0 K9 W9 v
  27. 8 c: G0 q9 y- `& f

  28. : [* D" c. l7 Y: l- J2 y5 U; E0 |
  29. //全局的LTDC配置信息+ Q* b3 Z2 m- P# Y9 a1 q# e& M+ }# p
  30. typedef struct
      z- u0 }5 U6 b( m' C
  31. {
    8 A7 u0 x. t9 g/ L) H8 Y% k
  32.         u16 lcd_width;                                                //显示器宽度1 `  u1 e- W8 j
  33.         u16 lcd_height;                                                //显示器高度
    / B8 I" K" q6 O! e( J
  34.         LTDC_LayerConfig LayerConfig[2];        //层信息" i) d. @6 W; G
  35. }LTDC_ConfigData;2 h# p& {" d% x; q0 \
  36. + B! P; h0 U9 w- i

  37. 3 r3 x: L# Y% e! d
  38. static LTDC_ConfigData sg_LTDC_ConfigData;        //记录全局的LCD配置" g8 ]. v0 `* p# W7 L5 x/ l

  39. 3 m! U3 D0 _% g6 s
  40. 0 L$ ^; J2 c& B% v/ X8 u0 p. b
  41. //显示屏信息
    1 K' C  ~/ F9 L# z+ ^* J. {
  42. typedef struct0 H& a0 i0 ]5 M7 a; _$ J% _
  43. {
    $ Z% {/ U# f( h9 I9 J
  44.         u16         Width;                //面板宽度,单位:像素" n) Q  p3 e6 k
  45.         u16         Height;                //面板高度,单位:像素: z9 P  r4 F- q% n8 L" f7 ?5 k
  46.         u8          Thbp;                //水平后廊9 m2 C6 B2 n. T4 F+ i7 x
  47.         u8          Thfp;                //水平前廊/ T+ S3 c% v, Q1 m& M# m
  48.         u8          Thw;                //水平同步宽度. K# Y- y, }* l7 z" \4 c% U
  49.         u8          Tvbp;                //垂直后廊+ i  S, F$ x8 A. p) ]
  50.         u8          Tvfp;                //垂直前廊
    # p* F$ O( T/ w& U# D8 h
  51.         u8          Tvw;                //垂直同步宽度4 m3 ?/ ~4 w- n; s
  52.         u8          DCLK;                //时钟速度,MHz2 B+ H3 Z( [. u: A/ \7 Y( I5 q
  53.         . I- y2 X$ v. Y, k9 H3 Q* t$ I
  54.         u8                HSPOL;                //水平同步极性,0:低电平有效;1:高电平有效
    + Q4 x. V/ {0 q5 f4 \+ k) _
  55.         u8                VSPOL;                //垂直同步极性,0:低电平有效;1:高电平有效
    9 e7 V2 H! H, `2 C, V6 B! A
  56.         u8                DEPOL;                //数据使能极性,0:低电平有效;1:高电平有效
    % q  J" @0 h& j4 x4 C
  57.         bool        PCPOL;                //像素时钟反向
    ! i6 W) N$ |5 v
  58. }LTDC_INFO_TYPE;3 X; I: ^( f* e  ]* f/ }

  59. ! h0 q) l, h7 y1 q- d

  60. ' b8 o% ]2 y2 l; X* x! K9 X) I5 n
  61. LTDC_INFO_TYPE DefaultLCD_Info =
    . n: T( v1 ~& c5 O
  62. {
    7 J4 b- V$ w9 U* u6 w, N
  63.         480,        //面板宽度,单位:像素  D$ o+ H# [& R& H9 h# |  F8 E
  64.         272,        //面板高度,单位:像素8 p- v0 U1 Q* c/ L
  65.         41,                //水平后廊; n4 X- G: I# g1 U# q% V( ^- z8 g
  66.         8,                //水平前廊! g7 R7 ~9 n! b! c& B* E
  67.         2,                //水平同步宽度
    8 @, E3 q0 C% t' y# |
  68.         2,                //垂直后廊, C  v7 a7 }( |
  69.         4,                //垂直前廊
    6 B& t3 G6 G% u
  70.         10,                //垂直同步宽度& D; F9 e- x  z
  71.         9,                //时钟速度,MHz- O; O( h) C; v, y4 B6 m1 e
  72.         0,                //水平同步极性,0:低电平有效;1:高电平有效
    / @! s0 C" U* o
  73.         0,                //垂直同步极性,0:低电平有效;1:高电平有效2 }1 w, T# n0 z5 C. M+ P  U" `
  74.         1,                //数据使能极性,0:低电平有效;1:高电平有效
    8 h3 P6 q6 u& W6 n2 N
  75.         FALSE,        //像素时钟反向
    % e1 S6 O. j1 X4 @. f
  76. };
    " D% O$ s7 x  k: ^

  77. # R) }+ J9 [+ N7 e7 a: v! c% B8 `
  78. bool LTDC_ClockInit(u16 ClockFreq);                                                        //STM32F4 LTDC时钟初始化* i4 a6 _$ T" q3 |
  79. , Z, K' O+ f4 C" E' Y7 w' ]* N4 H
  80. . s4 Z& T$ h7 H7 P  o
  81. /*************************************************************************************************************************
    3 D) o9 k) m1 y2 G9 d
  82. * 函数        :                        void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha)# V' u4 s5 x- J6 q6 P
  83. * 功能        :                        LTDC 层窗口尺寸设置(会自动根据窗口尺寸以及像素格式设置帧缓冲区大小)) x  i  Q" e1 K+ H1 P
  84. * 参数        :                        LayerIndex:层选择(0-1);sx,sy:起始坐标;width,height:宽度和高度
    . a4 `" a! t3 r& c8 l
  85. * 返回        :                        无
    9 f+ a. k! C% z6 ~6 o' ]
  86. * 依赖        :                        底层宏定义, J* {7 ?9 L8 ~2 Z$ ~
  87. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>9 ^9 r: h2 K# \/ f
  88. * 时间        :                        2019-10-28; P' X* i2 E7 U3 R
  89. * 最后修改时间 :         2019-10-28: V9 h* y( a5 o& N
  90. * 说明        :                         不会使能层,不会更新层,只设置配置,需要刷新层配置后更新
    , x0 W/ ?" c; Y# _# y7 {/ w# K9 G
  91. *************************************************************************************************************************/
    7 i& E, H0 N6 \$ W# [# K
  92. void LTDC_SetLayerConfig(u8 LayerIndex,u16 sx,u16 sy,u16 width,u16 height, u32 FrameBuff, u8 Alpha)
    % L5 j7 s' S6 Y, T5 U
  93. {2 \9 L$ x, k; |+ R8 F0 J6 p$ j' r, |$ ^
  94.         u32 temp;
    % p# D0 p" c0 g# K0 b: D" m
  95.         u8 pixformat=0; - `3 V: b; o$ C0 ~0 @+ a
  96.         1 y5 X" N5 _* ?, Z: V8 _9 [' |
  97.         if(LayerIndex==0), H( F( h. e" m
  98.         {
    2 H+ q9 y+ T- o" M
  99.                 //基本配置
    + d8 b1 M4 d8 R1 U, ]* X2 Y7 s
  100.                 LTDC_Layer1->CFBAR = FrameBuff;                                                                        //设置层颜色帧缓存起始地址
    2 k+ C* H! V0 s1 m
  101.                 LTDC_Layer1->PFCR = LTDC_PIXEL_FORMAT;                                                        //设置层颜色格式0 e' E4 |( Y: Q! d+ O
  102.                 LTDC_Layer1->CACR = Alpha;                                                                                //常数 Alpha,255分频;设置255,则不透明0 ~& G! _( {4 U/ J  H. t2 B. p" ?
  103.                 LTDC_Layer1->DCCR = 0x00;                                                                                //设置默认颜色:透明的黑色% q9 B2 U: ]% q. g" Z5 l
  104.                 LTDC_Layer1->BFCR = ((u32)6<<8)|7;                                                                //设置层混合系数
    2 L0 X; P6 S! S- n9 i) f) k  ~
  105.                 //配置窗口* J' k% n5 W3 X) j
  106.                 temp = (sx+width+((LTDC->BPCR&0X0FFF0000)>>16))<<16;
    0 E0 P( W7 x7 x/ y
  107.                 LTDC_Layer1->WHPCR = (sx+((LTDC->BPCR&0X0FFF0000)>>16)+1)|temp;//设置行起始和结束位置 5 m) Q4 O/ V1 |; _
  108.                 temp = (sy+height+(LTDC->BPCR&0X7FF))<<16; ! Q: w7 T8 J- w* a" v9 H/ g' g% J
  109.                 LTDC_Layer1->WVPCR = (sy+(LTDC->BPCR&0X7FF)+1)|temp;                        //设置列起始和结束位置
    3 K, ]& T0 r4 z9 ?  K$ i
  110.                 pixformat = LTDC_Layer1->PFCR&0X07;                                                                //得到颜色格式
    : H* g. b5 R2 E7 p* Y
  111.                 if(pixformat == 0)temp=4;                                                                                //ARGB8888,一个点4个字节1 F, g0 i- b8 R9 V; X
  112.                 else if(pixformat == 1)temp=3;                                                                        //RGB888,一个点3个字节
    , }6 z, `: O" n: Z
  113.                 else if(pixformat==5||pixformat==6)temp=1;                                                //L8/AL44,一个点1个字节' ?( O6 K) J1 ?: P: f
  114.                 else temp=2;                                                                                                        //其他格式,一个点2个字节7 J  i2 X0 d6 f* u6 h
  115.                 LTDC_Layer1->CFBLR = (width*temp<<16)|(width*temp+3);                        //帧缓冲区长度设置(字节为单位)
    ; X* ^9 K# K& O' R# z7 e
  116.                 LTDC_Layer1->CFBLNR = height;                                                                        //帧缓冲区行数设置        
    " L( ?+ I$ H$ _2 y4 N6 g
  117.                 1 j  |* A6 T" E! Z" B2 C( c, s
  118.                 //记录层窗口大小位置信息
    ' L# m9 a; v9 Y5 F; u7 A+ A, Q" D
  119.                 sg_LTDC_ConfigData.LayerConfig[0].sx = sx;                . n0 c0 `# I5 e# c; q2 k' M( |
  120.                 sg_LTDC_ConfigData.LayerConfig[0].sy = sy;        : h% }# k2 r4 W6 H" q. R
  121.                 sg_LTDC_ConfigData.LayerConfig[0].width = width;        
    , {' x" f* g; o, d0 i0 W# L$ t  \
  122.                 sg_LTDC_ConfigData.LayerConfig[0].height = height;        / a. I8 J6 d1 {" `8 W
  123.         }else$ d& O) N/ ?6 ~( ?; z
  124.         {
    + I. }. M9 n! A  l
  125.                 //基本配置
    # m. T* D4 V6 z3 y* ]" M# p' a
  126.                 LTDC_Layer2->CFBAR = FrameBuff;                                                                        //设置层颜色帧缓存起始地址3 a) Y2 G) _) V. h2 S4 \! ~
  127.                 LTDC_Layer2->PFCR = LTDC_PIXEL_FORMAT;                                                        //设置层颜色格式; }) Y4 o4 D: j. ~( W
  128.                 LTDC_Layer2->CACR = Alpha;                                                                                //常数 Alpha,255分频;设置255,则不透明
    ' w1 H2 s0 ?2 R. i9 [
  129.                 LTDC_Layer2->DCCR = 0x00;                                                                                //设置默认颜色:透明的黑色
    ; H3 w& P3 J8 W5 z( Q* _! G# b8 g
  130.                 LTDC_Layer2->BFCR = ((u32)6<<8)|7;                                                                //设置层混合系数
    ) e# N/ ]7 t" z% Z8 Q& h
  131.                 //配置窗口
    7 J9 D3 L) |/ z8 ~
  132.                 temp = (sx+width+((LTDC->BPCR&0X0FFF0000)>>16))<<16; ; ?0 X+ x! @- v" R2 Y! S. L
  133.                 LTDC_Layer2->WHPCR = (sx+((LTDC->BPCR&0X0FFF0000)>>16)+1)|temp;        //设置行起始和结束位置
      R% L" X; P! E5 N5 D7 n" R# G
  134.                 temp = (sy+height+(LTDC->BPCR&0X7FF))<<16;
    7 `* O6 W! Q5 l( @* o8 h
  135.                 LTDC_Layer2->WVPCR = (sy+(LTDC->BPCR&0X7FF)+1)|temp;                        //设置列起始和结束位置
    ( Y) l$ _) L7 |. @  h
  136.                 pixformat = LTDC_Layer2->PFCR&0X07;                                                                //得到颜色格式
      v" K2 L# l/ }0 B, F
  137.                 if(pixformat == 0)temp=4;                                                                                //ARGB8888,一个点4个字节
    * A1 m5 `/ J- [$ s
  138.                 else if(pixformat == 1)temp=3;                                                                        //RGB888,一个点3个字节
    ' d' E6 V& o' {* i1 @
  139.                 else if(pixformat == 5||pixformat==6)temp=1;                                        //L8/AL44,一个点1个字节9 ~) B- z1 V1 {6 J3 |4 u
  140.                 else temp = 2;                                                                                                        //其他格式,一个点2个字节3 u# v/ M. T* C" H! _
  141.                 LTDC_Layer2->CFBLR = (width*temp<<16)|(width*temp+3);                        //帧缓冲区长度设置(字节为单位)
    % w( R- a) ?6 L  }
  142.                 LTDC_Layer2->CFBLNR = height;                                                                        //帧缓冲区行数设置        0 [/ k5 S6 }9 J# l1 U8 J
  143.                 ' Y) ?2 F  x7 }! P
  144.                 //记录层窗口大小位置信息' `- E; z& B/ s" Y& C1 c) j1 o  f
  145.                 sg_LTDC_ConfigData.LayerConfig[1].sx = sx;               
    2 m0 D$ ?% g; z7 k& Q
  146.                 sg_LTDC_ConfigData.LayerConfig[1].sy = sy;        7 V; ]/ z) @0 s3 W4 m/ A
  147.                 sg_LTDC_ConfigData.LayerConfig[1].width = width;        
    , y& v0 l+ d1 r# t$ |
  148.                 sg_LTDC_ConfigData.LayerConfig[1].height = height;               
    7 d, x6 X$ X2 s: p- J6 b3 z
  149.         }# y7 V3 ^3 A9 T/ E) S1 v( W( u
  150. }5 F- F: `9 b& M3 u

  151. * p% G+ R) t7 Y8 F
  152. . v* u) Y5 q+ D! T( m

  153. # E1 t$ q8 h0 L: ?+ o6 L4 a
  154. /*************************************************************************************************************************7 P* W0 n" v! L8 X
  155. * 函数        :                        void LTDC_Init(void)
    ; o" m5 S3 U, v  D$ n8 H
  156. * 功能        :                        LTDC 接口初始化
    $ x! i+ q- |7 s0 \9 f/ R
  157. * 参数        :                        无
    9 n9 `' O  ]# R4 `
  158. * 返回        :                        无( M: s! [$ n) D6 @+ v5 n8 N
  159. * 依赖        :                        底层宏定义+ ~  ^4 m5 r4 x; P% B- B) p
  160. * 作者        :                        <a href="mailto:cp1300@139.com">cp1300@139.com</a>. H/ w6 b& U2 o
  161. * 时间        :                        2019-09-082 `) V) G( G$ Q! q9 u
  162. * 最后修改时间 :         2019-09-08
    + J! ?7 ^( y8 \" z
  163. * 说明        :                         用于初始化STM32F7 LTDC 接口
    ) G% {+ y  O  l# I
  164. *************************************************************************************************************************/  % @4 h* d; D9 [3 d! L
  165. void LTDC_Init(void)
    2 D0 X8 S  Z& N! h
  166. {
    . u* @! d. D+ g1 n8 H6 y* b8 f
  167.         u32 temp;; m& J5 b! q2 r9 @1 m4 c
  168.         8 G5 Q- k+ o# J( H, T
  169.         SYS_DeviceClockEnable(DEV_LTDC, TRUE);        //LTDC时钟使能1 q: U, [! `$ m
  170.         SYS_DeviceReset(DEV_LTDC);                                //STM32F7外设复位$ Q; A' d6 H4 }8 r: U  I+ z
  171.         SYS_DeviceClockEnable(DEV_GPIOE, TRUE);        //使能GPIOE时钟% x- S& M! q! ?9 b/ Y( Y" E
  172.         SYS_DeviceClockEnable(DEV_GPIOG, TRUE);        //使能GPIOG时钟9 c3 p: E2 ^! _* p5 H- N, a
  173.         SYS_DeviceClockEnable(DEV_GPIOJ, TRUE);        //使能GPIOJ时钟# F8 `+ Z$ I: k: m- s- n  z- Q* M
  174.         SYS_DeviceClockEnable(DEV_GPIOK, TRUE);        //使能GPIOK时钟
    3 X; z) M5 F& ?9 }1 M! P
  175.         SYS_DeviceClockEnable(DEV_GPIOI, TRUE);        //使能GPIOI时钟( q& `0 q0 C6 \  [+ Y
  176. . L. I( Z- @0 g) a' K1 `7 x
  177.         
      Z9 H) p0 ^" d6 [7 K9 N* J
  178.         //初始化IO3 p5 ]  r! G) U$ J1 K  p2 D0 o7 {$ s
  179.         SYS_GPIOx_Init(GPIOE, BIT4, AF_PP_OPU, SPEED_100M);                                                                                //PE40 F/ u6 z* P  t0 L' t; h4 U! R
  180.         SYS_GPIOx_Init(GPIOG, BIT12, AF_PP_OPU, SPEED_100M);                                                                        //PG12/ m; j2 u( [8 j; a( }, F8 x
  181.         SYS_GPIOx_Init(GPIOJ, 0Xffff&(~BIT12), AF_PP_OPU, SPEED_100M);                                                        //PJ0~11/13/14/15" t% j. d; @* r
  182.         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
  183.         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
  184.         * x& o* W- G8 j- d
  185.         SYS_GPIOx_SetAF(GPIOE, 4, AF14_LTDC);                //PE4,AF14        + U$ o) n" b+ e/ |
  186.          SYS_GPIOx_SetAF(GPIOG, 12, AF14_LTDC);                //PG12,AF14        
    8 w% `: p7 P* z0 }
  187.         SYS_GPIOx_SetAF(GPIOJ, 0, AF14_LTDC);                //PJ0,AF144 q; o0 P3 f5 A" Q5 o0 s8 Q5 B
  188.         SYS_GPIOx_SetAF(GPIOJ, 1, AF14_LTDC);                //PJ1,AF14  x6 a" w% G& ^( y
  189.         SYS_GPIOx_SetAF(GPIOJ, 2, AF14_LTDC);                //PJ2,AF14
    % y$ O" ]1 o9 z% ^7 ~& Q) x4 P
  190.         SYS_GPIOx_SetAF(GPIOJ, 3, AF14_LTDC);                //PJ3,AF14
    # [& C# l9 [& }8 B; z4 P4 t1 i' A5 c
  191.         SYS_GPIOx_SetAF(GPIOJ, 4, AF14_LTDC);                //PJ4,AF14' u& ^- a6 q: i  O- F% _) L
  192.         SYS_GPIOx_SetAF(GPIOJ, 5, AF14_LTDC);                //PJ5,AF145 T1 z* o! V8 M6 `" F
  193.         SYS_GPIOx_SetAF(GPIOJ, 6, AF14_LTDC);                //PJ6,AF14
    1 Z* ?# k* r& D( L# `. O, G! e
  194.         SYS_GPIOx_SetAF(GPIOJ, 7, AF14_LTDC);                //PJ7,AF144 ]- O) R  b7 x# R! d; T
  195.         SYS_GPIOx_SetAF(GPIOJ, 8, AF14_LTDC);                //PJ8,AF143 n! v4 J4 H+ n5 P8 i
  196.         SYS_GPIOx_SetAF(GPIOJ, 9, AF14_LTDC);                //PJ9,AF140 f+ z5 s( U: Q- Z/ s9 a
  197.         SYS_GPIOx_SetAF(GPIOJ, 10, AF14_LTDC);                //PJ10,AF140 [  A9 L2 t0 x& ]8 j7 {4 Y
  198.         SYS_GPIOx_SetAF(GPIOJ, 11, AF14_LTDC);                //PJ11,AF14
    5 W( C: E# S/ w$ w, e
  199.         SYS_GPIOx_SetAF(GPIOJ, 13, AF14_LTDC);                //PJ13,AF14
    2 N% q% t3 E0 `& h2 @
  200.         SYS_GPIOx_SetAF(GPIOJ, 14, AF14_LTDC);                //PJ14,AF14
    % E! V, q9 B  i6 ]  u$ l$ Y
  201.         SYS_GPIOx_SetAF(GPIOJ, 15, AF14_LTDC);                //PJ15,AF145 D. e: X, H! d& ?0 L& ^7 a
  202.         
    " G6 R: n3 ?0 o' {3 f" W. ~
  203.         SYS_GPIOx_SetAF(GPIOK, 0, AF14_LTDC);                //PK0,AF14$ v3 A" {6 O, C7 j! s7 U" g
  204.         SYS_GPIOx_SetAF(GPIOK, 1, AF14_LTDC);                //PK1,AF14! a; ?& |) H. ]6 t, e' w; \
  205.         SYS_GPIOx_SetAF(GPIOK, 2, AF14_LTDC);                //PK2,AF14
    / j7 ]4 }$ k$ b6 p
  206.         SYS_GPIOx_SetAF(GPIOK, 4, AF14_LTDC);                //PK4,AF14: R1 O: V0 u8 W6 M
  207.         SYS_GPIOx_SetAF(GPIOK, 5, AF14_LTDC);                //PK5,AF149 I  v' r( j# |( {  H9 o6 x
  208.         SYS_GPIOx_SetAF(GPIOK, 6, AF14_LTDC);                //PK6,AF144 L/ L' R4 E! z% R5 [$ L( x5 }1 Z
  209.         SYS_GPIOx_SetAF(GPIOK, 7, AF14_LTDC);                //PK7,AF14
    6 I/ _) p- c, Z2 r
  210.         
    8 S; Z2 ~: n5 o( A$ p0 V
  211.          SYS_GPIOx_SetAF(GPIOI, 9, AF14_LTDC);                //PI9,AF14
    , ]" v' g: j9 d) Z$ y/ H7 Y
  212.          SYS_GPIOx_SetAF(GPIOI, 10, AF14_LTDC);                //PI10,AF14 $ r0 N1 i  K  B' Y& f
  213.         SYS_GPIOx_SetAF(GPIOI, 14, AF14_LTDC);                //PI14,AF14
      k3 d+ ]% x: B; w0 C; M
  214.          SYS_GPIOx_SetAF(GPIOI, 15, AF14_LTDC);                //PI15,AF14 2 B- M3 q' z/ N5 f
  215.         
    ! O9 O" B4 D& x4 S: g
  216.         LTDC_ClockInit(DefaultLCD_Info.DCLK);                 //设置像素时钟  9Mhz
    ( J4 ]/ e0 w# P) k7 _; C
  217.         //设置LTDC 全局控制寄存器 (LTDC_GCR)6 k9 p  ?  q+ h' [2 c! H
  218.         temp = 0;$ f1 U4 N# O; Y! I) J$ C
  219.         temp |= (DefaultLCD_Info.HSPOL&0x01) << 31;        //水平同步极性4 p# l/ O% {" q5 g! u* @0 B! D
  220.         temp |= (DefaultLCD_Info.VSPOL&0x01) << 30;        //垂直同步极性+ m0 q. }8 T5 {4 p, d" L
  221.         temp |= (DefaultLCD_Info.DEPOL&0x01) << 29;        //数据使能极性
    - E3 W4 V/ B: B- i& U
  222.         temp |= (DefaultLCD_Info.PCPOL&0x01) << 28;        //像素时钟极性
    / ^2 R* S0 C( y# ~
  223.         LTDC->GCR = temp;
    1 W! Z/ M+ A) x# S
  224.         //LTDC 后沿配置寄存器 (LTDC_BPCR)3 ~# a! C( z) E' e7 }, B. N
  225.         temp = (DefaultLCD_Info.Tvw + DefaultLCD_Info.Tvbp - 1) << 0;        //这些位定义累加水平后沿宽度(水平同步像素加水平后沿像素减 1)。
    : V0 Q& d; |2 r+ n  Z
  226.         temp |= (DefaultLCD_Info.Thw + DefaultLCD_Info.Thbp - 1) << 16;        //这些位定义累加垂直后沿宽度(垂直同步行加垂直后沿行减 1)。8 t) {0 H# N8 a
  227.         LTDC->BPCR=temp;        - ^& d& z5 ^% g% W! i
  228.         0 w) X0 x4 I: `$ G: X
  229.         //LTDC 有效宽度配置寄存器 (LTDC_AWCR)1 Q# H' P7 z; E8 k- m
  230.         temp=(DefaultLCD_Info.Tvw+DefaultLCD_Info.Tvbp+DefaultLCD_Info.Height-1)<<0;        //累加有效高度=垂直脉宽+垂直后沿+垂直分辨率-1
    % G3 x6 @% E: f2 O
  231.         temp|=(DefaultLCD_Info.Thw+DefaultLCD_Info.Thbp+DefaultLCD_Info.Width-1)<<16;        //累加有效宽度=水平脉宽+水平后沿+水平分辨率-1
    ; |# l% \% E1 R! P& X
  232.         LTDC->AWCR=temp;        
    ; R4 n9 o5 `7 k. h. v+ x, C  m
  233.         //LTDC 总宽度配置寄存器 (LTDC_TWCR)* \# b5 y( z, L# S
  234.          temp=(DefaultLCD_Info.Tvw+DefaultLCD_Info.Tvbp+DefaultLCD_Info.Height+DefaultLCD_Info.Tvfp-1)<<0;        //总高度=垂直脉宽+垂直后沿+垂直分辨率+垂直前廊-16 U9 f9 p8 ~& K
  235.         temp|=(DefaultLCD_Info.Thw+DefaultLCD_Info.Thbp+DefaultLCD_Info.Width+DefaultLCD_Info.Thfp-1)<<16;        //总宽度=水平脉宽+水平后沿+水平分辨率+水平前廊-1
    & V4 _; O: P, O1 P' y6 `7 e
  236.         LTDC->TWCR=temp;                                4 }" }1 l4 ^4 j* J% Q% \

  237. , p7 U. b8 j) v5 W( {( B& V
  238.         //背景设置
    ) q: O! ?. Q1 @6 j  H$ N: ^2 R
  239.         LTDC->BCCR=0xffffff;                                //设置背景层颜色寄存器(RGB888格式)- {5 N4 W9 f2 T- H4 m
  240.         LTDC_Enable(TRUE);                                        //开启LTDC
    7 S- T- Q0 M; y/ c
  241.         //初始化层19 C* L% i) V0 U
  242.         LTDC_SetLayerConfig(0, 0, 0, LTDC_WIDTH, LTDC_HEIGHT, (u32)g_LTDC_BUFF_RGB888[0], 255);9 @9 g- R4 R; _% r8 b# F) ~
  243.         //初始化层2
    2 X1 k! `  {1 u& h
  244.         LTDC_SetLayerConfig(1, 0, 0, LTDC_WIDTH, LTDC_HEIGHT, (u32)g_LTDC_BUFF_RGB888[1], 255);. Z1 P! G# j: R
  245.         LTDC_Clear(0, 0xFF000000);                        //清屏层1-不透明的黑色
    , a4 W9 U" {5 B& u7 e
  246.         LTDC_Clear(1, 0x00000000);                        //清屏层2-透明的黑色
    3 S$ ?8 M% `# \7 s* d4 U1 W: z2 Q/ f
  247.         LTDC_LayerEnable(0, TRUE);                        //使能层16 D+ [, W6 V; S: ]( F% r
  248.         LTDC_LayerRefreshConfig();                        //LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)
    + J% j" @; `% o7 W4 P/ Q# z6 o
  249.         LCD_DispIoInit();                                        //初始化DISP引脚-启动显示
    5 K# N: S, Q1 U% K; i
  250. }! m- ]& x# h) S
  251. 9 ?; q1 p1 l4 M% l
  252. /*************************************************************************************************************************$ N+ ]( ^' O* a" H
  253. * 函数                        :        void LTDC_LayerRefreshConfig(void)
    + U5 {$ X, y. l) u  M
  254. * 功能                        :        LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)
    3 P) w3 E# t) g( R% p. D
  255. * 参数                        :        无
    8 C, ?  w4 n( @8 U
  256. * 返回                        :        无0 r, X+ [0 u4 c% W/ e0 h8 n; A
  257. * 依赖                        :        底层宏定义3 X# F3 K' S1 y( K: U+ t
  258. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    $ B% l1 z0 _7 K) ?4 D
  259. * 时间                        :        2019-10-295 Z$ E# v: l5 H2 a5 ]- N$ n! T
  260. * 最后修改时间         :         2019-10-297 D0 M+ Q& A' f% D% n
  261. * 说明                        :        修改层配置后必须重新加载,否则不会生效
    ' U/ C9 N- t0 K2 }
  262. *************************************************************************************************************************/
    4 h# L% ?2 z3 e! U% N, @- o
  263. void LTDC_LayerRefreshConfig(void)
    7 Q# q! W% R* f: C3 M3 E6 \( w' x( y; q
  264. {* I$ c- X) X( y; y
  265.         LTDC->SRCR|=1<<0;                                                        //重新加载配置-必须重新加载,否则上面的层不会更新,折腾好久才发现,叫啥影子寄存器重载,也不说清楚
    # Q# B5 a9 u0 L- ~1 [
  266. }
    - \; L! B9 ~: i, d% B

  267. ! Q+ J, `7 g2 o# X+ [
  268. /*************************************************************************************************************************4 N  Y: M6 K* F
  269. * 函数                        :        void LTDC_Enable(bool Enable)
    . @" W/ A: S; o' r% V) v5 l7 C
  270. * 功能                        :        LTDC使能设置
    9 ]$ v9 K4 ~) ]! K. B4 z. _1 H3 G. Z
  271. * 参数                        :        Enable:TRUE:使能;FALSE:失能
    " s' v. j; `- x! F& R6 h
  272. * 返回                        :        无
    * T+ D9 N* ]7 C% ]
  273. * 依赖                        :        底层宏定义# t$ r4 S5 v1 j) J; z' u& n
  274. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>% L9 T# s0 u% l* W
  275. * 时间                        :        2019-10-29. y9 \) }/ Z3 [4 b( S
  276. * 最后修改时间         :         2019-10-29
    8 {' w. q/ b8 |8 ?- X
  277. * 说明                        :        ( X( @7 f/ B  g9 N! \# }
  278. *************************************************************************************************************************/  X  D# z  ]2 m7 D$ y
  279. void LTDC_Enable(bool Enable)" r4 e& Q3 ?  V/ H7 m$ g) F
  280. {) i% L2 ?; A9 e# K
  281.         if(Enable). s1 H9 v  K2 G3 v" x' F- t" k. I
  282.         {6 A& r9 r) k, Z
  283.                 LTDC->GCR |= BIT0;                                        //打开LTDC
    + B4 }. f" Y" e7 v
  284.         }6 d6 p, u% ?! W/ O0 I2 [' @. _
  285.         else0 K. Y) t# e* e' H7 W, Y
  286.         {8 c+ d8 _$ n1 d
  287.                 LTDC->GCR &= ~BIT0;                                        //关闭LTDC0 P1 E* z% O" y6 c0 N
  288.         }
    ( R: g( x+ i1 \4 }
  289. }4 H: ~- O; D2 G4 D5 U

  290. 8 J# |/ c; f; T7 N
  291. /*************************************************************************************************************************
    : A. g" f: b7 y; s# L
  292. * 函数                        :        void LTDC_LayerEnable(u8 LayerIndex, bool Enable)
      y- K* a( R6 D/ ]
  293. * 功能                        :        LTDC 层使能设置
    ( a& m9 l) s; k6 x: V# f
  294. * 参数                        :        LayerIndex:层选择0-1;Enable:TRUE:使能;FALSE:失能0 }% e' Q' i" C; G( D5 |, C/ D/ k
  295. * 返回                        :        无
    - N- D  f, \( K* X, V/ K
  296. * 依赖                        :        底层宏定义  }- h7 I4 c) V( }$ Y$ A8 W( y
  297. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    * x! ~0 u. w( X$ v! I* a( N
  298. * 时间                        :        2019-10-29. D2 L# c/ c# t+ A) ]) L$ L
  299. * 最后修改时间         :         2019-10-292 A, _; P( l+ B% ~1 H
  300. * 说明                        :        6 o5 }( C  G7 M2 i) b6 b
  301. *************************************************************************************************************************/( Y% ~- z  B$ Y0 U( A  m5 T4 O
  302. void LTDC_LayerEnable(u8 LayerIndex, bool Enable)0 k2 A( n1 r6 `  o( r9 Q
  303. {
    8 `& z- r# }" ~6 b% w4 B  K
  304.         if(Enable)
    : ~9 n3 W. r& f  \! U
  305.         {
    $ @6 ]  h; i1 L  E+ O2 w8 y
  306.                 if(LayerIndex == 0)                                        //层1. ^1 o, g5 G8 W+ v  V
  307.                 {4 z1 h' P' P2 Q; @. D# l, i4 e# a
  308.                         LTDC_Layer1->CR |= BIT0;                //使能层1
    / W5 ^) E7 b! k7 V2 r6 ~
  309.                 }! N9 O5 l$ H3 H
  310.                 else& s6 H  |  S$ y! \
  311.                 {
    ; w0 r' ?) \6 a9 w$ C4 g
  312.                         LTDC_Layer2->CR |= BIT0;                //使能层2
    , p  t$ O+ D4 @# L. R! d" v
  313.                 }
    * m+ R6 ~7 M; ^3 c2 T8 m
  314.         }
    ) r+ d5 L, Y& P0 D# P8 I
  315.         else) R' ^+ ~3 S; Z$ |! q+ k. ~
  316.         {
    ) Y8 P2 `. g6 u
  317.                 if(LayerIndex == 0)                                        //层1
    : P' ^- m# X, l
  318.                 {0 L+ O0 A+ y' A( O, y9 F  ~7 M, D
  319.                         LTDC_Layer1->CR &= ~BIT0;                //失能层1" f$ k, d. g7 w3 |8 x( ?# `
  320.                 }
    ' \+ C3 f. q; ~  r8 u
  321.                 else
    6 d. O% [4 j# t/ e3 y% t; ^
  322.                 {
    . i! Z2 \- u  x9 C7 f0 {
  323.                         LTDC_Layer2->CR &= ~BIT0;                //失能层2
    ; P' R- p- @0 Q: D4 @
  324.                 }
    , l( W* Z1 o$ w! ]0 e
  325.         }
    ( p; M! E( K  G$ E1 d, f: s7 Q
  326. }: |, u  {. }: g$ A

  327. % G; G; x3 k: P9 s
  328. 5 r! H) k' }/ A+ b8 c

  329. ; U7 B$ N) n# b4 t3 k

  330. $ b$ X; U( \+ @' J8 f( L( L$ \
  331. /*************************************************************************************************************************0 z5 h  X3 W' ~% @7 n% e4 {
  332. * 函数                        :        bool LTDC_ClockInit(u16 ClockFreq)                        
    , f" j- e! v6 m
  333. * 功能                        :        STM32F7 LTDC时钟初始化( [1 K- P6 L& i) w& V% [' y7 H
  334. * 参数                        :        ClockFreq:时钟频率,2-168MHZ8 k& a) B+ R1 T  q- W0 L
  335. * 返回                        :        是否设置成功& Z: c, Y1 n/ t5 t/ N7 y3 j) L4 u6 N
  336. * 依赖                        :        底层宏定义
    ! E. @; x/ C3 u# o
  337. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>' C# H) [! m2 G& U+ A# v7 }' C
  338. * 时间                        :        2019-10-28! D% T3 r" r8 d% x
  339. * 最后修改时间         :         2019-10-283 H- v0 W( b1 R, g
  340. * 说明                        :        输入时钟频率在系统主时钟初始化之后就会设置为1MHz,通过设置SAI PLL实现LTDC所需频率,VCO频率范围:49~432
    * G* A5 S$ K# ^$ ?8 o. z
  341. *************************************************************************************************************************/( i9 Q0 E8 j$ E8 z* x% X. ?6 U
  342. bool LTDC_ClockInit(u16 ClockFreq)) p; s! k8 @" L# R
  343. {8 _0 W5 m+ s% e) @. Y6 n
  344.         u32 TimeOut = 0;
    ' g  h4 P) l; v- w1 q( P; \
  345.         u32 VCO;9 [; o. s6 ]! L) Y) X, ?+ R
  346.         u32 PLLSAIR;                //PLLSAICFGR[30:28]
    6 y' {7 m4 G% _) Z  r
  347.         u32 PLLSAIDIVR;                //DCKCFGR1[17:16], y. p; D# |. H5 t. r
  348.         u32 temp;
    8 H, j/ ~- Y9 N
  349.         
    ; n. s/ H$ l* z  u% \' |2 t' D
  350.         if(ClockFreq < 1)ClockFreq = 1;+ V# R/ I% U& h8 d  S) C
  351.         if(ClockFreq > 100) ClockFreq = 100;
    1 ]/ {/ k8 X; }
  352.         
    , T! v: a$ X9 I3 v+ O
  353.         RCC->CR &= ~(1<<28);                                                //关闭SAI时钟 3 [1 C7 i8 O+ o! T  f8 K- v
  354.         TimeOut = 0;
    " P5 m+ _; Q& x# w" P8 i# H" O$ t2 U! m
  355.         while(RCC->CR&(1<<29))                                                //等待关闭成功3 i6 v8 U3 s% G4 m/ C% M
  356.         {
    . K* @/ m4 o8 l3 ?* ~2 G
  357.                 nop;" w8 f4 P0 K  C" Z/ [0 H6 _
  358.                 TimeOut ++;
    - N6 A. m7 ?" s- b- J$ o
  359.                 if(TimeOut > 0xFFFF) return FALSE;                //关闭超时
    * y" a4 R; p6 f% @+ |
  360.         }2 V7 H5 o" Z. v( ]( i
  361.         //计算分频与VCO频率,通过PLLSAICFGR[30:28]可以设置2-7分频
    6 V! {: q* t9 c2 A3 P
  362.         //通过PLLSAICFGR[17:16]可以设置00:2 01:4 10:8 11:16分频
    # T( p# E: e- A
  363.         //通过PLLSAICFGR[14:6]可以设置为49-432MHz的VCO频率6 t/ k- O' z8 f: \" d' O1 Y. _; c
  364.         if(ClockFreq <= 6)" o7 n& N5 y0 O- I( B
  365.         {( W; u( J6 v5 c6 b
  366.                 PLLSAIR = 4;        //4分频
    ! k. w; i$ f% g/ R! a! u0 O
  367.                 PLLSAIDIVR = 3;        //16分频
    4 x1 l1 \* D8 z! M; u. ?6 P
  368.                 VCO = ClockFreq * PLLSAIR * 16;                        //VCO范围:64-384;0 H) ]1 L7 G, R" {9 m3 E
  369.         }6 O# }! }9 T0 @$ {, H! k
  370.         else if(ClockFreq <= 13)3 `: R  m) F) j! \
  371.         {% A1 p2 t, ~5 D5 a- l7 d3 [6 T
  372.                 PLLSAIR = 4;        //4分频
    8 W  x  l6 j. Z
  373.                 PLLSAIDIVR = 2;        //8分频! `3 k6 |8 ^' R; o: s$ l9 R
  374.                 VCO = ClockFreq * PLLSAIR * 8;                        //VCO范围:224-416;
    , D/ _/ B( Z# x1 O
  375.         }
    + [; q& K) E5 y  P8 L2 ^$ J. r1 M
  376.         else if(ClockFreq <= 26)
    ' z3 L5 L9 _! [1 A
  377.         {
    ! y" C+ Y9 N1 w6 {; Y( _
  378.                 PLLSAIR = 2;        //2分频$ p6 t+ A; e- o/ U( a, z
  379.                 PLLSAIDIVR = 2;        //8分频
    ' _/ c! E3 N( C3 c% x9 L  h
  380.                 VCO = ClockFreq * PLLSAIR * 8;                        //VCO范围:224-416;
    ' J4 t6 S* T8 S3 \
  381.         }- e" k5 ?% M; q( w5 g+ z
  382.         else if(ClockFreq <= 52)0 k0 S! k0 t- J( Y5 ~. M
  383.         {3 g( e# c$ j$ [1 O% x2 h* v4 w
  384.                 PLLSAIR = 2;        //2分频
      d/ e5 f1 }# {5 Q3 O2 I/ j
  385.                 PLLSAIDIVR = 1;        //4分频
    . C# N% r3 A5 s7 ~4 I8 x
  386.                 VCO = ClockFreq * PLLSAIR * 4;                        //VCO范围:216-416;
    ) ?- {$ L! w9 w. ]
  387.         }
    ) W+ a. U# a1 L' I* A* v" k2 ~
  388.         else if(ClockFreq <= 104)
    ) c6 F, M! `' H  \! e% T
  389.         {9 x6 \' S9 j7 C
  390.                 PLLSAIR = 2;        //2分频& J* ~8 o! v  [1 _5 k- s! t
  391.                 PLLSAIDIVR = 0;        //2分频# H: o* T( h* B
  392.                 VCO = ClockFreq * PLLSAIR * 2;                        //VCO范围:212-416;
    9 g% o" j- E' u5 w) `- d  `
  393.         }* a. C* t2 o; r
  394.         //设置PLLSAICFGR
    ! S% G- n& x9 I6 G/ p, p" f+ @
  395.         temp = RCC->PLLSAICFGR;' ^; V! T5 M# r2 E/ d- G
  396.         temp &= ~((3<<28) | (0x1FF<<6));                        //清除之前的设置
    3 c/ ^3 o! S! R6 n
  397.         temp |= PLLSAIR << 28;                                                //设置分频PLLSAICFGR[30:28]# F  `6 h2 }2 B4 w% g
  398.         temp |= VCO << 6;                                                        //设置VCO1 |7 s2 q: _  g& S/ x2 r! z
  399.         RCC->PLLSAICFGR = temp;2 F0 ^8 S5 R0 s! R/ E
  400.         //设置DCKCFGR1. a6 m8 ?$ G8 g+ S0 m& {
  401.         temp = RCC->DCKCFGR1;
    ; @  z. W4 A3 s% b8 w1 ~
  402.         temp &= ~(3<<16);                                                        //清除之前的设置
    % s' A( g) i3 M. Q0 a. f
  403.         temp |= PLLSAIDIVR << 16;                                        //设置分频DCKCFGR1[17:16]- O6 `, V- K$ X) d0 i
  404.         RCC->DCKCFGR1 = temp;
    % _$ M- ]+ l$ G8 z
  405.         //启动时钟
    ) D  T+ X% B4 G  ~
  406.         RCC->CR |= 1<<28;                                                        //启动SAI时钟# x& Z/ u# r) {! u) b# d0 n
  407.         TimeOut = 0;4 `( P/ _, b% i. A
  408.         while((RCC->CR&(1<<29)) == 0)                                //等待开启成功
    % J/ a- c, W1 L- m. u
  409.         {, \4 D9 N: F  A% P, l
  410.                 nop;
    8 ?" q  |4 k* L* t) o9 {$ O! \  T
  411.                 TimeOut ++;  I( D3 N3 I: D4 s6 h. m
  412.                 if(TimeOut > 0xFFFF) return FALSE;                //开启超时4 x& r5 V- `* _5 K4 \7 _8 i8 L
  413.         }! R; R+ ?+ V2 l* j/ K+ B! Z
  414.         
    1 }0 D; g+ _' U& d$ f
  415.         return TRUE;) e# M0 q/ }. s: E. a6 l
  416. }$ }& P" D# T* O+ I5 a

  417. + D( w7 ^- ]# J: I/ S
  418. # l4 V( d& u8 \; D/ y7 j, ]! z
  419. /*************************************************************************************************************************" N" ]' Z. s6 b0 g: z8 `, b( s! Y5 \
  420. * 函数                        :        void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color)        
    " e6 o3 T0 I, T
  421. * 功能                        :        矩形填充(使用DMA2D)
    2 Q1 c2 a6 S: d" D% s
  422. * 参数                        :        LayerIndex:层选择0-1;sx,sy:开始坐标;ex,ey:结束坐标,color:需要填充的颜色8 C/ H, v. ~) u3 F
  423. * 返回                        :        无# K+ |3 F" H1 ~3 l$ s
  424. * 依赖                        :        底层宏定义. K! \8 z6 u" c" O- I
  425. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    ' [1 v  a+ M3 _5 V2 t, Y4 o
  426. * 时间                        :        2019-10-30
    - k" Z+ {. o0 s8 o
  427. * 最后修改时间         :         2019-10-30) G( f' s, k$ r- X
  428. * 说明                        :        采用DMA2D实现( K' [/ J. u( N9 Q" m7 E
  429. *************************************************************************************************************************/
    7 X7 J: O1 Y( @) r6 Z* ~4 s: b
  430. void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color). @  y+ x6 Z' N9 W4 V4 d. [
  431. {
    ( W0 k+ _" g' I. m1 A" @: }
  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进行单色填充
    ! X4 \# N% |& L8 z
  433.         DMA2D_WaitTransferComplete(500);                                                                                                                                                                                                                                //等待DMA2D传输完成
    / I7 S/ f# e; O& [( }6 B
  434. }
    ; d4 k: f3 E! a: U( g( _* U

  435. : G! J; y" [, f$ U
  436. 1 h! d: Y! G3 K2 ^: l* W4 E
  437. /*************************************************************************************************************************; Z  G( y* Y! c8 L8 G) Q# P$ V
  438. * 函数                        :        void LTDC_Clear(u8 LayerIndex,u32 color): g! r+ t8 y$ ?/ }
  439. * 功能                        :        清屏(使用DMA2D)
      `' R' A' m$ B: o% _
  440. * 参数                        :        LayerIndex:层选择0-1;color:需要填充的颜色
    ! ]  L) R7 {$ G" Z: ^
  441. * 返回                        :        无
    ; t1 k+ E, K2 f' x
  442. * 依赖                        :        底层宏定义: p: J) Q' O* e
  443. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    : X% U4 `6 i9 Q  F3 v* u
  444. * 时间                        :        2019-10-30) W, L$ i" L* k0 B. t
  445. * 最后修改时间         :         2019-10-303 p& L% Z5 r5 ]9 }, ]7 D" j3 r
  446. * 说明                        :        采用DMA2D实现- {6 I' s5 F7 M8 v" ]
  447. *************************************************************************************************************************/7 r; w5 w0 p1 k$ O" r
  448. void LTDC_Clear(u8 LayerIndex,u32 color)
    ) a* w& L, P# `2 H5 `' S
  449. {
    & u* S% N3 X5 ?: r# h/ f! b7 |1 e
  450.         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
  451.         SYS_DelayMS(5);) x3 F1 r- n) t, Q
  452.         DMA2D_WaitTransferComplete(500);                                                                                                                                                                                                                                //等待DMA2D传输完成2 F) ~* Q% R2 l' i, F0 h% y2 ^& h
  453. }
    $ C5 p8 {+ J6 M. A6 ?

  454. / v% |( E% N0 ~8 `- c* B

  455. / ~& ]- b+ w6 ?
  456. /*************************************************************************************************************************& p' d' x; C* J) |* B+ C+ i
  457. * 函数                        :        void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr)
    7 D8 `  e0 [3 W- i% e1 e
  458. * 功能                        :        矩形图像填充(相同坐标范围传输,要求源图像与目标显示器分辨率一致,使用DMA2D)5 S( Y9 m+ j" V$ m
  459. * 参数                        :        LayerIndex:层选择0-1;sx,sy:开始坐标;ex,ey:结束坐标,ImageAddr:需要填充的图像地址8 E0 ~1 S/ R* |2 p3 `9 F
  460. * 返回                        :        无
    3 Z: F" N! Z: Z# l% {: n/ d. y
  461. * 依赖                        :        底层宏定义+ u% G! X% {5 J6 N4 y! Z
  462. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>* }! S* `( @- B+ C
  463. * 时间                        :        2019-10-30+ @+ T6 u, T) Z
  464. * 最后修改时间         :         2019-10-30( e( G$ h8 k3 m9 s; @9 F
  465. * 说明                        :        采用DMA2D实现,将源图像指定位置传输到现存,要求源图像与显存大小一致
    9 b: K4 l" A% `# L
  466. *************************************************************************************************************************/+ l- Z# t# T! ]+ H7 P8 Q6 e
  467. void LTDC_FillImageSamePosi(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 ImageAddr)
    % d$ w$ T' }. C6 ^
  468. {
    ( c( \/ ?. Q& o: j
  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进行矩形图形填充
    + Y) b! ~& V: o) f* z
  470.         DMA2D_WaitTransferComplete(500);& T; O- k2 X9 M, M5 v
  471. }
复制代码
  1. /*************************************************************************************************************
      t7 L# j4 x( ^$ _
  2. * 文件名                :        stm32f7_ltdc.h
    2 |( S. f4 T% J( U, f  W1 F
  3. * 功能                        :        STM32F7 外部RGB LCD驱动
    - H' @" y+ f' W; F# A* W( x/ A
  4. * 作者                        :        <a href="mailto:cp1300@139.com">cp1300@139.com</a>
    . v" T+ {  N* c' U
  5. * 创建时间                :        2019-09-12$ X0 }, z: {7 e
  6. * 最后修改时间        :        2019-09-12% j1 S6 P" F8 O4 [$ J9 z. I3 o
  7. * 详细:        . q; D4 y: V/ C2 y, l
  8. *************************************************************************************************************/               
    " ~, }+ O; h% r; b
  9. #ifndef __STM32F7_LTDC_H_7 {1 A+ a8 b( J( l( m8 p
  10. #define        __STM32F7_LTDC_H_           
    ' H: ?  s9 e3 r" s7 R* n" J1 M
  11. #include "system.h"
    ; ~9 A: Y8 z+ J7 V: _' `$ O2 V
  12. #include "DMA2D.h"! K4 w1 P1 q. k9 x( D7 a

  13. 2 c- ?& x- m  E1 ?6 B
  14. #define LTDC_WIDTH                4807 N5 k  ?/ o* h9 @
  15. #define LTDC_HEIGHT                272, Z( F# N% F- X- v  L- X& H

  16. # I* l  {" W8 N) h& `

  17. . d$ b) l( d* d$ l7 q4 C+ z. ?
  18. extern u32 g_LTDC_BUFF_RGB888[2][LTDC_HEIGHT][LTDC_WIDTH];& S. @1 x9 f7 |. Q5 `
  19. : A' t+ M7 J( R5 \& i
  20. //像素格式定义! f7 i1 f" m7 }: j4 d# l7 Y) h+ f0 c$ J
  21. typedef enum
    0 Z7 ~/ p. k* q; I. H1 d# \
  22. {
    7 n5 ?) ~6 v7 M, {
  23.         LTDC_ARGB8888         = 0,
      i$ r5 g# `! o3 R' J, c
  24.         LTDC_RGB888         = 1,& K0 w: E7 \5 J, L5 J
  25.         LTDC_RGB565         = 2,
    6 m% Z) h2 S- ~' s1 C1 L9 B- f- I
  26.         /*LTDC_ARGB1555         = 3,
    8 Z$ P! x" c; E. R, [
  27.         LTDC_ARGB4444         = 4,, B& V( T: X; O1 u- \
  28.         LTDC_L8                 = 5,        //8 位 Luminance
    # w+ V  {7 f9 a
  29.         LTDC_AL44                 = 6,        //4 位 Alpha,4 位 Luminance
    8 o3 a6 ]: [+ B+ g
  30.         LTDC_AL88                 = 7,        //8 位 Alpha,8 位 Luminance*/* S: [. P/ `+ N* C
  31. }LTDC_PixelFormat;
    ; P/ G' y9 b0 Q$ ?: A  t0 u
  32. #define LTDC_PIXEL_FORMAT                LTDC_ARGB8888                //选择ARGB8888格式
    6 S* k) _* b$ m( l& t' D

  33. . k% R2 [1 W  u8 d, V# t- {

  34. 6 W  J, x& S* X. [. C" |
  35. 9 s2 L5 x! g0 Y: w. J' O. X

  36. % O/ i3 w: Y$ R! F- J" ?+ {3 S: H
  37. //画点函数32bit ARGB8888格式  o5 E" W* Y0 y. K5 c1 N# H6 D1 L4 @, s
  38. __inline void LTDC_DrawPoint(u8 LayerIndex, u16 Xpos,u16 Ypos,u32 ARGB8888_Color)# R8 v6 M0 ~4 z. F* M4 m! [- t4 e
  39. {5 i6 T! t- V8 G7 t' X. P
  40.         g_LTDC_BUFF_RGB888[LayerIndex][Ypos][Xpos] = ARGB8888_Color;
    ( \* E. K- C7 ~# s+ [4 M+ r
  41. }
    6 K6 r/ T' F; |% k3 X9 o- @& z

  42. 2 g" L* K" y" q- K# n$ O; {+ [
  43. //初始化DISP引脚
    6 O$ v" y1 @- R3 b( {# ?# m
  44. __inline void LCD_DispIoInit(void)
    & F- @* V; Z) K
  45. {
    6 Q" I% u  V2 w0 c
  46.         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
  47.         PIout(12) = 1;                                                                                                                                                                        //DISP = H  2019-10-16:一直忽略将此引脚置为高电平,调试走了很多弯路
    9 b' Q' O; Y: W# `
  48. }3 Q0 ~! |/ l2 z6 R3 S% H
  49. 0 J6 M3 K: t* [. Z5 F% \
  50. void LTDC_Enable(bool Enable);                                                                                                                                                //LTDC使能设置$ U* C$ ]1 Y, r
  51. void LTDC_Init(void);                                                                                                                                                                //LTDC 接口初始化
    ! n( D+ K( T6 U
  52. 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 _
  53. void LTDC_LayerEnable(u8 LayerIndex, bool Enable);                                                                                                        //LTDC 层使能设置; S# w- M- }: k/ I9 [7 N
  54. void LTDC_LayerRefreshConfig(void);                                                                                                                                        //LTDC 刷新层配置(修改层配置后必须重新加载,否则不会生效)4 _+ \) J& A/ w& L1 s+ p, i

  55. + b3 }1 F$ q5 z. Y: a6 a. v% H
  56. //图形相关API5 ]  }1 n7 h2 m2 D
  57. void LTDC_DrawPoint(u8 LayerIndex, u16 Xpos,u16 Ypos,u32 ARGB8888_Color);                                                        //画点函数32bit ARGB8888格式
    . K% J2 n# A$ }0 o/ v6 }& j  E
  58. void LTDC_Fill(u8 LayerIndex,u16 sx, u16 sy,u16 ex,u16 ey,u32 color);                                                                //矩形填充(使用DMA2D)
    ( b- k1 f( |; M
  59. void LTDC_Clear(u8 LayerIndex,u32 color);                                                                                                                        //清屏(使用DMA2D)
    3 X8 q! z& h) a$ T! R/ K

  60. ! `9 ?+ K& e: L% F
  61. 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
收藏 评论0 发布时间:2021-12-14 10:49

举报

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