这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【分享评测,赢取加热台】CH32X035的软硬件SPI驱动TFT液晶屏

共4条 1/1 1 跳转至

【分享评测,赢取加热台】CH32X035的软硬件SPI驱动TFT液晶屏

高工
2024-03-31 19:20:17   被打赏 50 分(兑奖)     打赏

本次测试主要是通过SPI驱动显示单元:

        在本次测试中,我们选用了1.54英寸的TFT液晶显示屏作为显示元件。该屏幕具备高清晰度特性,其主要参数为240×240的分辨率,能够呈现出细腻的图像和文字效果。该显示单元采用了7789作为主控芯片。这款芯片支持SPI和8080两种通信协议,具有高度的灵活性和可扩展性。

        在本次测试中,我们选择了SPI协议作为通信方式。SPI(Serial Peripheral Interface)是一种同步串行外设接口,具有高速、简洁、低功耗的特点,非常适合用于显示单元与主控芯片之间的数据传输。

        在驱动部分,我们分别尝试了使用IO口模拟和硬件SPI两种方式来驱动显示屏。首先,我们采用了IO口模拟SPI的方式进行屏幕驱动。这种方式通过软件编程,利用IO口的输入输出功能来模拟SPI通信协议的时序和数据传输过程。虽然这种方法相对复杂且速度可能受到一定限制,但它无需额外的硬件支持,成本较低,且具有较强的灵活性。

        IO口模拟部分代码如下:

#define SPI1_MASTER                     SPI1
#define SPI1_MASTER_PERIPH              RCC_APB2_PERIPH_SPI1
#define SPI1_MASTER_PERIPH_GPIO         RCC_APB2Periph_GPIOA
#define SPI1_MASTER_GPIO                GPIOA
#define SPI1_MOSI_GPIO_ALTERNATE        GPIO_AF1_SPI1
#define SPI1_CLK_GPIO_ALTERNATE         GPIO_AF2_SPI1
#define SPI1_MASTER_MISO_PIN            GPIO_Pin_6
#define SPI1_MASTER_MOSI_PIN            GPIO_Pin_7
#define SPI1_MASTER_CLK_PIN             GPIO_Pin_5
#define SPI1_MASTER_NSS_PIN             GPIO_Pin_4

#define TFT_BL_GPIO                     GPIOC
#define TFT_BL_PERIPH_GPIO              RCC_APB2Periph_GPIOC
#define TFT_BL_PIN                      GPIO_Pin_7
#define TFT_RS_PIN                      GPIO_Pin_16
#define TFT_RESET_PIN                   GPIO_Pin_17

#define TFT_RS_reset            GPIO_WriteBit(TFT_BL_GPIO, TFT_RS_PIN,Bit_RESET)
#define TFT_RS_set              GPIO_WriteBit(TFT_BL_GPIO, TFT_RS_PIN,Bit_SET)
#define TFT_RESET_reset         GPIO_WriteBit(TFT_BL_GPIO, TFT_RESET_PIN,Bit_RESET)
#define TFT_RESET_set           GPIO_WriteBit(TFT_BL_GPIO, TFT_RESET_PIN,Bit_SET)
#define TFT_BL_SET              GPIO_WriteBit(TFT_BL_GPIO, TFT_BL_PIN,Bit_SET)
#define TFT_BL_RESET            GPIO_WriteBit(TFT_BL_GPIO, TFT_BL_PIN,Bit_RESET)
#define SPI1_CS_OUT0            GPIO_WriteBit(SPI1_MASTER_GPIO, SPI1_MASTER_NSS_PIN,Bit_RESET)
#define SPI1_CS_OUT1            GPIO_WriteBit(SPI1_MASTER_GPIO, SPI1_MASTER_NSS_PIN,Bit_SET)

#define SPI1_MOSI_OUT0          GPIO_WriteBit(SPI1_MASTER_GPIO, SPI1_MASTER_MOSI_PIN,Bit_RESET)
#define SPI1_MOSI_OUT1          GPIO_WriteBit(SPI1_MASTER_GPIO, SPI1_MASTER_MOSI_PIN,Bit_SET)

#define SPI1_CLK_OUT0           GPIO_WriteBit(SPI1_MASTER_GPIO, SPI1_MASTER_CLK_PIN,Bit_RESET)
#define SPI1_CLK_OUT1           GPIO_WriteBit(SPI1_MASTER_GPIO, SPI1_MASTER_CLK_PIN,Bit_SET)

void delay_us(uint32_t Data)
{
    Delay_Us(Data);
}

