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

STM32驱动ST7789V2 tft屏幕

[复制链接]
STMCU小助手 发布时间:2022-8-21 18:00
一 . 简介' B% J& T2 r& E2 u6 ^- B0 ^. a
本次教程使用的是1.54寸240*240像素的tft屏幕,其接口协议为SPI协议。在使用的过程中仅需要四根数据即可驱动点亮屏幕。然后硬件使用的是STM32F103C8T6核心板,用的是SPI2。一般购买屏幕的话它们会提供对应的例程,直接拿过来修改即可。( v1 v5 }. W" L8 u

0 o) V1 V. {& `二. 屏幕的使用
9 I3 m  J0 H9 \8 s; X$ ~第一步肯定是引脚初始化,接口是SPI接口,所以也需要对SPI进行初始化(软件模拟SPI时序的话就不需要,硬件SPI需要),如果需要用到DMA进行加速的话,也需要对DMA进行初始化(不用DMA显示一副图片的速度比使用DMA的要慢上几倍,如果不显示图片的话可以不进行初始化)。7 J; j% K7 D* \  ?
- e4 F$ ^) q9 S# E
1.屏幕引脚介绍:
" d1 E' r  z2 }/ w% uDC: 写数据后命令控制,1为数据
- N6 H! q. m5 E# tCS:片选,低电平有效6 w, B+ S, X) X, w5 {8 z
RES: 控制lCD重启
7 i3 S" F; r# P' J) z0 n. w7 eSDA:SPI的MOSI线
+ C. A3 Z( j; u) {, X2 ZSCK:SPI的时钟线
! ?* w: L* H) uBLK:控制LCD是否显示,不进行控制的话直接接高电平即可(这里直接接的高电平)4 v: r5 E+ b5 k8 X' T* V! m4 T
2.引脚初始化
- T2 i7 j# f& T# ]这里除了SDA和SCK是SPI信号线需要进行复用之外,其他的都可以当做普通的IO进行初始化即可。查看手册可以知道SPI2的时钟映射到了GPIOB-Pin13,MOSI映射到了GPIOB-Pin15(一下子找不到了 ̄□ ̄||)。对其引脚进行复用初始化即可。; T" N; G4 F& ?# F( D& N
3.SPI初始化5 n4 c6 ]: F7 b- x% N0 |
这里就直接上代码了- e' o- B; a. O: D( C& Y. Z7 t
  1.     SPI_InitTypeDef SPI_InitStructure;! @8 R, X+ }. L1 r7 R/ r( j" n
  2.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); //初始化SPI2端口时钟& b% H4 r- K$ A' s3 i
  3.     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    - H7 _* e- I- W3 _6 f/ B/ g; q5 h
  4.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;+ z4 R* a7 V) E) C+ F! o8 @
  5.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;, V$ @# r- W& u* w( ]8 q
  6.     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    6 s7 V* V) B- [& F" v
  7.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;+ r$ X% r, \$ h0 n- X$ W0 k0 p9 @$ D- R
  8.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    8 I: R5 E% b/ I3 R
  9.     SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
    7 i  r; Z+ z1 G8 Q5 H
  10.     SPI_InitStructure.SPI_CRCPolynomial = 7;
      r9 ?9 P( E. G- @% g
  11.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
    " W6 y* V5 n, f" d
  12.     SPI_Init(SPI2,&SPI_InitStructure);& O' C) E4 i9 p" b- _6 [
  13.     SPI_Cmd(SPI2,ENABLE);
复制代码
, f: s0 c0 G7 `( x/ ^! M
4.DMA初始化
; ^2 k. v/ w3 r3 J需要查看SPI2的Tx是使用的DMA1的那个通道,这个也需要查看手册。如下图,映射到的时候通道5,根据这个就可以进行初始化了。
9 j) y; L! F+ ?5 |6 m% ?9 W4 a" S6 F: }- X3 P' {$ @) I, d* ?* D
079514c7266542f6bd151bcd2b3a3a18.png 1 Z/ C% \8 o3 s6 u
3 P2 Y, ^0 I' d& Z' D8 }: _8 @
  1. DMA_InitTypeDef DMA_InitStructure;
    % x0 \; @; z, f, w8 D

  2. * S6 d9 `. c2 |3 {# {: R
  3.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);/ J- |/ N2 A$ m7 \

  4. : [+ j, Z  n; c
  5.     DMA_DeInit(DMA1_Channel5); 0 y& ?8 q& ], E# [
  6.     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32)&SPI2->DR;5 M7 i' F  b" \9 T! M
  7.     DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32)buffer;    //发送数据的内存地址4 B8 P9 |' r- G, T. N- u5 f
  8.     DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST; //方向为内存到外设
    % A5 [5 ~- m) [- l! ?
  9.     DMA_InitStructure.DMA_BufferSize         = 480;   //数据大小
    ) L% L! L5 \! ]2 a
  10.     DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable; //每发送一个外设地址不变8 `  s$ l  Q& r* O& N
  11.     DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable; //每发送一个内存地址加一
    7 e& k3 x7 v) a$ q
  12.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    + z; p+ f% ?: @  c$ R
  13.     DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;5 |2 ?6 R; ^9 k6 p9 K0 x' N1 o9 Z
  14.     DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;
    4 S+ M( a+ p+ G9 }) ?9 K. h, L
  15.     DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;: ^. Y" o1 ?; h8 A1 ^) z, `* }+ I. q
  16.     DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;
    ) }* }* k0 c" X6 b
  17.     DMA_Init(DMA1_Channel5,&DMA_InitStructure);
