使用STM32 HAL库驱动1.8寸TFT-LCD屏幕的硬件SPI(软件SPI)方法详解

stm32hal库硬件spi(软件spi)驱动1.8寸tft—lcd屏幕

  • 前言
  • 环境搭建
  • 一、stm32软件spi驱动lcd
  • 1 cubemx配置
  • 2 代码移植
  • 1)lcd.c
  • 2)spi.c
  • 3)gui.c
  • 4)test.c
  • 5)验证
  • 3 屏幕背光亮度调节
  • 二、stm32硬件spi驱动lcd
  • 1 cubemx配置
  • 2 代码修改
  • 3 速度测试
  • 三、提高屏幕刷新率
  • 总结

  • 前言

    屏幕是嵌入式开发中的一个重要的部分,cdsn上有许多解释原理的,还有很多是采用正点原子的屏幕来驱动的,对于刚刚入门不久的我们可能没有资金去购买较为昂贵的屏幕。而对于底层原理我们暂时也不必了解的那么深入,能点亮屏幕就是我们最大的快乐。
    除了中景园的资料全一些以外,没有啥更好的驱动了! 嘛?
    无意中找到了一个很不错的网站,他们的代码和中景园相似但又有所不同,毕竟科技以换壳为本嘛!所以本篇拙笔就是记录如何将代码移植到stm32上。
    官网地址:官网地址
    在官网中可下载相应的代码,我在每节的链接中会贴出移植好的代码。


    环境搭建

    cubemx、keil5、tft_lcd屏幕(spi接口)、stm32开发板、

    一、stm32软件spi驱动lcd

    链接:百度网盘——my
    提取码:fnov

    1 cubemx配置


    cubemx配置如上图所示,记得一定要改名字,不然每次都要修改lcd的源码会很麻烦,名字就写图中的就可以了。(这个还不知道是什么的需要补习一下cubemx了后续会出一期期cubemx的基础使用

    2 代码移植

    将官网中的文件下载下来以后继续解压,
    这个链接里面有官网的文件
    链接:百度网盘
    提取码:2eq4

    打开这个目录下的代码并在自己创建的工程下创建一个user文件夹。
    在user文件夹下创建需要的.h .c文件

    1)lcd.c

    上面的大段注释就不需要了,直接把下面的代码加入就可以了,再把lcd.h加入
    这个时候要根据叉叉和感叹号去修改代码
    第一步
    删除#include “delay.h”
    删除void LCD_Init(void)中的LCD_GPIOInit();//LCD GPIO初始化 这句代码,因为cube已经帮我们初始化过了不需要初始化了。
    delay_ms改成hal_delay;因为标准库中没有带延时而hal库中有,我们直接用hal库的就可以了。
    第二步
    #include “sys.h”改成#include “main.h”

    并在下面加一下
    #define u8 uint8_t
    #define u16 uint16_t
    因为hal库中没有u8 和u 16,所以需要宏定义一下。

    第三步
    删除lcd端口定义,因为cube引脚帮我们配置好了,不需要这个了

    修改引脚电平的跳变,这一步是很重要的
    这里我们修改为:

    这里并没有调用hal_gpio_write()因为直接操纵寄存器的话会快很多。

    lcd.h就自己写了,这个也很简单,实在不会就对照我的【百度网盘——my】中的文件抄写一下,后面基本都是只介绍.c库的修改

    2)spi.c

    在这里直接移植过去就可以了不需要继续更改(可以把头部注释都删除)

    在spi.h文件中我们修改宏定义如图:

    这一步是修改模拟spi信号的跳变的。

    3)gui.c

    第一步:
    删除#include "delay.h"
    第二步:
    在gui.h中写:

    #include "main.h"
    #define u8 uint8_t
    #define u16 uint16_t
    #define u32 uint32_t
    

    第三步:
    移植font.h文件,这里是不需要修改的

    4)test.c

    第一步:
    删除#include "delay.h"
    #include "touch.h"
    #include "key.h"
    #include "led.h"
    以及最下面的void Touch_Test(void)函数
    第二步:
    移植test.h文件
    并写入:

    #include "main.h"
    #define u8 uint8_t
    

    5)验证


    在主函数中写这些即可。

    3 屏幕背光亮度调节

    背光的原理就不介绍了,我们的lcd会有一个BL引脚,这样引脚就是调节背光的,即调节屏幕亮度,这个引脚我们一般设置为3.3v即为正常亮度,当想让他暗一些的时候就需要对这个引脚pwm输出,通过控制占空比来调节亮度,高电平占比越多,屏幕越亮。

    二、stm32硬件spi驱动lcd

    硬件spi要比软件模拟的spi快很多,在本次有一个test_time函数,用软件和硬件分别跑,硬件所需的时间仅仅是软件的一半。

    链接:硬件spi_my
    提取码:6ikf

    1 cubemx配置



    并不需要要重新创建文件,只需要将上一份的文件复制粘贴以后进cubemx继续修改就可以了。
    模式选择为只做主机发送。随后生成代码即可。

    2 代码修改

    本次我们只需要修改spi.c和spi.h即可,首先就是把user文件夹下的这两个文件改名为my_user.hmy_user.c因为本来名字会和cubemx生成的文件重名。

    把my_user.c中的删除掉,添加下面代码:

    #include "my_spi.h"
    #include "spi.h"
    
    /*****************************************************************************
     * @name       :u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte)
     * @date       :2018-08-09 
     * @function   :Write a byte of data using STM32's hardware SPI
     * @parameters :SPIx: SPI type,x for 1,2,3
                    Byte:Data to be written
     * @retvalue   :Data received by the bus
    ******************************************************************************/
    u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte)
    {
    	while((SPIx->SR&SPI_FLAG_TXE)==RESET);		//等待发送区空	  
    	SPIx->DR=Byte;	 	//发送一个byte   
    	while((SPIx->SR&SPI_FLAG_RXNE)==RESET);//等待接收完一个byte  
    	return SPIx->DR;          	     //返回收到的数据			
    } 
    //u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte)
    //{
    //	HAL_SPI_Transmit(&hspi1,&Byte,1,10);
    //	return SPIx->DR;          	     //返回收到的数据			
    //} 
    
    
    /*****************************************************************************
     * @name       :void SPI_SetSpeed(SPI_TypeDef* SPIx,u8 SpeedSet)
     * @date       :2018-08-09 
     * @function   :Set hardware SPI Speed
     * @parameters :SPIx: SPI type,x for 1,2,3
                    SpeedSet:0-high speed
    												 1-low speed
     * @retvalue   :None
    ******************************************************************************/
    void SPI_SetSpeed(SPI_TypeDef* SPIx,u8 SpeedSet)
    {
    	SPIx->CR1&=0XFFC7;
    	if(SpeedSet==1)//高速
    	{
    		SPIx->CR1|=SPI_BAUDRATEPRESCALER_2;//Fsck=Fpclk/2	
    	}
    	else//低速
    	{
    		SPIx->CR1|=SPI_BAUDRATEPRESCALER_32; //Fsck=Fpclk/32
    	}
    	SPIx->CR1|=1<<6; //SPI设备使能
    } 
    
    /*****************************************************************************
     * @name       :void SPI2_Init(void)	
     * @date       :2018-08-09 
     * @function   :Initialize the STM32 hardware SPI2
     * @parameters :None
     * @retvalue   :None
    ******************************************************************************/
    void SPI_Init(void)	
    {
    	__HAL_SPI_ENABLE(&hspi1);//这句话很重要
    }
    
    

    在my_spi.h中写:

    #include "main.h"
    
    #ifndef _SPI_H_
    #define _SPI_H_
    
    #define u8 uint8_t
     
    u8 SPI_WriteByte(SPI_TypeDef* SPIx,u8 Byte);
    void SPI_Init(void);
    void SPI_SetSpeed(SPI_TypeDef* SPIx,u8 SpeedSet);
    
    #endif
    
    

    再把lcd.c中的打叉的地方改为SPI_WriteByte(SPI1,…….)红色的省略号就是填写本来那里填的数据。

    这样就完成了,直接烧录即可。

    3 速度测试

    分别在软件和硬件的test.c文件的末尾写上:

    void test_time(void)
    {
    	
    	LCD_Fill(0,0,lcddev.width,lcddev.height,WHITE);
    	Show_Str(20,30,BLUE,YELLOW,"BL Test",16,1);HAL_Delay(1);
    	LCD_Fill(0,0,lcddev.width,lcddev.height,RED);
    	Show_Str(20,30,BLUE,YELLOW,"RED ",16,1);HAL_Delay(1);
    	LCD_Fill(0,0,lcddev.width,lcddev.height,GREEN);
    	Show_Str(20,30,BLUE,YELLOW,"GREEN ",16,1);HAL_Delay(1);
    	LCD_Fill(0,0,lcddev.width,lcddev.height,BLUE);
    	Show_Str(20,30,RED,YELLOW,"BLUE ",16,1);HAL_Delay(1);	
    }
    

    并把主函数中的原有测试代码注释,写成如图:

    当复位键按下以后开始计时,在我的板子上,硬件spi跑完只需要14秒,即屏幕的刷新率可以达到30fps,而使用软件的话只能达到10多fps。由此可见硬件spi是很不错的选择。

    三、提高屏幕刷新率

    在tft_lcd的屏幕下,我们对于屏幕呈像素质的关注是比较少的,我们主要是希望屏幕有较快的相应速度,使用我们在上两节分别使用了软件spi和硬件spi。在硬件spi中我们参考的是标准库,移植到的是hal库,其中不难发现我们在使用写数据函数的时候,使用到的都是寄存器方法,而没有使用标准库以及hal库提供的库函数。为什么留着方便的库函数不用而才用寄存器呢?
    其实当你F12库函数你就能发现,库函数中存积着大量的代码,有些代码是为了检查通信协议的。我们在追求速度的时候总要舍弃些什么,毕竟有舍才有得嘛!

    在标准库中代码是这样的

    而在我们移植的hal库中,我们用了差不多的函数:

    细心的你可能已经发现了,只是标志少了几个字母而已。
    其实我们可以很简洁的写出这个代码:

    一句话就可以解决,但是当你使用这个函数驱动屏幕刷新的时候你会发现你只能眨眼补帧,这实在是太慢了,慢到速度还比不过软件spi。那有没有方法在hal库的spi中寻找一个速度也比较快,且合适的代码呢?
    这只能通过缩减hal_spi_transmit();函数了,暂时还没想好

    总结

    以上就是今天要讲的内容,本文仅仅简单介绍了如何移植到hal库,当你点亮屏幕的那一刻所以的坑都是值得的。
    相逢何必曾相识,江湖再见!!

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用STM32 HAL库驱动1.8寸TFT-LCD屏幕的硬件SPI(软件SPI)方法详解

    发表回复