STM32F407HAL库模拟SPI驱动1.8寸TFT(ST7735)屏幕

        找了好久没找到能用的,就自己移植HAL库,现在分享一下

        最近屏幕涨价不少,为了图便宜就在某宝花了23买了一块1.8寸无触摸TFT(ST7735)的屏幕,买回来后发现跟其他的有些许不太一样,网上没看见相关参考,仅有几个店家给的例程,但是例程里面的针脚定义跟我拿到手的也不一样,没办法控制背光,我拿到的就是下面这块屏幕

 可以看到仅有CLK、SDA(MOSI)、RS、RST、CS五个有效引脚,少了控制背光LED引脚的,但是这并不是大问题,因为项目其他功能都是使用HAL库开发,所以就只能把STM32F103固件库的驱动例程自己改一下移植到STM32F407HAL库上。


目录

硬件平台

 接线方式

STM32CubeMX配置

代码部分

运行效果

取模部分


硬件平台

 本次使用的硬件平台是STM32F407VET6核心板

软件则用的是 Keil5.35 和 STM32CubeMX


 接线方式

  •  VCC              3.3V(5V容易烧坏屏幕)
  • GND               GND
  • GND               GND
  • NC                  悬空
  • NC                  悬空
  • NC                  悬空
  • CLK                PD0
  • SDA/MOSI      PD1
  • RS/DC            PD2
  • RST/RES        PD3
  • CS/CE             PD4

STM32CubeMX配置

第一步选择芯片:

 然后找到你开发板上的芯片型号(我推荐是把自己开发板上的芯片型号点哪个星星收藏一下,下次直接点搜索框旁边的收藏夹就能直接选择了)

 第二步开启调试(防止芯片锁住)并配置IO口

 选择使用外部高速时钟HSE

 配置IO

后面的四个配置方式一样无上下拉,推挽输出,并把IO速率开到最高very high(为了屏幕刷新快一点 )

 

第三步配置时钟

因为板子上带的是8M的晶振所以需要改一下,cubemx默认25M晶振 

 第四步设置工程配置

 

 最后一步生成代码

先生成报告,得到一个cubemx的ioc文件等后续还可以继续配置

接着点右上角生成代码(生成代码的路径不能存在中文,否则生成代码会失败)

 

 生成成功后直接点击打开工程

 打开工程后配置一下下载

 接着选择pack取消掉(防止下载后不会复位运行)

完成之后先编译一遍工程

 

 然后回到工程目录创建一文件用来装移植过来的程序

打开里面放移植的程序

 

回到keil接着点这个

 接着新建一个

 选中新键的往里面添加文件

找到刚刚移植过来的C文件添加进去再点ok

 

 接着添加头文件目录

 

 接着新建一个路径,点旁边序号选择头文件路径

 

 然后点ok

到这里大部分移植过程已经完成了,接下来就是改代码


代码部分

Lcd_Driver.h(部分代码)

#include "stm32f4xx_hal.h"
#include "stm32f407xx.h"

#define RED  	0xf800
#define GREEN	0x07e0
#define BLUE 	0x001f
#define WHITE	0xffff
#define BLACK	0x0000
#define YELLOW  0xFFE0
#define GRAY0   0xEF7D   	//灰色0 3165 00110 001011 00101
#define GRAY1   0x8410      	//灰色1      00000 000000 00000
#define GRAY2   0x4208      	//灰色2  1111111111011111




#define LCD_CTRL   	  	GPIOD		//定义TFT数据端口
#define LCD_RS         	GPIO_PIN_2	//TFT --RS/DC
#define LCD_CS        	GPIO_PIN_4  //TFT --CS/CE
#define LCD_RST     		GPIO_PIN_3	//TFT --RST
#define LCD_SCL        	GPIO_PIN_0	//TFT --SCL/SCK
#define LCD_SDA        	GPIO_PIN_1	//TFT --SDA/DIN



#define	LCD_CS_SET  	LCD_CTRL->BSRR=LCD_CS    
#define	LCD_RS_SET  	LCD_CTRL->BSRR=LCD_RS    
#define	LCD_SDA_SET  	LCD_CTRL->BSRR=LCD_SDA    
#define	LCD_SCL_SET  	LCD_CTRL->BSRR=LCD_SCL    
#define	LCD_RST_SET  	LCD_CTRL->BSRR=LCD_RST    
#define	LCD_LED_SET  	LCD_CTRL->BSRR=LCD_LED 




void LCD_GPIO_Init(void);
void Lcd_WriteIndex(uint8_t Index);
void Lcd_WriteData(uint8_t Data);
void Lcd_WriteReg(uint8_t Index,uint8_t Data);
uint16_t Lcd_ReadReg(uint8_t LCD_Reg);
void Lcd_Reset(void);
void Lcd_Init();
void Lcd_Clear(uint16_t Color);
void Lcd_SetXY(uint16_t x,uint16_t y);
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data);
unsigned int Lcd_ReadPoint(uint16_t x,uint16_t y);

Lcd_Driver.c(部分代码)

/******************************************************************************
接口定义在Lcd_Driver.h内
#define LCD_CTRL   	  	GPIOD		
#define LCD_SCL        	GPIO_Pin_0	//SCL/SCK
#define LCD_SDA        	GPIO_Pin_1	//SDA/DIN
#define LCD_RS         	GPIO_Pin_2	//RS/DC
#define LCD_RST     	GPIO_Pin_3	//RST
#define LCD_CS        	GPIO_Pin_4  //CS/CE
*******************************************************************************/
void LCD_GPIO_Init(void)
{

	GPIO_InitTypeDef GPIO_InitStruct = {0};
	      
	 __HAL_RCC_GPIOD_CLK_ENABLE();
	
	GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
                          |GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
      
}


