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

【NUCLEO-U545RE-Q】评测 SPI通信速测试+驱动LCD屏

[复制链接]
lugl 发布时间:2023-11-22 08:27

LCD屏是常用的外设,常用的是SPI来驱动,下面向大家展示,如何用spi的软件摸拟spi协议与硬件SPI来驱动Gc9036的TFT屏。

【开发工具】

stm32CubeIDE

【硬件】

STM32U545RE-Q NCLEO开发板

GC9306TFT屏

【实现步骤】

1、新建stm32project 工程,工程选用NUCLEO-U545RE开发板。

image.png

2、点下一步,输入工程名称,然后按finish生成工程:

image.png

3、选中spi1,在模式选项中,选中只发送模式。

image.png

4、配置时钟主频为160M。

image.png

5、回到spi总线配置界面选为8bit,16分频,片选为失能:

image.png

6、打开GPIO配置中的spi,选择速为Very High

image.png

8、配置LCD屏的SCK、CS、RST、DC四个GPIO,分别为如下

//              GND   电源地
//              VCC   3.3v电源
//              SCL   PA1(SCLK)
//              SDA   PA7(MOSI)
//              RES   PA2
//              DC    PA0
//              CS    PA4
//              BLK   PB0

9、在stm32cubeIDE中配置为输出模式,并帖标签为TFT_DC、TFT_CS、TFT_SCK,如果使用背光控制可以增加TFT_BLK,如果不用,则直接接VCC就行。

image.png

10、保存交生成工程代码。

11、添加移植在其他工程的复制粘帖进工程里面

image.png

12、添加文件夹到工程:

image.png

13、修改spi的数据发送函数。在spi数据传输中,官方的库给我们封装了HAL_SPI_Transmit用于阻塞式的发送。在LCD屏的通信协议中,我们需要自己定义DC(命令、数据发送)、CS片选来实现与屏的通信协议。DC为高电平时,传输命令,DC为低电平时发送的为数据,CS为低电平时为选中TFT屏。为此我们重构SPI硬件、软件发送指令为:

void LCD_Writ_Bus(uint8_t dat)
{

    LCD_CS_Clr;
    #if SOFTWARE_SPI_ENABLE    
        uint8_t i;
        for(i=0;i<8;i++)
        {                      
            LCD_SCLK_LOW();
            if(dat&0x80)
            {
               LCD_MOSI_HIGH();
            }
            else
            {
               LCD_MOSI_LOW();
            }
            LCD_SCLK_HIGH();
            dat<<=1;
        }
#else
    HAL_SPI_Transmit(&hspi1, dat, 1,1000);


#endif 
    LCD_CS_Set;
}

14、发送命令与数据的代码如下:

/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA8(uint8_t dat)
{
    uint8_t buff[2];
    buff[0] = dat;
#if SOFTWARE_SPI_ENABLE
    LCD_Writ_Bus(dat);
#else
    HAL_SPI_Transmit(&hspi1, buff, 1,1000);
#endif

}


/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA(uint16_t dat)
{
#if SOFTWARE_SPI_ENABLE
    LCD_Writ_Bus(dat>>8);
    LCD_Writ_Bus(dat);
#else
    uint8_t buff[2];
    buff[0] = dat>>8;
    buff[1] = (uint8_t)dat;
    HAL_SPI_Transmit(&hspi1, buff, 2,1000);
#endif
}


/******************************************************************************
      函数说明:LCD写入命令
      入口数据:dat 写入的命令
      返回值:  无
******************************************************************************/
void LCD_WR_REG(uint8_t dat)
{
    uint8_t buff[2];
    buff[0] = dat;
    LCD_DC_Clr;//写命令
#if SOFTWARE_SPI_ENABLE
    LCD_Writ_Bus(dat);
#else
    HAL_SPI_Transmit(&hspi1, buff, 1,1000);
#endif
    LCD_DC_Set;//写数据

}

15、这样我们就把低层的三个数据接口指令全部写好了,在LCD的移植中,我们只需要重写这几个代码就行了。

16、为了适配软件摸拟SPI以及CS、REST的指令可读性,我这里用宏定义来定义了以下代码:

#define RES_PIN  GPIO_PIN_2
#define DC_PIN   GPIO_PIN_0
#define BLK_PIN  GPIO_PIN_0

#define CS_PIN   GPIO_PIN_4

#define SCK_PIN  GPIO_PIN_1
#define SDA_PIN  GPIO_PIN_7

