Skip to main content
USolar
Associate III
July 12, 2026
Question

STM32F767ZI + ILI9486 (Waveshare 4.0" Shield SKU13587) - Random pixels appear when drawing filled rectangles over SPI

  • July 12, 2026
  • 0 replies
  • 14 views

Hello everyone,

I'm trying to interface a Waveshare 4.0" TFT Touch Shield (SKU13587) with an ILI9486 LCD controller using an STM32F767ZI.

The display communicates over SPI, and the SPI bus is shared with the XPT2046 touch controller. At this stage I am testing only the LCD. The touchscreen is completely disabled and is not accessed by the software.

Hardware

  • MCU: STM32F767ZI
  • Display: Waveshare 4.0" TFT Touch Shield (SKU13587)
  • LCD Controller: ILI9486
  • Touch Controller: XPT2046 (not used during testing)
  • Interface: SPI

     

Current status

I wrote my own low-level ILI9486 driver.

The following basic operations work correctly:

  • LCD initialization
  • Setting an address window
  • Writing commands
  • Writing data
  • Drawing a single pixel

A single pixel is always drawn at the correct position.

Problem

The problem appears only when I draw a filled rectangle (or any larger filled area).

The rectangle itself is drawn correctly, but additional unwanted pixels appear beside the rectangle.

The artifacts have some interesting characteristics:

  • They always appear at specific X coordinates.
  • Their Y position never exceeds the height of the rectangle being drawn.
  • The larger the filled area, the more visible the artifacts become.
  • Single-pixel drawing never produces these artifacts.

I've attached pictures showing the problem.

What I have already checked

  • Address window (0x2A / 0x2B)
  • Memory Write command (0x2C)
  • Pixel format
  • MADCTL settings
  • SPI transmit routines
  • CS/DC timing
  • Display initialization sequence

Everything appears to be correct, since individual pixels are written perfectly.

My suspicion

Since single-pixel drawing works correctly, I suspect the issue is somewhere in one of these areas:

  • SPI data transmission during continuous pixel streaming
  • Address window programming
  • Loop that sends RGB565 pixel data
  • Number of transmitted bytes
  • Off-by-one error in width/height calculations
  • Incorrect handling of CS during long transfers
  • HAL_SPI_Transmit usage
  • ILI9486 auto-increment behavior

Questions

Has anyone experienced similar behavior with an ILI9486?

Could this be caused by:

  • an incorrect address window,
  • a timing issue,
  • SPI transmit routine,
  • cache/DMA problem,
  • compiler optimization,
  • or a known ILI9486 peculiarity?

I would greatly appreciate any suggestions or ideas.

Thank you very much for your time.

/*
* ili9486.c
*
*/

#include "ili9486.h"
#include "main.h" // Hardware setting
#include <stdbool.h>

// This function is for compatible HiLetgo ILI9486
// Inline Macros to control GPIO control pins fast



typedef enum {
ROTATE_0,
ROTATE_90,
ROTATE_180,
ROTATE_270
} LCD_Horizontal_t;

extern void Error_Handler(void);
extern SPI_HandleTypeDef hspi1;
volatile bool spi_dma_busy = false;

static void ILI9486_Reset(void);
void ILI9486_Init(LCD_SCAN_DIR LCD_ScanDir);
void ILI9486_WriteCommand_NoCS(uint8_t cmd);
void ILI9486_WriteData_NoCS(uint8_t data);
void ILI9486_WriteCommand(uint8_t cmd);
void ILI9486_WriteData(uint8_t data);
static void ILI9486_InitReg(void);
void ILI9486_SetGramScanWay(LCD_SCAN_DIR Scan_dir);
void ILI9486_SetWindow(POINT Xstart, POINT Ystart, POINT Xend, POINT Yend);
void ILI9486_SetCursor(POINT Xpoint, POINT Ypoint);
void ILI9486_SetColor(COLOR Color , POINT Xpoint, POINT Ypoint);
void ILI9486_SetPointlColor( POINT Xpoint, POINT Ypoint, COLOR Color);
void ILI9486_SetArealColor(POINT Xstart, POINT Ystart, POINT Xend, POINT Yend, COLOR Color);
void ILI9486_ClearScreen(COLOR Color);

static HAL_StatusTypeDef ILI9486_WriteRegister_NoCS(uint8_t cmd, const uint8_t *data, uint16_t len);
HAL_StatusTypeDef ILI9486_WriteDataBuffer_NoCS(const uint8_t *buffer, uint16_t length);
HAL_StatusTypeDef ILI9486_Write_AllData(uint16_t color, uint32_t pixels);
HAL_StatusTypeDef ILI9486_Write_bufferData(const uint8_t *buffer,uint32_t length);


LCD_DIS sLCD_DIS;

/*******************************************************************************
function:
Hardware reset
*******************************************************************************/
static void ILI9486_Reset(void)
{
LCD_RST_HIGH();
HAL_Delay(500);
LCD_RST_LOW();
HAL_Delay(500);
LCD_RST_HIGH();
HAL_Delay(500);
}

/*******************************************************************************
function:
Optimized Write register address and data
*******************************************************************************/
void ILI9486_WriteCommand_NoCS(uint8_t cmd)
{
LCD_DC_CMD();
HAL_SPI_Transmit(&hspi1,&cmd,1,HAL_MAX_DELAY);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

}

void ILI9486_WriteData_NoCS(uint8_t data)
{
LCD_DC_DATA();
HAL_SPI_Transmit(&hspi1,&data,1,HAL_MAX_DELAY);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
}

static HAL_StatusTypeDef ILI9486_WriteRegister_NoCS(uint8_t cmd, const uint8_t *data, uint16_t len)
{
ILI9486_WriteCommand_NoCS(cmd);

return ILI9486_WriteDataBuffer_NoCS(data, len);
}

HAL_StatusTypeDef ILI9486_WriteDataBuffer_NoCS(const uint8_t *buffer, uint16_t length)
{
if ((buffer == NULL) || (length == 0U))
{
return HAL_ERROR;
}
LCD_DC_DATA();
// LCD_CS_LOW();
return HAL_SPI_Transmit(&hspi1,(uint8_t *)buffer,length,HAL_MAX_DELAY);
// LCD_CS_HIGH();
}


//******************************************************************************
/*******************************************************************************
function:
Write register address and data
*******************************************************************************/
void ILI9486_WriteCommand(uint8_t cmd)
{
LCD_CS_LOW();
LCD_DC_CMD();
HAL_SPI_Transmit(&hspi1,&cmd,1,HAL_MAX_DELAY);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
LCD_CS_HIGH();
}

void ILI9486_WriteData(uint8_t data)
{
LCD_CS_LOW();
LCD_DC_DATA();
HAL_SPI_Transmit(&hspi1,&data,1,HAL_MAX_DELAY);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
LCD_CS_HIGH();
}

/*******************************************************************************
function:
Write register data
*******************************************************************************/

HAL_StatusTypeDef ILI9486_Write_AllData(uint16_t color, uint32_t pixels)
{
HAL_StatusTypeDef status;
uint8_t txBuf[128]; // 128 pixels

for(uint32_t i = 0; i < sizeof(txBuf); i += 2)
{
txBuf[i] = color >> 8;
txBuf[i+1] = color & 0xFF;
}

ILI9486_WriteCommand(0x2C);

LCD_CS_LOW();
LCD_DC_DATA();
while(pixels)
{
uint32_t n = pixels;
if(n > 64) //64
n = 64; //64
status = HAL_SPI_Transmit(&hspi1,txBuf,n * 2,HAL_MAX_DELAY);
if(status != HAL_OK)
{
LCD_CS_HIGH();
return status;
}
pixels -= n;
}
LCD_CS_HIGH();
return HAL_OK;
}


HAL_StatusTypeDef ILI9486_Write_bufferData(const uint8_t *buffer,uint32_t length)
{
HAL_StatusTypeDef status;

ILI9486_WriteCommand(0x2C);
LCD_DC_DATA();
LCD_CS_LOW();
status = HAL_SPI_Transmit(&hspi1,(uint8_t *)buffer,length,HAL_MAX_DELAY);

LCD_CS_HIGH();

return status;
}

/*******************************************************************************
function:
Common register initialization
*******************************************************************************/
static const uint8_t regF9[] = { 0x00, 0x08 };
static const uint8_t regC0[] = { 0x19, 0x1A };
static const uint8_t regC1[] = { 0x45, 0x00 };
static const uint8_t regC2[] = { 0x33 };
static const uint8_t regC5[] = { 0x00, 0x28 };
static const uint8_t regB1[] = { 0xB0, 0x11 };
static const uint8_t regB4[] = { 0x02};
static const uint8_t regB6[] = { 0x00, 0x42,0x3B };
static const uint8_t regB7[] = { 0x07 };
static const uint8_t regE0[] = { 0x1F,0x25,0x22,0x0B,0x06,0x0A,0x4E,0xC6,0x39,0x00,0x00,0x00,0x00,0x00,0x00};
static const uint8_t regE1[] = { 0x1F,0x3F,0x3F,0x0F,0x1F,0x0F,0x46,0x49,0x31,0x05,0x09,0x03,0x1C,0x1A,0x00};
static const uint8_t regF1[] = { 0x36,0x04,0x00,0x3C,0x0F,0x0F,0xA4,0x02};
static const uint8_t regF2[] = { 0x18,0xA3,0x12,0x02,0x32,0x12,0xFF,0x32,0x00};
static const uint8_t regF4[] = { 0x40,0x00,0x08,0x91,0x04};
static const uint8_t regF8[] = { 0x21,0x04};
static const uint8_t reg3A[] = { 0x55};

static const uint8_t regE2[] = { 0x1F,0x32,0x2E,0x0B,0x0D,0x05,0x47,0x75,0x37,0x06,0x10,0x03,0x24,0x20,0x00};
static const uint8_t regB0[] = { 0x40};

static void ILI9486_InitReg(void)
{
LCD_CS_LOW();

ILI9486_WriteRegister_NoCS(0xF9, regF9, sizeof(regF9));
ILI9486_WriteRegister_NoCS(0xC0, regC0, sizeof(regC0));
ILI9486_WriteRegister_NoCS(0xC1, regC1, sizeof(regC1));
ILI9486_WriteRegister_NoCS(0xC2, regC2, sizeof(regC2));
ILI9486_WriteRegister_NoCS(0xC5, regC5, sizeof(regC5));

ILI9486_WriteRegister_NoCS(0xB0, regB0, sizeof(regB0));

ILI9486_WriteRegister_NoCS(0xB1, regB1, sizeof(regB1));
ILI9486_WriteRegister_NoCS(0xB4, regB4, sizeof(regB4));
ILI9486_WriteRegister_NoCS(0xB6, regB6, sizeof(regB6));
ILI9486_WriteRegister_NoCS(0xB7, regB7, sizeof(regB7));
ILI9486_WriteRegister_NoCS(0xE0, regE0, sizeof(regE0));
ILI9486_WriteRegister_NoCS(0xE1, regE1, sizeof(regE1));

ILI9486_WriteRegister_NoCS(0xE2, regE2, sizeof(regE2));

ILI9486_WriteRegister_NoCS(0xF1, regF1, sizeof(regF1));
ILI9486_WriteRegister_NoCS(0xF2, regF2, sizeof(regF2));
ILI9486_WriteRegister_NoCS(0xF4, regF4, sizeof(regF4));
ILI9486_WriteRegister_NoCS(0xF8, regF8, sizeof(regF8));
ILI9486_WriteRegister_NoCS(0x3A, reg3A, sizeof(reg3A));

LCD_CS_HIGH();
}

/********************************************************************************
function: Set the display scan and color transfer modes
parameter:
Scan_dir : Scan direction
Colorchose : RGB or GBR color format
********************************************************************************/
void ILI9486_SetGramScanWay(LCD_SCAN_DIR Scan_dir)
{
uint16_t MemoryAccessReg_Data = 0; //addr:0x36
uint16_t DisFunReg_Data = 0; //addr:0xB6

// Gets the scan direction of GRAM
switch (Scan_dir)
{
case L2R_U2D:
MemoryAccessReg_Data = 0x48;//0x08 | 0X8
DisFunReg_Data = 0x22;
break;
case L2R_D2U:
MemoryAccessReg_Data = 0x08;
DisFunReg_Data = 0x62;
break;
case R2L_U2D: //0X4
MemoryAccessReg_Data = 0x08;
DisFunReg_Data = 0x02;
break;
case R2L_D2U: //0XC
MemoryAccessReg_Data = 0x08;
DisFunReg_Data = 0x42;
break;
case U2D_L2R: //0X2
MemoryAccessReg_Data = 0x28;
DisFunReg_Data = 0x22;
break;
case U2D_R2L: //0X6
MemoryAccessReg_Data = 0x28;
DisFunReg_Data = 0x02;
break;
case D2U_L2R: //0XA
MemoryAccessReg_Data = 0x28;
DisFunReg_Data = 0x62;
break;
case D2U_R2L: //0XE
MemoryAccessReg_Data = 0x28;
DisFunReg_Data = 0x42;
break;
}

//Get the screen scan direction
sLCD_DIS.LCD_Scan_Dir = Scan_dir;

//Get GRAM and LCD width and height
if(Scan_dir == L2R_U2D || Scan_dir == L2R_D2U || Scan_dir == R2L_U2D || Scan_dir == R2L_D2U)
{
sLCD_DIS.LCD_Dis_Column = GUI_HEIGHT;
sLCD_DIS.LCD_Dis_Page = GUI_WIDTH;
} else
{
sLCD_DIS.LCD_Dis_Column = GUI_WIDTH;
sLCD_DIS.LCD_Dis_Page = GUI_HEIGHT;
}

// Set the read / write scan direction of the frame memory
LCD_CS_LOW();

ILI9486_WriteCommand_NoCS(0xB6);
ILI9486_WriteData_NoCS(0X00);
ILI9486_WriteData_NoCS(DisFunReg_Data);

ILI9486_WriteCommand_NoCS(0x36);
ILI9486_WriteData_NoCS(MemoryAccessReg_Data);

LCD_CS_HIGH();
}

/********************************************************************************
function:
initialization
********************************************************************************/
void ILI9486_Init(LCD_SCAN_DIR LCD_ScanDir){
//Hardware reset
ILI9486_Reset();
ILI9486_WriteCommand(0x01); //Soft Reset
//Set the initialization register
ILI9486_InitReg();
ILI9486_WriteCommand(0x13); //Normal Display Mode ON
ILI9486_WriteCommand(0x38); //Idle Mode OFF

//Set the display scan and color transfer modes
ILI9486_SetGramScanWay(LCD_ScanDir);
HAL_Delay(200);

ILI9486_WriteCommand(0x20); //Display Inversion OFF
//sleep out
ILI9486_WriteCommand(0x11);
HAL_Delay(130);

//Turn on the LCD display
ILI9486_WriteCommand(0x29);
}
/********************************************************************************
function: Sets the start position and size of the display area
parameter:
Xstart : X direction Start coordinates
Ystart : Y direction Start coordinates
Xend : X direction end coordinates
Yend : Y direction end coordinates
********************************************************************************/
void ILI9486_SetWindow(POINT Xstart, POINT Ystart, POINT Xend, POINT Yend)
{
// LCD_CS_LOW();
//set the X coordinates
ILI9486_WriteCommand(0x2A);
ILI9486_WriteData(Xstart>> 8); //Set the horizontal starting point to the high octet
ILI9486_WriteData(Xstart); //Set the horizontal starting point to the low octet
ILI9486_WriteData(Xend>> 8); //Set the horizontal end to the high octet
ILI9486_WriteData(Xend); //Set the horizontal end to the low octet

//set the Y coordinates
ILI9486_WriteCommand(0x2B);
ILI9486_WriteData(Ystart >> 8);
ILI9486_WriteData(Ystart);
ILI9486_WriteData(Yend>> 8);
ILI9486_WriteData(Yend);

// ILI9486_WriteCommand(0x2C);
// LCD_CS_HIGH();
}

/********************************************************************************
function: Set the display point (Xpoint, Ypoint)
parameter:
xStart : X direction Start coordinates
xEnd : X direction end coordinates
********************************************************************************/
void ILI9486_SetCursor(POINT Xpoint, POINT Ypoint)
{
ILI9486_SetWindow(Xpoint, Ypoint, Xpoint-1, Ypoint-1);
}

/********************************************************************************
function: Set show color
parameter:
Color : Set show color,16-bit depth
********************************************************************************/
//static void LCD_SetColor(LENGTH Dis_Width, LENGTH Dis_Height, COLOR Color ){
void ILI9486_SetColor(COLOR Color , POINT Xpoint, POINT Ypoint)
{
uint32_t pixels = (uint32_t)Xpoint * (uint32_t)Ypoint;
ILI9486_Write_AllData(Color ,pixels);
}

/********************************************************************************
function: Point (Xpoint, Ypoint) Fill the color
parameter:
Xpoint : The x coordinate of the point
Ypoint : The y coordinate of the point
Color : Set the color
********************************************************************************/
void ILI9486_SetPointlColor( POINT Xpoint, POINT Ypoint, COLOR Color)
{
if ((Xpoint <= sLCD_DIS.LCD_Dis_Column) && (Ypoint <= sLCD_DIS.LCD_Dis_Page)) {
ILI9486_SetCursor (Xpoint, Ypoint);
ILI9486_SetColor(Color, 1, 1);
}
}

/********************************************************************************
function: Fill the area with the color
parameter:
Xstart : Start point x coordinate
Ystart : Start point y coordinate
Xend : End point coordinates
Yend : End point coordinates
Color : Set the color
********************************************************************************/
void ILI9486_SetArealColor(POINT Xstart, POINT Ystart, POINT Xend, POINT Yend, COLOR Color)
{
uint16_t width = (uint16_t)(Xend - Xstart);
uint16_t height = (uint16_t)(Yend - Ystart);
if((Xend >= Xstart) && (Yend >= Ystart)) {

ILI9486_SetWindow(Xstart , Ystart , Xend-1 , Yend-1);
ILI9486_SetColor ( Color , width, height);
}
}

/********************************************************************************
function:
Clear screen
********************************************************************************/
void ILI9486_ClearScreen(COLOR Color)
{
ILI9486_SetArealColor(0, 0, sLCD_DIS.LCD_Dis_Column , sLCD_DIS.LCD_Dis_Page , Color);
}

 

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ili9486.h"
#include "ili9486_Controller.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */


/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */


/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_tx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SPI1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI1_Init();
/* USER CODE BEGIN 2 */


LCD_SCAN_DIR Lcd_ScanDir = SCAN_DIR_DFT;//SCAN_DIR_DFT = D2U_L2R

ILI9486_Init(Lcd_ScanDir);
HAL_Delay(1000);
ILI9486_ClearScreen(BLACK);
HAL_Delay(1000);

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{

ILI9486_SetArealColor(100,100,200,200, GRAY);
HAL_Delay(1000);
ILI9486_SetPointlColor(160,300, GREEN);
HAL_Delay(1000);

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 6;
RCC_OscInitStruct.PLL.PLLN = 216;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/** Activate the Over-Drive mode
*/
if (HAL_PWREx_EnableOverDrive() != HAL_OK)
{
Error_Handler();
}

/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief SPI1 Initialization Function
* @param None
* @retval None
*/
static void MX_SPI1_Init(void)
{

/* USER CODE BEGIN SPI1_Init 0 */

/* USER CODE END SPI1_Init 0 */

/* USER CODE BEGIN SPI1_Init 1 */

/* USER CODE END SPI1_Init 1 */
/* 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_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */

/* USER CODE END SPI1_Init 2 */

}

/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{

/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();

/* DMA interrupt init */
/* DMA2_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);

}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */

/* USER CODE END MX_GPIO_Init_1 */

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);

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

/*Configure GPIO pin : LCD_CS_Pin */
GPIO_InitStruct.Pin = LCD_CS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(LCD_CS_GPIO_Port, &GPIO_InitStruct);

/*Configure GPIO pins : LCD_RST_Pin LCD_DC_Pin */
GPIO_InitStruct.Pin = LCD_RST_Pin|LCD_DC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */

/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */