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

STM32驱动ST7789V2 tft屏幕

[复制链接]
STMCU小助手 发布时间:2022-8-21 18:00
一 . 简介
* m& Y; E. c& ]9 F3 A  W& i& q本次教程使用的是1.54寸240*240像素的tft屏幕,其接口协议为SPI协议。在使用的过程中仅需要四根数据即可驱动点亮屏幕。然后硬件使用的是STM32F103C8T6核心板,用的是SPI2。一般购买屏幕的话它们会提供对应的例程,直接拿过来修改即可。& D3 E: y+ P3 ^& z/ r) _
2 [8 E7 O3 j9 ?) v3 Y) `% l  n7 i) U
二. 屏幕的使用
6 u. C  ^9 o4 a0 |0 x第一步肯定是引脚初始化,接口是SPI接口,所以也需要对SPI进行初始化(软件模拟SPI时序的话就不需要,硬件SPI需要),如果需要用到DMA进行加速的话,也需要对DMA进行初始化(不用DMA显示一副图片的速度比使用DMA的要慢上几倍,如果不显示图片的话可以不进行初始化)。' h( l: c# j1 E5 ]8 v" p  j
, w9 K( o5 K$ w  ?/ Z0 E* v0 d
1.屏幕引脚介绍:2 {7 R: L7 Q. K! u0 c) E
DC: 写数据后命令控制,1为数据
/ V7 x' e. v% a& ACS:片选,低电平有效
4 y2 P  H1 U' i% T3 m) ZRES: 控制lCD重启1 T9 ~; {' G% u7 Q+ v
SDA:SPI的MOSI线$ H9 F, |; m# f+ w
SCK:SPI的时钟线0 }5 d( G# `+ b/ p% s0 ]
BLK:控制LCD是否显示,不进行控制的话直接接高电平即可(这里直接接的高电平)
% {0 a! A. U' A" j2.引脚初始化
) h$ n, V# D8 n6 x% u+ I5 x7 [$ _这里除了SDA和SCK是SPI信号线需要进行复用之外,其他的都可以当做普通的IO进行初始化即可。查看手册可以知道SPI2的时钟映射到了GPIOB-Pin13,MOSI映射到了GPIOB-Pin15(一下子找不到了 ̄□ ̄||)。对其引脚进行复用初始化即可。
% J; Z- r/ V$ w1 y( g3.SPI初始化
% S4 q! R4 ]: G0 U: y5 F这里就直接上代码了
* c4 D% r1 e/ J7 ?, f
  1.     SPI_InitTypeDef SPI_InitStructure;
    % \5 w! U+ e7 Y$ T& ~1 ~- U
  2.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); //初始化SPI2端口时钟
    ; E; m  m' P& l, T  e3 i, h
  3.     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;& j8 ?4 z5 H" e1 k
  4.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    4 D2 y; w& b9 I5 L8 ^- O8 L
  5.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;* Q* L/ m' W4 y& k" s+ j
  6.     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    % S5 h: b, w, f: _! u
  7.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    % I! Z4 e. g" r/ G. O3 G5 F  q
  8.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;; f& F$ T9 X7 f
  9.     SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
      I3 P# A0 S* D
  10.     SPI_InitStructure.SPI_CRCPolynomial = 7;- @. w( G& s" F! x. d
  11.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
    9 r; L7 B% I9 X7 F
  12.     SPI_Init(SPI2,&SPI_InitStructure);. h8 z; [) r) E6 A7 W
  13.     SPI_Cmd(SPI2,ENABLE);
复制代码
6 }# r: j/ k2 T! a! W: ]
4.DMA初始化
& B5 `, G) J8 H7 L( h4 q8 ~  t' n需要查看SPI2的Tx是使用的DMA1的那个通道,这个也需要查看手册。如下图,映射到的时候通道5,根据这个就可以进行初始化了。
3 ^& G4 ]+ b3 e! T- w' e. p6 a) L: L; [* O, A. F# e
079514c7266542f6bd151bcd2b3a3a18.png * {1 d# R% |4 |# v/ D* ?5 f( O7 G
  U: y. v; z/ Q3 X4 o
  1. DMA_InitTypeDef DMA_InitStructure;
    ( p* `4 R/ d$ t, J& [! a
  2. 0 p3 {' v( B: Q1 G  L3 ]
  3.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    - ^* p* G7 ]* x
  4. " V! e, @: a1 Z; G0 ~- B/ N
  5.     DMA_DeInit(DMA1_Channel5); 3 u- f* l3 s4 r2 r( x) T
  6.     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32)&SPI2->DR;) T! f- j( ^, K: V
  7.     DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32)buffer;    //发送数据的内存地址
    3 s, P4 f; v( e* a* p
  8.     DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralDST; //方向为内存到外设! T! [$ C) ~/ p! U. i4 l9 O* Q
  9.     DMA_InitStructure.DMA_BufferSize         = 480;   //数据大小
    4 ~3 y6 _& w) S' o& w% D1 V
  10.     DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable; //每发送一个外设地址不变, A9 p$ e  x& K( N/ D* ^: u
  11.     DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable; //每发送一个内存地址加一
    6 _# e: {8 P( C( a
  12.     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;: I8 }. F' M0 l( R  q+ b* S
  13.     DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;
      A2 e. j! d9 z& g  v7 P7 G
  14.     DMA_InitStructure.DMA_Mode               = DMA_Mode_Normal;" j$ A: q* v' b( L- Q9 K1 q
  15.     DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;+ [# P% g1 @# ]; o" L' [" A
  16.     DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;- b5 l1 W) i3 b& C+ G
  17.     DMA_Init(DMA1_Channel5,&DMA_InitStructure);
