[原创] 【AT32WB415测评】03 SPI驱动TFT液晶屏

秦天qintian0303   2022-8-11 18:10 楼主

03 SPI驱动TFT液晶屏

前言

        上文已经实现MCU的IO口、定时器、外部中断等操作,在此基础上我们来实现TFT液晶屏的驱动,用于后边测试的状态张氏。

目标

        软硬件驱动TFT液晶屏,实现页面展示。

实现

        本次使用的液晶屏是1.54吋,IPS高清显示,分辨率240*240,驱动芯片为ST7789,支持MCU和SPI两种通信方式,本次通过SPI方式驱动液晶屏,相对来说分辨率不低,所以通过软硬件两种方式可以轻松看出来比较明显的区别,液晶屏SPI通信时只能作为从机接收数据,所以只用到了MOSI和SCK,CS和RS通过软件控制,复位和背光控制通过软件控制。

相应宏定义

#define MOSI_OUT0       gpio_bits_reset(GPIOB,GPIO_PINS_15)
#define MOSI_OUT1       gpio_bits_set(GPIOB,GPIO_PINS_15)

#define CLK_OUT0      gpio_bits_reset(GPIOB,GPIO_PINS_13)
#define CLK_OUT1      gpio_bits_set(GPIOB,GPIO_PINS_13)

#define CS_OUT0       gpio_bits_reset(GPIOA,GPIO_PINS_4)
#define CS_OUT1       gpio_bits_set(GPIOA,GPIO_PINS_4)

#define TFT_RS_reset            gpio_bits_reset(GPIOA,GPIO_PINS_5)
#define TFT_RS_set              gpio_bits_set(GPIOA,GPIO_PINS_5)
#define TFT_RESET_reset         gpio_bits_reset(GPIOA,GPIO_PINS_3)
#define TFT_RESET_set           gpio_bits_set(GPIOA,GPIO_PINS_3)
#define TFT_BL_SET              gpio_bits_set(GPIOA,GPIO_PINS_2)
#define TFT_BL_RESET            gpio_bits_reset(GPIOA,GPIO_PINS_2)

 

软件模拟SPI控制:

void SPI_IOInit(void)
{
  gpio_init_type gpio_init_struct;
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

  gpio_init_struct.gpio_drive_strength  = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type        = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode            = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pins            = GPIO_PINS_13|GPIO_PINS_15;
  gpio_init_struct.gpio_pull            = GPIO_PULL_NONE;
  gpio_init(GPIOB, &gpio_init_struct);

  gpio_init_struct.gpio_drive_strength  = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type        = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode            = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pull            = GPIO_PULL_UP;
  gpio_init_struct.gpio_pins            = GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_3;
  gpio_init(GPIOA, &gpio_init_struct);
  
  gpio_init_struct.gpio_drive_strength  = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type        = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode            = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pull            = GPIO_PULL_DOWN;
  gpio_init_struct.gpio_pins            = GPIO_PINS_2;
  gpio_init(GPIOA, &gpio_init_struct);

  CLK_OUT0;
  MOSI_OUT0;
  CS_OUT0;
  TFT_RS_reset;
  TFT_RESET_reset;
  TFT_BL_RESET;
}

void SPI_Send_Data(uint8_t Data)
{
  
  CS_OUT0;                                                              //选中该从机
  delay_us(2);

  uint8_t i;
  for (i = 0;i < 8;i++)
  { 
    if ((Data << i) & 0x80)
    {
      MOSI_OUT1;
      CLK_OUT0;//rising edge
      CLK_OUT1;
    }
    else
    {
      MOSI_OUT0;
      CLK_OUT0;//rising edge
      CLK_OUT1;
    }
  }
  
  CS_OUT1;                                                             

}

硬件SPI控制:

void SPI_IOInit(void)
{
  gpio_init_type gpio_initstructure;
  spi_init_type spi_init_struct;

  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
  
  /* software cs, pa4 as a general io to control flash cs */
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pins           = GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_3;
  gpio_init(GPIOA, &gpio_initstructure);
  
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;
  gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_initstructure.gpio_pull           = GPIO_PULL_DOWN;
  gpio_initstructure.gpio_pins           = GPIO_PINS_2;
  gpio_init(GPIOA, &gpio_initstructure);
  
  CS_OUT0;
  TFT_RS_reset;
  TFT_RESET_reset;
  TFT_BL_RESET;
  /* sck */
  gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  gpio_initstructure.gpio_pull           = GPIO_PULL_UP;
  gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
  gpio_initstructure.gpio_pins           = GPIO_PINS_13;
  gpio_init(GPIOB, &gpio_initstructure);
  /* mosi */
  gpio_initstructure.gpio_pull           = GPIO_PULL_DOWN;
  gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
  gpio_initstructure.gpio_pins           = GPIO_PINS_15;
  gpio_init(GPIOB, &gpio_initstructure);

  crm_periph_clock_enable(CRM_SPI2_PERIPH_CLOCK, TRUE);
  spi_default_para_init(&spi_init_struct);
  spi_init_struct.transmission_mode     = SPI_TRANSMIT_FULL_DUPLEX;
  spi_init_struct.master_slave_mode     = SPI_MODE_MASTER;
  spi_init_struct.mclk_freq_division    = SPI_MCLK_DIV_8;
  spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
  spi_init_struct.frame_bit_num         = SPI_FRAME_8BIT;
  spi_init_struct.clock_polarity        = SPI_CLOCK_POLARITY_HIGH;
  spi_init_struct.clock_phase           = SPI_CLOCK_PHASE_2EDGE;
  spi_init_struct.cs_mode_selection     = SPI_CS_SOFTWARE_MODE;
  spi_init(SPI2, &spi_init_struct);
  spi_enable(SPI2, TRUE);
}

void SPI_Send_Data(uint8_t Data)
{
  
  CS_OUT0;                                                              //选中该从机
  delay_us(1);
  
  spi_i2s_data_transmit(SPI2, Data);
  while(spi_i2s_flag_get(SPI2, SPI_I2S_TDBE_FLAG) == RESET);
  
  delay_us(1);
  CS_OUT1;                                                             

}

        在软件模拟驱动成功后切换到硬件SPI时出现了一个小插曲,居然驱动失败了,通过不断的修改测试发现出现在了CS_OUT1;这个操作,可能上升太快导致异常,在之前加了一个delay_us(1);后驱动正常。 

        直接使用#if + #elif + #endif进行选择性代码编写,方便切换。

        具体的tft的驱动代码可以结合实际使用的屏进行设计,这块一般都是使用的厂家提供的驱动代码。

        驱动成功:

微信图片_20220810211933.jpg

 

 

 

 

 

 

 

 

 

 

 

 

 

 

在爱好的道路上不断前进,在生活的迷雾中播撒光引

回复评论 (2)

只看到背光亮了,没见有显示,是不是上传图片有误?

点赞  2022-8-11 21:38
引用: lugl4313820 发表于 2022-8-11 21:38 只看到背光亮了,没见有显示,是不是上传图片有误?

只是点亮了,验证SPI功能正常

在爱好的道路上不断前进,在生活的迷雾中播撒光引
点赞  2022-8-11 23:03
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复