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

STM32L4使用SPI驱动TFTLCD

[复制链接]
STMCU小助手 发布时间:2022-8-27 14:53
在上新建工程的基础上添加使用SPI功能(新建工程见STM32使用LL库建立工程)
8 p8 C) N0 o! J; o6 h2 }( c7 _0 L! R- d3 H2 v* @. a
一、CubeMX的配置
  ?5 J0 P# ?# d, N1、非SPI的LCD控制IO口的配置
/ `$ z6 `1 T- l) \4 b' ?  Z查看原理图可以看到,有5个引脚接在了MCU上,其中有两个SPI引脚,三个LCD控制引脚) v( v5 B( @1 J- E! R- j- i
2020011015195320.png
, V" w  i! p4 \8 @/ w2 b& A7 ~' B8 C7 Y
其引脚对照表如下,所以我们先将PC6、PC7、PB15配置为通用IO推挽输出6 w5 A3 l, b4 i# r/ b8 b
+ s. q" _4 [0 }( d
20200110153020937.png
2 I4 ~; r+ z. K! \! n. G, s( [! }6 A# u1 S2 b0 I( X& ]7 M, _
20200110153726935.png
' }# q# h5 H* U1 B
  [" v$ q, }* S% f* v2、SPI的的配置
8 R4 C! ^; M4 A, `! p- r2 rMCU只需要通过SPI向LCD控制器发送命令/数据即可,所以只使用 SPI2 的 SCK 和 MOSI 引脚,将SPI2配置为主设备只发送模式,接下来开始配置SPI2接口:' s5 T- C7 W+ U* n# n4 ^
' v( l& ]* p! u: D! y
首先将SPI2配置为只发送主设备模式
0 R. D3 m) M8 R5 I; b; ?3 Z8 U, |2 z7 p. ?: g. g; W5 W
20200110154317851.png 4 W% _6 g' d" J

! w' h1 _6 A+ J( l1 f8 V- R! h可以看到,SPI2_SCK引脚默认为PB10,我们需要将其修改为PB134 u9 ?' y9 i7 l) |& q/ ^: D. K, {+ ^
' O4 X; F/ Q% L% h& n3 ~: }% N8 _" j  O0 Y
20200110155915102.png 9 U9 q9 _6 i7 v' b
* U9 h# |. w: S/ ~0 r- i7 c
然后对SPI的参数进行配置
8 c8 ~' F$ v% \! O$ G7 ~
3 I- N$ ?* b0 U5 U 2020011016032433.png
( G3 U0 D( v% X4 g/ [5 d. K# C# {; M; C- J% P7 f7 c% h
然后重要的是工程设置里,将HAL改成LL# G; }- n. q# x$ s9 U) A. {1 U* f
, A- s+ Y* c' Q0 ?4 z) f( Z' a1 u% @
20200110160609448.png
# l2 _9 P1 M) d
" @+ g7 f# L+ d* V* j9 q5 x然后便可以生成代码
  W; T! @1 D! V" E4 L9 q- f2 A; m5 [( y
20200110160627106.png : F+ e+ k+ |7 @) h

6 Y% Y0 T* a4 l4 m9 R3 M, i二、用户代码修改7 @! m; A* N( d1 N6 J
将SPI初始化代码修改为如下,放入新建的spi.c文件% E1 A6 s3 @' h4 a4 }

9 m: R- a0 x9 H! V
  1. //SPI2初始化代码,配置成主设备只发送模式$ y% |4 Q& I3 D) i
  2. void SPI2_Init(void)  c+ w/ v8 ~: E2 n; [
  3. {/ F0 m+ U) d6 R  Y9 u
  4.         LL_SPI_InitTypeDef SPI_InitStruct;7 r; r1 ^- M1 A! N# W3 u
  5.         LL_GPIO_InitTypeDef GPIO_InitStruct;
    / h, C8 {  [3 V

  6. 9 ^- ]3 B$ j0 e) `
  7.         LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);//使能GPIOB时钟
    . p9 |" M% Y) l
  8.         LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);//使能GPIOC时钟% `- x9 d2 k9 N2 n) O& |
  9.         LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);        //使能SPI2时钟
    % F5 x; ^( o' g) I  J* v
  10. * n  ~( h  f# h. t: T8 m
  11.         // **LCD控制GPIO配置 LCD_PWR->PB15        LCD_WR_RS PC6         LCD_RST->PC7        */
    + ~9 \1 r$ V' a* E2 p# ~
  12.         GPIO_InitStruct.Pin = LL_GPIO_PIN_15;
    1 V& P' ]) m9 d
  13.         GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;5 a. b7 a# S# g8 G( {
  14.         GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
    2 e* B  l; U, s6 u3 @
  15.         GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;' B8 R+ _1 p( r4 g7 n, _5 w) s
  16.         GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
    : S9 e0 T: H* d. U
  17.         LL_GPIO_Init(GPIOB, &GPIO_InitStruct);' S: F: a) h( Y1 d- d0 Q! e
  18.         LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_15);8 X! N# T1 ~& Y9 |& o% g6 E

  19.   \! U* Y0 b8 K- S3 f
  20.         GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;: D0 C' ?( ^" B
  21.         LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    7 K6 k4 L+ o( h
  22.         LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_6|LL_GPIO_PIN_7);  v4 a/ [0 f4 ?# O+ j
  23.         
    8 t; U% g" t4 V, x( Y9 R1 v. k
  24.         // **SPI2 GPIO Configuration        PC3-> SPI2_MOSI                PB13-> SPI2_SCK */3 U5 o8 @* [4 U* @0 A
  25.         GPIO_InitStruct.Pin = LL_GPIO_PIN_13;  \4 ~/ w* A! U: ]3 O
  26.         GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;* K! n! G  V% i5 o
  27.         GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;  H7 }$ J- z$ j. r, K  w
  28.         GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;1 {/ H+ v' ]% k7 J* g
  29.         GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;- F9 c9 j% b7 {
  30.         GPIO_InitStruct.Alternate = LL_GPIO_AF_5;& h: [! `6 w5 e8 I: O
  31.         LL_GPIO_Init(GPIOB, &GPIO_InitStruct);  w, ?( w7 z+ z0 l+ W7 T
  32.         
    . D: u2 a% {* ^4 @- S* Q$ f. d
  33.         GPIO_InitStruct.Pin = LL_GPIO_PIN_3;2 M  }6 b( H: |* `) Q/ @
  34.         LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
      ~* h! T- k9 C) w- y8 T& v

  35. 1 {, T8 M) Z1 i6 j! v3 `' s
  36.         /* SPI2 parameter configuration*/
    ; w  ]: j/ o( z* ]1 h
  37.         SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;        //全双工/ x' H" k" l, O2 S( _
  38.         SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;                                //主设备模式
      g* N1 O6 O* U; L( D" a
  39.         SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;                //8位数据宽度0 R8 I& A: h" T7 |* O, X
  40.         SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;        //串行同步时钟的空闲状态为高电平
    0 O- @, Z  V' j
  41.         SPI_InitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;                        //串行同步时钟的第二个跳变沿数据被采样
    $ F9 }9 S. [, g% G/ n1 s
  42.         SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;                                        //NSS信号由软件(使用SSI位)管理:内部NSS信号由SSI位控制! @& V/ ?8 H! t7 {: I  m
  43.         SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;//定义波特率预分频的值:波特率预分频值为256* `/ e" P4 P: v: }" x2 }. U
  44.         SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;                                //数据传输从MSB位开始
    ( D+ m! u4 Y, [) y4 t+ i
  45.         SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
    7 c! j% r, U: C5 L$ g3 y
  46.         SPI_InitStruct.CRCPoly = 7;                                                                //CRC值计算的多项式" l  I, D8 v$ Q: G( W4 K- E
  47.         LL_SPI_Init(SPI2, &SPI_InitStruct);
    3 ?% G7 K: }$ l' ]9 S

  48. 4 n; y3 U* [9 K8 j6 G
  49.         LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);                //SPI帧格式 为 SPI Motorola模式
    4 k; V0 Z, J& G* \+ a9 Z
  50.         LL_SPI_DisableNSSPulseMgt(SPI2);                                                //关闭 NSS脉冲模式. U! w( ]% s% V, k" M
  51. 0 y6 ?. W6 u7 ~2 I. M
  52.         LL_SPI_Enable(SPI2);                //使能SPI2
    4 L, J8 w$ `1 I9 v
  53. }& Q# c% a  f7 B) \5 w% ^! u0 w
  54.   S: ]7 Y$ z  H- ~
复制代码

7 e1 b! U+ c4 U! B! G: I; Y然后编写SPI2_WriteByte(u8 *TxData,u16 size)函数
1 N, J3 x# w3 _3 J9 O
) t; x+ S: m; F# ?3 C) ~& V4 g5 S( k
  1. /**7 D; F2 A& I4 t6 I' D: V  Q- o- R
  2. * @brief        SPI3 写入一个字节& g4 y( M0 D6 w5 [. S; V) A9 M, V
  3. * @param   TxData        要写入的字节  b0 S; n& M$ n, l- p  }% w
  4. * @param   size        写入字节大小
    . g4 c. w- Z& d; T" o6 y  Z
  5. * @return  u8                0:写入成功,其他:写入失败
    " p- e5 R4 r# e
  6. */& q: T2 q* ?5 ^1 J7 A" p8 Q; v' U
  7. u8 SPI2_WriteByte(u8 *TxData,u16 size)
    2 K" r( q0 ]( @* Q
  8. {
    ; l5 ^; ?4 }5 ~/ l- P
  9.         u8 retry=0;        ' ?. D3 L+ H- v
  10.         u8 n=0;
    : Z1 \! m% i9 ]' V
  11.         for(n=0;n<size;n++)
    5 r) ^; B6 d8 B( Z6 a9 N
  12.         {
    7 ^3 `$ Y% h/ y6 C7 _
  13.                 while (LL_SPI_IsActiveFlag_TXE(SPI2) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位$ R* ]/ x' c( c- I
  14.                 {! j5 e8 D3 T7 [8 v; k$ q! C' D
  15.                         retry++;
      o# w& A5 }9 e9 E, O
  16.                         if(retry>200)return retry;7 a# u  G- h/ V& ?
  17.                 }                          
    + |- z8 V% X& I
  18.                 LL_SPI_TransmitData8(SPI2, TxData[n]); //通过外设SPIx发送一个数据6 {" H0 }2 G# W' ~  E
  19.         }3 }* r& E( y" X7 a( d" _' b" [7 Z% X
  20.           D  X( |& r+ I
  21.         return 0;
    " `9 H6 u/ U- Y. ?7 C; z* c1 Q0 L8 v
  22. }
复制代码
, I8 P+ n' ^3 P  i7 U  _  j# p- G+ O
三、LCD代码移植+ ~  \. q+ H% w, J
BearPi和正点原子的Pandora开发板使用的LCD是同一款,且模式配置也一样,所以既然有现成的代码,我们不妨copy一下,将lcd.c和lcd.h复制过来( B+ Y  U. g  `9 T" ~" s
然后修改lcd.h里的LCD控制GPIO代码9 G- D2 b$ r5 C, ~# X
. e  d% n. ~5 c: \+ l
  1. /*
    ; ?5 g8 F) L8 R- O# ?
  2.         LCD_PWR:        PB15/ [, u; _+ C( }/ N1 d- q9 X
  3.         LCD_RST:        PC7, x2 Y" m( X: }2 ]* X! ~( P% C
  4.         LCD_DC:                PC6
    ! \7 [& I) H) Y5 @, q
  5. */8 E* l( N( P- v* Q! i
  6. #define        LCD_PWR(n)                (n?LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_15):LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_15))
    2 u+ X( \$ H/ c3 [5 o
  7. #define        LCD_RST(n)                (n?LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_7 ):LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_7))
    5 n3 E5 z/ g3 z( h* H
  8. #define        LCD_DC(n)                (n?LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_6 ):LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_6))4 ]+ g4 w+ C+ N: W1 p
复制代码

8 n: h* ]4 U( L将lcd.c里的LCD_Gpio_Init()代码删去,然后在LCD_Init()开头添加如下代码:3 D* Z4 v7 v' ~3 h% {. i

; D% J0 k* j' x
  1.     SPI2_Init();2 R1 s3 R& J9 k- ^9 z
  2.         
    ( L7 K" A! _) e( @* P9 h
  3.     LCD_PWR(0);                //关闭显示
    5 B6 [2 Z- y$ b( m- p$ U

  4. % p2 Z( D, C- l# t7 U' d
  5.     LCD_RST(0);
    0 G; {7 Z0 F+ a; b, ?9 ]
  6.     delay_ms(120);
      B/ [& N' R9 e
  7.     LCD_RST(1);                //复位
复制代码

0 c6 z0 \$ f& o在主函数里写入
4 `" }0 Z, z; D) c
) H$ c7 i- Z, t: P9 p8 }
  1.         LCD_Init();                                //初始化LCD
    : @8 R4 W( v* o+ F
  2.         
    6 p5 }3 L  v& o  I  S' y. k( m" n% _& y
  3.         POINT_COLOR = RED;
    ' H% q# {; @# u/ j4 T
  4.         LCD_ShowString(0, 100, 240, 32, 32, "BearPi STM32L4");
复制代码
/ @2 i- w( t% B& ]# c$ `
编译链接下载到开发板里,测试结果如下
; O9 r4 |! j9 \- s2 D
+ O' q. I7 ^" a) _ 2020011018350065.png 3 o8 l, S/ F; z3 d& L
5 p% W, F5 H& P9 G! P
表明测试成功1 t  v/ d8 W/ l. ^
————————————————
( c- a! Y" D; _转载:Willliam_william9 l5 g6 `4 W+ K# n- \

3 n+ L+ A( C& f; X2 g( x0 a. z4 h, v( `( T  L
赞 收藏 评论0 发布时间:2022-8-27 14:53

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版