使用STM32 HAL库 驱动ST7789 显示屏

使用STM32 HAL库 驱动ST7789 显示屏

这是驱动好的效果图,我买的是中景园电子的一块IPS显示屏, 它的像素密度很高,显示非常细腻。

今天我用stm32 HAL库来驱动它。

使用STM32CubeMX生成代码

使用STM32CubeMX 生成功能, 其中主要设置了SPI和 驱动引脚

主要代码所示:

//引脚设置
#define LCD_D0_SCL_Pin GPIO_PIN_5
#define LCD_D0_SCL_GPIO_Port GPIOA
#define LCD_D1_SDA_Pin GPIO_PIN_7
#define LCD_D1_SDA_GPIO_Port GPIOA
#define LCD_RES_Pin GPIO_PIN_0
#define LCD_RES_GPIO_Port GPIOB
#define LCD_DC_Pin GPIO_PIN_1
#define LCD_DC_GPIO_Port GPIOB
#define LCD_CS_Pin GPIO_PIN_10
#define LCD_CS_GPIO_Port GPIOB
/* SPI1 init function */
static void MX_SPI1_Init(void)
{

  /* SPI1 parameter configuration*/
  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_4;	//SPI时钟,使用72M主频,4分频
  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(__FILE__, __LINE__);
  }

}
/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LCD_RES_Pin|LCD_DC_Pin|LCD_CS_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : LCD_RES_Pin LCD_DC_Pin LCD_CS_Pin */
  GPIO_InitStruct.Pin = LCD_RES_Pin|LCD_DC_Pin|LCD_CS_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hspi->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
  
    /**SPI1 GPIO Configuration    
    PA5     ------> SPI1_SCK
    PA7     ------> SPI1_MOSI 
    */
    GPIO_InitStruct.Pin = LCD_D0_SCL_Pin|LCD_D1_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }

}

移植官方例程

中景园官方给的资料全是使用标准库的,很无奈, 不过看了一下,改动应该非常简单。

首先是改动驱动包里面的lcd.c文件:

#include "lcd.h"
#include "oledfont.h"
#include "delay.h"
#include "bmp.h"
u16 BACK_COLOR;   //背景色


/******************************************************************************
      函数说明:LCD串行数据写入函数
      入口数据:dat  要写入的串行数据
      返回值:  无
******************************************************************************/
void LCD_Writ_Bus(u8 dat) 
{	
	u8 i;			  
	OLED_CS_Clr();
	for(i=0;i<8;i++)
	{			  
		OLED_SCLK_Clr();
		if(dat&0x80)
		   OLED_SDIN_Set();
		else 
		   OLED_SDIN_Clr();
		OLED_SCLK_Set();
		dat<<=1;   
	}			
	OLED_CS_Set();
}
/*把上面的函数改成下面这种, 因为中景园给的例程是使用模拟spi的时序的,刷新非常慢, 
我们改成如下这种,在使用的时候要事先初始化单片机SPI模块*/
void LCD_Writ_Bus(u8 dat) 
{	
	u8 i;
	OLED_CS_Clr();
	
	HAL_SPI_Transmit(&hspi1, &dat, 1, 0xffff);
  OLED_CS_Set();	
}

再改动lcd.h文件:

//-----------------OLED端口定义---------------- 

#define OLED_SCLK_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_5)
#define OLED_SCLK_Set() GPIO_SetBits(GPIOA,GPIO_Pin_5)

#define OLED_SDIN_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_7)//DIN
#define OLED_SDIN_Set() GPIO_SetBits(GPIOA,GPIO_Pin_7)

#define OLED_RST_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_0)//RES
#define OLED_RST_Set() GPIO_SetBits(GPIOB,GPIO_Pin_0)

#define OLED_DC_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_1)//DC
#define OLED_DC_Set() GPIO_SetBits(GPIOB,GPIO_Pin_1)
 		     
#define OLED_CS_Clr()  GPIO_ResetBits(GPIOA,GPIO_Pin_4)//CS
#define OLED_CS_Set()  GPIO_SetBits(GPIOA,GPIO_Pin_4)
 		     
#define OLED_BLK_Clr()  GPIO_ResetBits(GPIOB,GPIO_Pin_10)//BLK
#define OLED_BLK_Set()  GPIO_SetBits(GPIOB,GPIO_Pin_10)

/*上面是原来例程里面的程序,我改成下面这种的, 因为已经使用了硬件SPI ,所以去掉了时钟线与数据线的设置,
其他的仍保留,使用固件库HAL_GPIO_WritePin() 函数来设置引脚电平*/
//-----------------OLED端口定义---------------- 

#define OLED_RES_Clr() HAL_GPIO_WritePin(LCD_RES_GPIO_Port, LCD_RES_Pin, GPIO_PIN_RESET)//RES
#define OLED_RES_Set() HAL_GPIO_WritePin(LCD_RES_GPIO_Port, LCD_RES_Pin, GPIO_PIN_SET)

#define OLED_DC_Clr() HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET)//DC
#define OLED_DC_Set() HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET)
 		     
#define OLED_CS_Clr()  HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET)///CS
#define OLED_CS_Set()  HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET)

// #define OLED_BLK_Clr()  HAL_GPIO_WritePin(, LCD_DC_Pin, GPIO_PIN_RESET)///BLK
// #define OLED_BLK_Set()  HAL_GPIO_WritePin(, LCD_DC_Pin, GPIO_PIN_SET)

接着,再把初始化函数里面的引脚初始化部分注释掉,也把里面的延时函数更改成HAL库的:

至此,程序移植已经可以了,在main里面执行初始化屏幕的函数就可以了。

/*=================IPS显示屏初始化=============*/
	Lcd_Init();
	LCD_Clear(GREEN);
	BACK_COLOR = GREEN;

如图,成功驱动屏幕。

原文地址:https://www.cnblogs.com/Gentleaves/p/11311836.html