复制代码

$ J8 N8 v6 w+ \3 [3 s' s) Q5.然后就是对LCD屏幕的初始化了,也就是配置对应的寄存器。这个可以拿卖家提供的直接拿来用就可以。
- A) F- ?  b8 s. K) ~- m这里我们就完成了所有的初始化工作了。
8 A1 A  j& A; H! r) V) V% |# ~4 ~$ J# Q
1. 设置数据地址范围
% _: E+ s1 z2 J每次发送显示数据的时候,需要设置显示范围,也就是行列的起始值。设置好范围,然后就发送对应大小的数据即可。其显示发送为从左往右,从上到下。
/ W" K; y0 R/ T% g4 C
' t; r0 n7 m) Z) ?: H, u fb58874c6f744d58ac68da63db9998e5.png 5 P+ }0 I  r7 f& F6 E% F

  1. 7 N( G) h0 v/ L7 I; P1 A$ x
  2. //设置数据显示地址范围0 u* z6 b$ I7 ^7 }: m; c8 S
  3. void LCD_Address_Set(uint16 x1,uint16 y1,uint16 x2,uint16 y2)
    ' [  b* y1 L5 U7 X  X
  4. {
    ! A3 ]7 R- r; L& n7 N
  5.     LCD_Write_Cmd(0x2a);//列地址设置
    $ h' L4 e* P, |
  6.     LCD_WriteDisplayData16(x1);6 C0 n. C; u" O$ W8 a
  7.     LCD_WriteDisplayData16(x2);
    6 U2 D* Q! O: z
  8.     LCD_Write_Cmd(0x2b);//行地址设置
    ! B3 a% Q8 C; J! c/ x% X1 ^
  9.     LCD_WriteDisplayData16(y1);7 X. r% n0 i2 x* ^. r3 x# {
  10.     LCD_WriteDisplayData16(y2);' J2 H5 L0 _' c0 y: }
  11.     LCD_Write_Cmd(0x2c);//储存器写
    . g' l3 A( C# D+ l
  12. }
复制代码
- f. d/ }$ w, P0 S, l! M
2. 点亮LCD屏幕. D: c3 K) W$ S4 |3 X- ?( ?
  1. //LCD全亮
    + {, j$ {2 a, ~, m$ u# B) V
  2. void LCDFullOn(uint16 Color)
    5 o7 W) e8 z7 W. b& Q8 [
  3. {. z- i( j3 _) ?4 F  C. i
  4.     uint16 i,j;         
    - S% J! j5 [7 a
  5.         LCD_Address_Set(0,0,LCD_Width-1,LCD_Height-1);
    2 k" ^: W, t& i. {, c% L! T' E* o$ c
  6.     for(i=0;i<LCD_Width;i++)1 q# y* j# t  m
  7.           {
    * V) n5 B5 Q/ b9 _
  8.                         for (j=0;j<LCD_Height;j++)
    : H3 ~  n3 o/ H  _
  9.                                 {1 H/ ?0 J0 K: i; ?+ x# F4 o
  10.                                         LCD_WriteDisplayData16(Color);1 e5 ~" ^8 }" q, S
  11.                                 }      2 C0 h0 I' n9 Q% |8 V0 w9 B6 \
  12.           }) N% X( H6 U3 t; ~+ k% R
  13. }
复制代码
2 s  [. F8 z6 y, D9 }0 w, f
3. 使用DMA搬运数据
3 x! u+ }! O7 W; @1.对设置DMA搬运数据的大小并且使能
9 j6 w: W( L: b8 W% {+ D& q
  1. //spi2 DMA使能 - n/ C8 g- b' b' p
  2. void SPI2DMA_Enable(void). E/ z3 K' H6 T( M4 x! A0 |6 c
  3. {
    : t+ H( E; K' Q3 u. u
  4.     DMA_Cmd(DMA1_Channel5, DISABLE );   
    9 b5 @2 x: O% z+ Y
  5.          DMA_SetCurrDataCounter(DMA1_Channel5,480);  //设置搬运数据的大小- O! c* \& }9 i. _: }# g+ Q
  6.          DMA_Cmd(DMA1_Channel5, ENABLE);  
    2 F* l6 ^4 a+ ~
  7. }
复制代码
) t: q5 \! |9 x, g! ~* y
2.开启DMA请求,且等待发送完成,清除标志位7 m6 D6 ^6 O/ s$ ]- \1 ~
  1.   for(j = 0 ; j< 240 ; j++)
    ' q9 }2 h4 c- i8 R" y% W! B) r. g
  2.     {
    7 i, y! w' |. G: @; o5 ~% r, U
  3.         SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);
    8 k9 A1 J6 [) B- B$ k* e
  4.             SPI2DMA_Enable();
    7 {6 |4 x3 U  I" ?# w8 R/ w
  5.         while((DMA_GetFlagStatus(DMA1_FLAG_TC5)==RESET)); // 等待dma发送完成
    & o1 m6 K  v/ h/ K; Y/ h
  6.         DMA_ClearFlag(DMA1_FLAG_TC5);; }. @9 z. B/ h3 q
  7.     }
复制代码

) w0 h+ e: e& e: M通过测试,可以明显看到使用DMA进行加速的显示效果要快很多。
$ A" U( p5 t/ r2 n: }
; r) J5 `0 W7 F1 i. l9 Z1 t
: g* s. c+ @9 x  t! c% d( Y1 G$ b  G7 W) D3 C
赞 收藏 评论0 发布时间:2022-8-21 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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