#define SCK_PORT GPIOA
#define SDA_PORT GPIOA

#define CS_PORT     GPIOA
#define DC_PORT     GPIOA
#define RES_PORT    GPIOA
#define BLK_PORT    GPIOB


//-----------------LCD端口定义----------------

#define LCD_CS_Clr   CS_PORT->BRR = (uint32_t)CS_PIN;
#define LCD_CS_Set   CS_PORT->BSRR = (uint32_t)CS_PIN;

#define LCD_RES_Clr  RES_PORT->BRR = (uint32_t)RES_PIN;
#define LCD_RES_Set  RES_PORT->BSRR = (uint32_t)RES_PIN;

#define LCD_DC_Clr   DC_PORT->BRR = (uint32_t)DC_PIN;
#define LCD_DC_Set   DC_PORT->BSRR = (uint32_t)DC_PIN;

#define LCD_BLK_Clr  BLK_PORT->BRR = (uint32_t)BLK_PIN;
#define LCD_BLK_Set  BLK_PORT->BSRR = (uint32_t)BLK_PIN;

#define LCD_SCLK_LOW() SCK_PORT->BRR = (uint32_t)SCK_PIN;
#define LCD_SCLK_HIGH() SCK_PORT->BSRR = (uint32_t)SCK_PIN;

#define LCD_MOSI_LOW() SDA_PORT->BRR = (uint32_t)SDA_PIN;
#define LCD_MOSI_HIGH() SDA_PORT->BSRR = (uint32_t)SDA_PIN;

这样我们就可以,查看有标识意义的代码部分。

17、定义屏的长与宽,我们在.h定义如下:

#define LCD_W 240
#define LCD_H 320

18、其他的代码我打包放在附件中,大家可以自行查看,到此,代码移植就完成了。

【测试】

我们在main.c中引入lcd的头文件,并书写main.c的测试代码如下:

  IVO28_GC9306_P4();

  LCD_Fill(0,0,239,319,BLACK);
  HAL_Delay(200);
  LCD_Fill(0,0,239,319,0xFFFF);
  LCD_ShowChinese(10,10,"电压监测系统",BLUE,WHITE,32,0);//显示汉字�?

下载后效果如图:

83dc8f38059f537e59d4f4e8d1f5075.jpg

【SPI的总结速度的测试】

测试工具:LA2016逻辑分析仪,可以测试16路最高200M速度。

1、软件的总线通迅速:

image.png

2、SPI为32分频时的总线速度

image.png

![image.png](

"image.png")

3、分频为16时的速:

image.png

image.png

4、分频为8分频时:

image.png

image.png

5、分频为4时:

image.png

image.png

737186a11debbe3bac55176d3a97417.jpg

用逻辑分析仪是测得是40M,用示波器测是41.7MHz。

6、分频为2时,图像是可以正常显示的,但是因为我的逻辑分析仪的带宽,没有捕捉到正确的波形。

image.png

image.png

改用示波器捕获SCK时钟信号,测得为75.7Mhz。

b7e89622e2973fe50d5409bb9ff6e89.jpg

【总结】

从上面的测试可以看到,SPI的时钟与实际配置的是一样的,波形也非常的正常,可以说这款芯是非常之稳定。

经过上述的测试,可以说STM32U545的SPI总线最高可以跑到80M。我在测试另一款芯片(150M)频率,跑到40M时,同样的LCD屏就不能正常显示了。

同时STM32CubeIDE也提供了非常优秀的开发环境,在图形化配置工具中我们可以实际的看到一些配置好后的参数。使用开发板进行开发时,选择对应的开发板,可以默认的把开发板的外设全部配置好,后期我们只需要进行少量的配置就可以新建开发环境。

image.png
收藏 评论3 发布时间:2023-11-22 08:27

举报

3个回答
lugl 回答时间:2023-11-22 08:30:08
image.png 0 }$ o* q2 w# O7 R) {  }
$ o7 o0 S* V3 X4 v/ ?: t. @
u545_tft.zip (1.59 MB, 下载次数: 0)
h12121 回答时间:2023-12-11 18:06:26

LCD的刷新速度咋样

lugl 回答时间:2023-12-12 08:33:38

h12121 发表于 2023-12-11 18:06
LCD的刷新速度咋样

不是很高,主要受制于显存,如果要想速高,选U5A9或者U599J,这样有专用的LCD驱动。

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版