void delay_ms(uint32_t Data)
{
    Delay_Ms(Data);
}
  
void SPI1_IOInit(void)
{

    GPIO_InitTypeDef GPIO_InitStructure = {0};
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE);

    GPIO_InitStructure.GPIO_Pin = SPI1_MASTER_NSS_PIN | SPI1_MASTER_MOSI_PIN | SPI1_MASTER_CLK_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = TFT_BL_PIN |TFT_RS_PIN | TFT_RESET_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    SPI1_CLK_OUT0;
    SPI1_MOSI_OUT0;
    SPI1_CS_OUT1;
    TFT_RS_reset;
    TFT_RESET_reset;
    TFT_BL_SET;
}

void SPI1_Send_Data(uint8_t Data)
{
  
    SPI1_CS_OUT0;                                                              //选中该从机
    delay_us(2);

    uint8_t i;
    for (i = 0;i < 8;i++)
    {
        if ((Data << i) & 0x80)
        {
          SPI1_MOSI_OUT1;
          SPI1_CLK_OUT0;//rising edge
          SPI1_CLK_OUT1;
        }
        else
        {
          SPI1_MOSI_OUT0;
          SPI1_CLK_OUT0;//rising edge
          SPI1_CLK_OUT1;
        }
     }
  
    SPI1_CS_OUT1;
}

        显示屏的驱动初始化程序因芯片型号的不同而有所差异,因此在此不作详细介绍。只要能够成功实现8位数据的时序传输,基本上就可以保证驱动程序的正常工作。

目前我们使用的SPI接口中,CS(片选)、MOSI(主出从入)和CLK(时钟)分别对应复用功能的GPIOA的GPIO_Pin_4、GPIO_Pin_7和GPIO_Pin_5。而其他控制字引脚则采用普通的IO控制方式。具体来说,RS引脚用于切换数据/命令模式(对应GPIOC-GPIO_Pin_16),复位引脚用于重启显示屏(对应GPIOC-GPIO_Pin_17),而BL引脚则用于控制背光开关(对应GPIOC-GPIO_Pin_7)。

        通过上述引脚配置和控制方式,我们实现了对显示屏的精确控制,取得了良好的显示效果:

IO模拟SPI刷屏.gif

        经过初步的测试,我们可以确认显示屏的驱动已经成功实现。然而,对于240*240的高分辨率来说,当前的刷新速度并不尽如人意。这主要是由于主控芯片的主频限制在48MHz,从而影响了数据传输的速度和效率。

        为了进一步提升刷新速度,我们接下来将尝试使用硬件SPI来进行屏幕刷新。硬件SPI相较于IO口模拟的方式,具有更高的数据传输速率和更低的延迟,因此有望显著提升显示屏的刷新效果。现在,让我们来体验一下使用硬件SPI进行刷屏的过程。通过配置和初始化硬件SPI接口,我们将能够直接利用硬件的特性,实现更高效的数据传输。这将使得显示屏在显示图像和文字时更加流畅和迅速,带来更加出色的视觉体验。

        接下来,我们将展示相关的代码实现。这些代码将详细展示如何配置硬件SPI接口、发送数据以及控制显示屏的刷新过程。通过这些代码,我们可以深入了解硬件SPI的工作原理,并探索其在显示驱动中的应用潜力。

        代码如下:

void SPI1_IOInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    SPI_InitTypeDef  SPI_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_SPI1, ENABLE);

    GPIO_InitStructure.GPIO_Pin = TFT_BL_PIN | TFT_RS_PIN | TFT_RESET_PIN ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = SPI1_MASTER_NSS_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    SPI1_CS_OUT1;
    TFT_RS_reset;
    TFT_RESET_reset;
    TFT_BL_SET;

    SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);

    SPI_Cmd(SPI1, ENABLE);
   
}
 
void SPI1_Send_Data(uint8_t Data)
{
  
  SPI1_CS_OUT0;                                                              //选中该从机
  delay_us(1);
  
  SPI_I2S_SendData(SPI1_MASTER, Data);
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
  
  delay_us(1);
  SPI1_CS_OUT1;                                                             

}

        效果如下:

硬件SPI刷屏展示.gif

        对比IO口模拟SPI和硬件SPI的效果,使用硬件SPI刷屏的速度还是有明显的提升的。





关键词: CH32X035     SPI          评测    

专家
2024-04-01 08:48:52     打赏
2楼

谢谢分享


高工
2024-04-01 13:17:07     打赏
3楼

谢谢分享


高工
2024-04-01 13:19:18     打赏
4楼

谢谢分享


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]