复制代码

5 l- s; G1 K4 p$ ~% P% `+ m5.然后就是对LCD屏幕的初始化了,也就是配置对应的寄存器。这个可以拿卖家提供的直接拿来用就可以。8 i! g; p+ }) p/ I' C/ s6 x
这里我们就完成了所有的初始化工作了。" Q" z& l7 r3 a, E- Q( ]; B2 v
; K; [0 k5 W) r% o6 r9 m
1. 设置数据地址范围+ X8 B$ _+ [& B; t
每次发送显示数据的时候,需要设置显示范围,也就是行列的起始值。设置好范围,然后就发送对应大小的数据即可。其显示发送为从左往右,从上到下。5 H) l, p; {: k  p2 G

6 J* N# c2 \% S fb58874c6f744d58ac68da63db9998e5.png # f5 p& @% I, `$ O  ]& S
  1. + @9 t/ x1 n/ Q% O. F
  2. //设置数据显示地址范围
    : N9 L& B* w$ [1 p& Y4 W
  3. void LCD_Address_Set(uint16 x1,uint16 y1,uint16 x2,uint16 y2)
    / a% L* K9 {3 P& B. J
  4. {
    : T8 a' L0 E; n( D- j: g5 h3 ]
  5.     LCD_Write_Cmd(0x2a);//列地址设置  N; t2 y# r2 P  J9 G) ?
  6.     LCD_WriteDisplayData16(x1);9 f' L; T" e% i& f  x8 V) i
  7.     LCD_WriteDisplayData16(x2);7 o& ^+ u4 m8 y8 m' W5 L) t
  8.     LCD_Write_Cmd(0x2b);//行地址设置
    ( J* o, p- N1 D+ e; I1 J
  9.     LCD_WriteDisplayData16(y1);
    $ d' Y1 s0 O- f* b( Y; f% R: B
  10.     LCD_WriteDisplayData16(y2);
    9 t( V0 `/ d. M4 t+ y! U/ d+ S, g
  11.     LCD_Write_Cmd(0x2c);//储存器写% n* K* g) _1 Y! u5 I* B- N
  12. }
复制代码

$ Z3 E; |2 ~# K. x9 k2 v, U2. 点亮LCD屏幕* ^2 N2 d- _% k  m, L
  1. //LCD全亮
    0 R- b7 c% o& X. P# f
  2. void LCDFullOn(uint16 Color)
    ' J9 g9 o  a7 `5 r0 ]- I
  3. {
    ) i, N2 x# S9 ?, }7 _2 ]
  4.     uint16 i,j;         
    $ A! D5 w7 c6 u5 p- d/ a
  5.         LCD_Address_Set(0,0,LCD_Width-1,LCD_Height-1);
    ! ?& b# T; i, T' i2 i; w0 f
  6.     for(i=0;i<LCD_Width;i++)
    1 v/ x# x  q, W; _* o/ u' [& f  k
  7.           {
    ( z- e5 ~: D. F
  8.                         for (j=0;j<LCD_Height;j++)# V, e2 P5 ^: R$ ^& f2 ?
  9.                                 {
    0 e/ ~% e, O% S& J( A* c
  10.                                         LCD_WriteDisplayData16(Color);7 T# o7 O, }- W2 y4 D6 u' X% V' u! z* E$ U
  11.                                 }      8 \4 K0 g; n  H; `0 S4 U
  12.           }
    8 t3 V& E2 b( l. Q
  13. }
复制代码

$ q+ t5 l! g& p3. 使用DMA搬运数据/ [6 l  g% A6 [
1.对设置DMA搬运数据的大小并且使能! U& y7 i1 w- ]/ B3 |
  1. //spi2 DMA使能
    8 V3 h# j) }8 `. I
  2. void SPI2DMA_Enable(void)1 z! i* U0 {" F$ F
  3. {# `: y( j2 p, {0 P$ U
  4.     DMA_Cmd(DMA1_Channel5, DISABLE );    % p5 ?, q. ^0 Z" ^5 J
  5.          DMA_SetCurrDataCounter(DMA1_Channel5,480);  //设置搬运数据的大小
    : p. C6 K/ m% ~( ^$ m, d
  6.          DMA_Cmd(DMA1_Channel5, ENABLE);  2 Y$ Z  H3 I2 P1 ~2 ]; g
  7. }
复制代码

7 g5 |; o: O, S' u1 H2.开启DMA请求,且等待发送完成,清除标志位
5 {: A# ~; Q8 g+ k
  1.   for(j = 0 ; j< 240 ; j++)
    & A" Z; D4 O5 Y) ~7 c  Z
  2.     {! i  T5 q! Q. y/ W/ |
  3.         SPI_I2S_DMACmd(SPI2,SPI_I2S_DMAReq_Tx,ENABLE);
    & @$ L6 g; \: {& j
  4.             SPI2DMA_Enable();
    % M( }# L  [, N* \. r" x! {9 [
  5.         while((DMA_GetFlagStatus(DMA1_FLAG_TC5)==RESET)); // 等待dma发送完成. [8 r6 |5 Z( i
  6.         DMA_ClearFlag(DMA1_FLAG_TC5);
    . S5 b& T+ B  S: U* G
  7.     }
复制代码
1 U3 A, u8 X( q
通过测试,可以明显看到使用DMA进行加速的显示效果要快很多。. S1 J( [' g: W$ X7 v- ~
2 O  R4 H* X2 b$ C- E& r! Z

" E- V* d2 C2 h6 f) }! C+ o$ Q
2 Y9 p" P5 m/ a
赞 收藏 评论0 发布时间:2022-8-21 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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