使用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;

如圖,成功驅動屏幕。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM