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

1 篇文章 0 订阅


前言

屏幕是嵌入式开发中的一个重要的部分,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();函数了,暂时还没想好

四、中文显示

1打开取模软件
在这里插入图片描述

2左上角模式选择为字符模式 在这里插入图片描述

3点击选项 在这里插入图片描述

4设置如下,然后点击确定。
在这里插入图片描述

5以16x16汉字取模为例:在这里插入图片描述

字宽字高都改为16
然后在输入栏输入汉字在这里插入图片描述

点击生成字模在这里插入图片描述
生成的字模如下

在这里插入图片描述

然后将字模复制到例程lcdfont.h文件夹 如下数组内
注:每个字的字模前需要添加这个汉字,并用双引号括起来然后加上逗号!
在这里插入图片描述

总结

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

你好,我可以回答这个问题。以下是使用HAL库编写1.8TFT屏幕驱动的代码示例: #include "stm32f4xx_hal.h" #include "stm32f4xx_hal_gpio.h" #include "stm32f4xx_hal_spi.h" #define TFT_DC_Pin GPIO_PIN_12 #define TFT_DC_GPIO_Port GPIOB #define TFT_CS_Pin GPIO_PIN_13 #define TFT_CS_GPIO_Port GPIOB #define TFT_RST_Pin GPIO_PIN_14 #define TFT_RST_GPIO_Port GPIOB SPI_HandleTypeDef hspi1; void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } } void TFT_Write_Command(uint8_t cmd) { HAL_GPIO_WritePin(TFT_DC_GPIO_Port, TFT_DC_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, 100); } void TFT_Write_Data(uint8_t data) { HAL_GPIO_WritePin(TFT_DC_GPIO_Port, TFT_DC_Pin, GPIO_PIN_SET); HAL_SPI_Transmit(&hspi1, &data, 1, 100); } void TFT_Reset() { HAL_GPIO_WritePin(TFT_RST_GPIO_Port, TFT_RST_Pin, GPIO_PIN_RESET); HAL_Delay(10); HAL_GPIO_WritePin(TFT_RST_GPIO_Port, TFT_RST_Pin, GPIO_PIN_SET); HAL_Delay(10); } void TFT_Init() { TFT_Reset(); TFT_Write_Command(x01); //Software reset HAL_Delay(100); TFT_Write_Command(x11); //Sleep out HAL_Delay(100); TFT_Write_Command(x3A); //Interface pixel format TFT_Write_Data(x05); //16 bits per pixel TFT_Write_Command(x36); //Memory data access control TFT_Write_Data(x08); //BGR order TFT_Write_Command(x29); //Display on } void TFT_Set_Address_Window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { TFT_Write_Command(x2A); //Column address set TFT_Write_Data(x1 >> 8); TFT_Write_Data(x1 & xFF); TFT_Write_Data(x2 >> 8); TFT_Write_Data(x2 & xFF); TFT_Write_Command(x2B); //Row address set TFT_Write_Data(y1 >> 8); TFT_Write_Data(y1 & xFF); TFT_Write_Data(y2 >> 8); TFT_Write_Data(y2 & xFF); TFT_Write_Command(x2C); //Memory write } void TFT_Fill_Color(uint16_t color) { uint32_t i; TFT_Set_Address_Window(, , 127, 159); for (i = ; i < 20480; i++) { TFT_Write_Data(color >> 8); TFT_Write_Data(color & xFF); } } int main(void) { HAL_Init(); MX_SPI1_Init(); TFT_Init(); TFT_Fill_Color(xF800); //Fill screen with red color while (1) { } } 希望这个代码示例对你有所帮助。
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值