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

【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 * h4 t$ S% k0 x0 _% E* v
7 F9 n3 @0 J2 y  H! C0 x
u545_tft.zip (1.59 MB, 下载次数: 8)
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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版