/****************************************************************************
* 名    称:Lcd_WriteIndex(uint8_t Index)
* 功    能:写 ST7735 控制器寄存器地址
* 入口参数:Index   寄存器地址
* 出口参数:无
* 说    明:调用前需先选中控制器,内部函数
* 调用方法:Lcd_WriteIndex(0xB1);
****************************************************************************/
void Lcd_WriteIndex(uint8_t Index)
{
   uint8_t i=0;
   //SPI 写命令时序开始
   LCD_CS_CLR;
   LCD_RS_CLR;

   for(i=8;i>0;i--)
   {
    if(Index&0x80){	
	  LCD_SDA_SET; }//输出数据
    else 
	  LCD_SDA_CLR; 

      LCD_SCL_CLR;      
      LCD_SCL_SET;
      Index<<=1; 
   }
   LCD_CS_SET;
}

/****************************************************************************
* 名    称:void Lcd_WriteData(uint8_t Data)
* 功    能:写 ST7735 寄存器数据
* 入口参数:Data     寄存器数据
* 出口参数:无
* 说    明:向控制器指定地址写入数据,调用前需先写寄存器地址,内部函数
* 调用方法:Lcd_WriteData(0x01);
****************************************************************************/
void Lcd_WriteData(uint8_t Data)
{
   uint8_t i=0;
   LCD_CS_CLR;
   LCD_RS_SET;

   for(i=8;i>0;i--)
   {
      if(Data&0x80)	{
	  LCD_SDA_SET;} //输出数据
      else LCD_SDA_CLR;
	   
      LCD_SCL_CLR;       
      LCD_SCL_SET;
      Data<<=1; 
   }
   LCD_CS_SET; 
}

/*************************************************
函数名:Lcd_WriteReg
功能:写寄存器
入口参数:Index,Data
返回值:无
*************************************************/
void Lcd_WriteReg(uint8_t Index,uint8_t Data)
{
	Lcd_WriteIndex(Index);
   	Lcd_WriteData(Data);
}

/*************************************************
函数名:Lcd_Reset
功能:重置LCD
入口参数:无
返回值:无
*************************************************/
void Lcd_Reset(void)
{
	LCD_RST_CLR;
	HAL_Delay(100);
	LCD_RST_SET;
	HAL_Delay(50);
}


/*************************************************
函数名:Lcd_SetRegion
功能:设置lcd显示区域,在此区域写点数据自动换行
入口参数:x_start起点,y_start起点,x_end,y_end终点
返回值:无
*************************************************/
void Lcd_SetRegion(uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end)
{		
	Lcd_WriteIndex(0x2a);
	Lcd_WriteData(0x00);
	Lcd_WriteData(x_start);
	Lcd_WriteData(0x00);
	Lcd_WriteData(x_end);

	Lcd_WriteIndex(0x2b);
	Lcd_WriteData(0x00);
	Lcd_WriteData(y_start);
	Lcd_WriteData(0x00);
	Lcd_WriteData(y_end);

	Lcd_WriteIndex(0x2c);

}

/*************************************************
函数名:Lcd_SetXY
功能:设置lcd显示起始点
入口参数:xy坐标
返回值:无
*************************************************/
void Lcd_SetXY(uint16_t x,uint16_t y)
{
  	Lcd_SetRegion(x,y,x,y);
}

	
/*************************************************
函数名:Gui_DrawPoint
功能:画一个点
入口参数:x,y,Data
返回值:无
*************************************************/
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data)
{
	Lcd_SetRegion(x,y,x+1,y+1);
	Lcd_WriteData(Data>>8);
	Lcd_WriteData(Data);

}    

/*****************************************
函数名:Lcd_ReadPoint
函数功能:读TFT某一点的颜色                          
出口参数:Data  点颜色值                                 
******************************************/
unsigned int Lcd_ReadPoint(uint16_t x,uint16_t y)
{
  unsigned int Data;
  Lcd_SetXY(x,y);

  //Lcd_ReadData();//丢掉无用字节
  //Data=Lcd_ReadData();
  Lcd_WriteData(Data);
  return Data;
}
/*************************************************
函数名:Lcd_Clear
功能:全屏清屏函数
入口参数:填充颜色Color
返回值:无
*************************************************/
void Lcd_Clear(uint16_t Color)               
{	
   unsigned int i,m;
   Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);
   Lcd_WriteIndex(0x2C);
   for(i=0;i<128;i++)
    for(m=0;m<160;m++)
    {	
	  	Lcd_WriteData(Color>>8);
			Lcd_WriteData(Color);
    }   
}

上面值得注意的是F103的BSRR置位寄存器和BRR复位寄存器在F407中都已经变成


如果屏幕边上有花屏,表示像素没填充够,修改Lcd_Driver.c和GUI.c内循环体数值即可

而整个屏幕图形显示函数的编写实现实际上就是点亮对应坐标像素并显示颜色


 好了到这里全部工作就已经全部完成,烧录看一下效果。


运行效果

 可以看见屏幕刷新率还是蛮快的,得益于STM32F407IO速率的提升

而F103则相对慢一些


取模部分

图片取模

 文字取模


 当然了STM32F103C8T6HAL库也移植有,如果有需要在评论留言。

代码我已经上传,有积分的好兄弟给点,不做伸手党

完整代码

  • 39
    点赞
  • 126
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 75
    评论
你好,我可以回答这个问题。以下是使用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) { } } 希望这个代码示例对你有所帮助。
评论 75
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fbuilke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值