跳到主要内容

在 STM32 上使用 LVGL 库

st7789.h
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file st7789.h
* @brief This file contains all the function prototypes for
* the st7789.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 GoStartKit.
* 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 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __ST7789_H__
#define __ST7789_H__

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* USER CODE BEGIN Includes */
#include <stdint.h>
#include "gpio.h"
#include "spi.h"
/* USER CODE END Includes */

extern SPI_HandleTypeDef hspi1;

/* USER CODE BEGIN Private defines */
// LCD size
#define LCD_WIDTH 240
#define LCD_HEIGHT 240

// color (RGB565)
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0XBC40
#define BRRED 0XFC07
#define GRAY 0X8430
/* USER CODE END Private defines */

/* USER CODE BEGIN Prototypes */
void LCD_Init(void);
void LCD_Fill(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end, uint16_t color);
void LCD_Set_Address(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void LCD_Write_Data(uint8_t *data, uint16_t size);
/* USER CODE END Prototypes */

#ifdef __cplusplus
}
#endif

#endif /* __ST7789_H__ */
st7789.c
#include "st7789.h"

static void SPI_Transmit(uint8_t *data, uint16_t size)
{
HAL_SPI_Transmit(&hspi1, data, size, HAL_MAX_DELAY);
}

static void LCD_Write_Cmd(uint8_t cmd)
{
HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET); // DC置低,表示命令
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); // 片选拉低
SPI_Transmit(&cmd, 1);
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); // 片选拉高
}

void LCD_Write_Data(uint8_t *data, uint16_t size)
{
HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // DC置高,表示数据
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); // 片选拉低
SPI_Transmit(data, size);
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); // 片选拉高
}

static void LCD_Write_Data_16Bit(uint16_t data)
{
uint8_t buffer[2] = {data >> 8, data & 0xFF};
LCD_Write_Data(buffer, 2);
}

void LCD_Set_Address(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
uint8_t data[4];

// 列地址设置
data[0] = x1 >> 8;
data[1] = x1 & 0xFF;
data[2] = x2 >> 8;
data[3] = x2 & 0xFF;
LCD_Write_Cmd(0x2A); // CASET
LCD_Write_Data(data, 4);

// 行地址设置
data[0] = y1 >> 8;
data[1] = y1 & 0xFF;
data[2] = y2 >> 8;
data[3] = y2 & 0xFF;
LCD_Write_Cmd(0x2B); // RASET
LCD_Write_Data(data, 4);

// 准备写RAM
LCD_Write_Cmd(0x2C); // RAMWR
}

static void LCD_Reset(void)
{
HAL_GPIO_WritePin(LCD_PWR_EN_GPIO_Port, LCD_PWR_EN_Pin, GPIO_PIN_SET); // 打开电源
HAL_Delay(20);

HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
HAL_Delay(100);
}

void LCD_Init(void)
{
LCD_Reset();

//************* Start Initial Sequence **********//
LCD_Write_Cmd(0x11); // Sleep Out
HAL_Delay(120); // Delay 120ms

LCD_Write_Cmd(0x36); // Memory Data Access Control
uint8_t madctl_data = 0x00; // 默认方向: 从上到下,从左到右,RGB
LCD_Write_Data(&madctl_data, 1);

LCD_Write_Cmd(0x3A); // Interface Pixel Format
uint8_t format_data = 0x55; // 16 bits/pixel
LCD_Write_Data(&format_data, 1);

LCD_Write_Cmd(0xB2); // Porch Setting
uint8_t porch_data[] = {0x0C, 0x0C, 0x00, 0x33, 0x33};
LCD_Write_Data(porch_data, sizeof(porch_data));

LCD_Write_Cmd(0xB7); // Gate Control
uint8_t gate_data = 0x35;
LCD_Write_Data(&gate_data, 1);

LCD_Write_Cmd(0xBB); // VCOM Setting
uint8_t vcom_data = 0x19;
LCD_Write_Data(&vcom_data, 1);

LCD_Write_Cmd(0xC0); // LCM Control
uint8_t lcm_data = 0x2C;
LCD_Write_Data(&lcm_data, 1);

LCD_Write_Cmd(0xC2); // VDV and VRH Command Enable
uint8_t vdv_vrh_data[] = {0x01, 0xFF};
LCD_Write_Data(vdv_vrh_data, sizeof(vdv_vrh_data));

LCD_Write_Cmd(0xC3); // VRH Set
uint8_t vrh_data = 0x12;
LCD_Write_Data(&vrh_data, 1);

LCD_Write_Cmd(0xC4); // VDV Set
uint8_t vdv_data = 0x20;
LCD_Write_Data(&vdv_data, 1);

LCD_Write_Cmd(0xC6); // Frame Rate Control in Normal Mode
uint8_t fr_ctrl_data = 0x0F;
LCD_Write_Data(&fr_ctrl_data, 1);

LCD_Write_Cmd(0xD0); // Power Control 1
uint8_t pwr_ctrl1_data[] = {0xA4, 0xA1};
LCD_Write_Data(pwr_ctrl1_data, sizeof(pwr_ctrl1_data));

LCD_Write_Cmd(0xE0); // Positive Voltage Gamma Control
uint8_t pv_gamma_data[] = {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23};
LCD_Write_Data(pv_gamma_data, sizeof(pv_gamma_data));

LCD_Write_Cmd(0xE1); // Negative Voltage Gamma Control
uint8_t nv_gamma_data[] = {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23};
LCD_Write_Data(nv_gamma_data, sizeof(nv_gamma_data));

LCD_Write_Cmd(0x21); // Display Inversion On (可选)

LCD_Write_Cmd(0x29); // Display On
HAL_Delay(100);
}

void LCD_Fill(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end, uint16_t color)
{
uint32_t pixel_count = (x_end - x_start + 1) * (y_end - y_start + 1);
uint32_t i;

LCD_Set_Address(x_start, y_start, x_end, y_end);

HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET);

for (i = 0; i < pixel_count; i++)
{
uint8_t pixel_data[2] = {color >> 8, color & 0xFF};
SPI_Transmit(pixel_data, 2);
}

HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET);
}