打印
[单片机芯片]

【CH32X035评估板测评】第三章 SPI驱动TFT液晶屏

[复制链接]
1085|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 qintian0303 于 2023-10-3 18:32 编辑

      显示单元的驱动:本次测试选用的是1.54寸tft作为显示元件,主要参数是240*240分辨率,主控是7789,通过SPI/8080进行通信,在本次测试使用SPI进行通信,同时驱动部分也是对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);
}

//******************************************************************************
//* 函数名称  : SPI1_IOInit()                                       
//* 函数描述  : SPI对应的IO口初始化                           
//* 输入参数  :                                                                 
//* 参数描述  :                                                                 
//* 输出参数  : 无                                                              
//* 返回值    : 无                                                               
//******************************************************************************      
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;
}

//******************************************************************************
//* 函数名称  : SPI1_Send_Data(uint8_t Data)
//* 函数描述  : SPI1发送8位数据
//* 输入参数  : Data
//* 参数描述  : 具体的指令代码
//* 输出参数  : 无
//* 返回值    : 无
//******************************************************************************  
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),效果如下:
      可以看出来驱动成功了,不过对于240*240分辨率老说,这个刷新速度是不理想的,主要原因还是因为该芯片的主频只有48MHz,接下来我们看看使用硬件SPI的效果。
      然后咱们用硬件SPI体验一下刷屏:
      代码如下:
//******************************************************************************
//* 函数名称  : SPI1_IOInit()                                       
//* 函数描述  : SPI1对应的IO口初始化                           
//* 输入参数  :                                                                 
//* 参数描述  :                                                                 
//* 输出参数  : 无                                                              
//* 返回值    : 无                                                               
//******************************************************************************      
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);
   
}


//******************************************************************************
//* 函数名称  : SPI_Send_Data(uint8_t Data)
//* 函数描述  : SPI发送8位数据
//* 输入参数  : Data
//* 参数描述  : 具体的指令代码
//* 输出参数  : 无
//* 返回值    : 无
//******************************************************************************  
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;                                                            

}
     看一看效果:
      对比IO口模拟SPI和硬件SPI的效果,使用硬件SPI刷屏的速度还是有明显的提升的。
      接下来通过SPI功能深度体验了一下MounRiver Studio这个开发环境,感觉还是很喜欢的。
      比如Outline显示框,我们在进行对应文件的编写时,这个框里面就会把当前文件的所有头文件,变量,函数等内容集中显示,这样避免咱们总是上下拉文件来找,尤其是文件比较大的时候,查找会很方便;
      添加文件不在需要逐个添加,放到对应的文件夹下,添加一次就会把所有的刷新添加了,有好处也有弊端,好处是便捷,弊端是比如只想添加一个,多个都拉进来了  还得一个一个移除;
      下载和调试是分开的,习惯需要重新建立,下载器去除后并没有对应的报警提示;
      整体来说MounRiver Studio开发环境还是挺简洁实用的。


使用特权

评论回复
沙发
袁胜富| | 2023-10-4 22:43 | 只看该作者
刷屏好慢,建议使用SPI DMA

使用特权

评论回复
板凳
qintian0303|  楼主 | 2023-10-5 09:26 | 只看该作者
袁胜富 发表于 2023-10-4 22:43
刷屏好慢,建议使用SPI DMA

全屏刷新适合用DMA,不过采取局部刷新或者字库DMA就发挥不了太大作用了,依然得一个一个点写,应该会有效果,不过效果不大

使用特权

评论回复
地板
Bymyself| | 2023-10-5 20:37 | 只看该作者
这个主频,刷新速度算可以了,就算提高一倍主频,整屏刷也会看到痕迹

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:硬件工程师
简介:有着多年硬件开发经验的专业人员,专注于医疗电子领域,热衷于对新鲜事物的探索,喜欢DIY!

43

主题

644

帖子

4

粉丝