Files
ch32v20x-examples/EVT/EXAM/APPLICATION/WUI/User/Drivers/LCD.c
T
2026-08-10 10:47:09 +08:00

383 lines
6.7 KiB
C

/*********************************************************************
* File Name : lcd.c
* Author : WCH
* Version : V1.0.0
* Date : 2023/8/15
* Description : file for lcd screen.
*********************************************************************************
* Copyright (c) 2023 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
#include "lcd.h"
#include "debug.h"
#include "LCD_Font.h"
#define LCD_SOFT_RESET (0x01)
#define LCD_READ_ID (0x04)
#define LCD_READ_DISPLAY_STATUS (0x09)
#define LCD_ON (0x28)
#define LCD_OFF (0x29)
#define LCD_SET_X (0x2a)
#define LCD_SET_Y (0x2b)
#define LCD_MEM_WRITE (0x2C)
#define LCD_MEM_READ (0x2e)
static void LCD_WR_REG(uint8_t data)
{
LCD_DC_CLR();
SPI2_Write(data);
}
static void LCD_WR_DATA(uint8_t data)
{
LCD_DC_SET();
SPI2_Write(data);
}
/*********************************************************************
* @fn Lcd_WriteData_16Bit
*
* @brief write two bytes to the lcd screen
*
* @param Data - the data to write
*
* @return none
*/
void Lcd_WriteData_16Bit(uint16_t Data)
{
SPI2_Write(Data >> 8);
SPI2_Write(Data);
}
/*********************************************************************
* @fn LCD_GPIOInit
*
* @brief Configuring the control gpio for the lcd screen
*
* @return none
*/
void LCD_GPIOInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(LCD_LED_RCC, ENABLE);
RCC_APB2PeriphClockCmd(LCD_DC_RCC, ENABLE);
RCC_APB2PeriphClockCmd(LCD_RST_RCC, ENABLE);
RCC_APB2PeriphClockCmd(LCD_CS_RCC, ENABLE);
GPIO_InitStructure.GPIO_Pin = LCD_LED_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LCD_LED_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LCD_DC_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LCD_DC_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LCD_RST_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LCD_RST_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LCD_CS_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LCD_CS_PORT, &GPIO_InitStructure);
LCD_LED_CLR();
LCD_CS_SET();
}
/*********************************************************************
* @fn LCD_RESET
*
* @brief reset the lcd screen by the rst pin
*
* @return none
*/
void LCD_RESET(void)
{
Delay_Ms(50);
LCD_RST_CLR();
Delay_Ms(100);
LCD_RST_SET();
Delay_Ms(50);
}
static const uint8_t lcd_st7789_init_cmds[] = {
1,
0x3A,
0x05,
2,
0xB0,
0x00,
0xF0,
5,
0xB2,
0x0C,
0x0C,
0x00,
0x33,
0x33,
1,
0xB7,
0x35,
1,
0xBB,
0x19,
1,
0xC0,
0x2C,
1,
0xC2,
0x01,
1,
0xC3,
0x12,
1,
0xC4,
0x20,
1,
0xC6,
0x0F,
2,
0xD0,
0xA4,
0xA1,
14,
0xE0,
0xD0,
0x04,
0x0D,
0x11,
0x13,
0x2B,
0x3F,
0x54,
0x4C,
0x18,
0x0D,
0x0B,
0x1F,
0x23,
14,
0xE1,
0xD0,
0x04,
0x0C,
0x11,
0x13,
0x2C,
0x3F,
0x44,
0x51,
0x2F,
0x1F,
0x1F,
0x20,
0x23,
0,
0x21,
1,
0x36,
#if USE_HORIZONTAL == 0
0,
#elif USE_HORIZONTAL == 1
(1 << 7) | (1 << 6) | (0 << 5),
#elif USE_HORIZONTAL == 2
(1 << 6) | (0 << 7) | (1 << 5),
#elif USE_HORIZONTAL == 3
(1 << 7) | (1 << 5),
#endif
0,
0x11,
0,
0x29,
0xff,
0xff,
};
void LCD_exec_init(uint8_t* init_code)
{
uint8_t* p = init_code;
uint8_t data_len;
uint8_t cmd;
LCD_CS_CLR();
while (1)
{
data_len = *p++;
cmd = *p++;
if (cmd == 0xFF)
{
break;
}
LCD_WR_REG(cmd);
for (uint8_t i = 0; i < data_len; i++)
{
LCD_WR_DATA(*p++);
}
}
LCD_CS_SET();
}
void LCD_Init(void)
{
SPI2_Init();
SPI2_DMA_Init();
LCD_GPIOInit();
LCD_RESET();
LCD_CS_CLR();
LCD_WR_REG(0x28);
LCD_exec_init((uint8_t*)lcd_st7789_init_cmds);
Delay_Ms(10);
LCD_Clear(LCD_BLACK);
Delay_Ms(10);
LCD_LED_SET();
}
/*********************************************************************
* @fn LCD_SetWindows
*
* @brief Setting LCD display window
*
* @param xStar - the bebinning x coordinate of the LCD display window
* yStar - the bebinning y coordinate of the LCD display window
* xEnd - the endning x coordinate of the LCD display window
* yEnd - the endning y coordinate of the LCD display window
*
* @return none
*/
void LCD_SetWindows(uint16_t xStar, uint16_t yStar, uint16_t xEnd, uint16_t yEnd)
{
LCD_CS_CLR();
LCD_WR_REG(LCD_SET_X);
LCD_WR_DATA(xStar >> 8);
LCD_WR_DATA(0x00FF & xStar);
LCD_WR_DATA(xEnd >> 8);
LCD_WR_DATA(0x00FF & xEnd);
LCD_WR_REG(LCD_SET_Y);
LCD_WR_DATA(yStar >> 8);
LCD_WR_DATA(0x00FF & yStar);
LCD_WR_DATA(yEnd >> 8);
LCD_WR_DATA(0x00FF & yEnd);
LCD_WR_REG(LCD_MEM_WRITE);
LCD_CS_SET();
}
// 设置引脚为高电平
void LCD_LED_SET(void)
{
LCD_LED_PORT->BSHR = LCD_LED_PIN;
}
void LCD_CS_SET(void)
{
LCD_CS_PORT->BSHR = LCD_CS_PIN;
}
void LCD_DC_SET(void)
{
LCD_DC_PORT->BSHR = LCD_DC_PIN;
}
void LCD_RST_SET(void)
{
LCD_RST_PORT->BSHR = LCD_RST_PIN;
}
// 设置引脚为低电平
void LCD_LED_CLR(void)
{
LCD_LED_PORT->BCR = LCD_LED_PIN;
}
void LCD_CS_CLR(void)
{
LCD_CS_PORT->BCR = LCD_CS_PIN;
}
void LCD_DC_CLR(void)
{
LCD_DC_PORT->BCR = LCD_DC_PIN;
}
void LCD_RST_CLR(void)
{
LCD_RST_PORT->BCR = LCD_RST_PIN;
}
void SPI1_wait_for_bsy()
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET)
;
}
void SPI2_wait_for_bsy()
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET)
;
}
void SPI2_wait_for_txe()
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)
;
}
void SPI1_wait_for_DMA()
{
while (SPI1_DMA_TX_CH->CNTR > 0)
{
}
}
void SPI2_wait_for_DMA()
{
while (SPI2_DMA_TX_CH->CNTR > 0)
{
}
}
void LCD_Clear(uint16_t color)
{
LCD_Fill(0, 0, LCD_W, LCD_H, color);
}