单片机:STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
原理图:

配置:
/* RESET 和系统复位脚共用 所以这里不用定义 RESET引脚 */
//#define LCD_RST_GPIO_PORT GPIOx
//#define LCD_RST_GPIO_PIN SYS_GPIO_PINx
//#define LCD_RST_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOx_CLK_ENABLE(); }while(0) /* 所在IO口时钟使能 */
#define LCD_WR_GPIO_PORT GPIOD
#define LCD_WR_GPIO_PIN GPIO_PIN_5
#define LCD_WR_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0) /* 所在IO口时钟使能 */
#define LCD_RD_GPIO_PORT GPIOD
#define LCD_RD_GPIO_PIN GPIO_PIN_4
#define LCD_RD_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0) /* 所在IO口时钟使能 */
#define LCD_BL_GPIO_PORT GPIOH
#define LCD_BL_GPIO_PIN GPIO_PIN_9
#define LCD_BL_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0) /* 背光所在IO口时钟使能 */
/* LCD_CS(需要根据LCD_FSMC_NEX设置正确的IO口) 和 LCD_RS(需要根据LCD_FSMC_AX设置正确的IO口) 引脚 定义 */
#define LCD_CS_GPIO_PORT GPIOG
#define LCD_CS_GPIO_PIN GPIO_PIN_12
#define LCD_CS_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOG_CLK_ENABLE(); }while(0) /* 所在IO口时钟使能 */
#define LCD_RS_GPIO_PORT GPIOG
#define LCD_RS_GPIO_PIN GPIO_PIN_0
#define LCD_RS_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOG_CLK_ENABLE(); }while(0) /* 所在IO口时钟使能 */
/* FSMC相关参数 定义
* 注意: 我们默认是通过FSMC块1来连接LCD, 块1有4个片选: FSMC_NE1~4
*
* 修改LCD_FSMC_NEX, 对应的LCD_CS_GPIO相关设置也得改
* 修改LCD_FSMC_AX , 对应的LCD_RS_GPIO相关设置也得改
*/
#define LCD_FSMC_NEX 4 /* 使用FSMC_NE4接LCD_CS,取值范围只能是: 1~4 */
#define LCD_FSMC_AX 10 /* 使用FSMC_A6接LCD_RS,取值范围是: 0 ~ 25 */
#define LCD_FSMC_BCRX FSMC_Bank1->BTCR[(LCD_FSMC_NEX - 1) * 2] /* BCR寄存器,根据LCD_FSMC_NEX自动计算 */
#define LCD_FSMC_BTRX FSMC_Bank1->BTCR[(LCD_FSMC_NEX - 1) * 2 + 1] /* BTR寄存器,根据LCD_FSMC_NEX自动计算 */
#define LCD_FSMC_BWTRX FSMC_Bank1E->BWTR[(LCD_FSMC_NEX - 1) * 2] /* BWTR寄存器,根据LCD_FSMC_NEX自动计算 */
/* LCD重要参数集 */
typedef struct
{
uint16_t width; /* LCD 宽度 */
uint16_t height; /* LCD 高度 */
uint16_t id; /* LCD ID */
uint8_t dir; /* 横屏还是竖屏控制:0,竖屏;1,横屏。 */
uint16_t wramcmd; /* 开始写gram指令 */
uint16_t setxcmd; /* 设置x坐标指令 */
uint16_t setycmd; /* 设置y坐标指令 */
} _lcd_dev;
/* LCD参数 */
extern _lcd_dev lcddev; /* 管理LCD重要参数 */
/* LCD的画笔颜色和背景色 */
extern uint32_t g_point_color; /* 默认红色 */
extern uint32_t g_back_color; /* 背景颜色.默认为白色 */
/* LCD背光控制 */
#define LCD_BL(x) do{ x ? \
HAL_GPIO_WritePin(LCD_BL_GPIO_PORT, LCD_BL_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(LCD_BL_GPIO_PORT, LCD_BL_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
/* LCD地址结构体 */
typedef struct
{
volatile uint16_t LCD_REG;
volatile uint16_t LCD_RAM;
} LCD_TypeDef;
/* LCD_BASE的详细解算方法:
* 我们一般使用FSMC的块1(BANK1)来驱动TFTLCD液晶屏(MCU屏), 块1地址范围总大小为256MB,均分成4块:
* 存储块1(FSMC_NE1)地址范围: 0x6000 0000 ~ 0x63FF FFFF
* 存储块2(FSMC_NE2)地址范围: 0x6400 0000 ~ 0x67FF FFFF
* 存储块3(FSMC_NE3)地址范围: 0x6800 0000 ~ 0x6BFF FFFF
* 存储块4(FSMC_NE4)地址范围: 0x6C00 0000 ~ 0x6FFF FFFF
*
* 我们需要根据硬件连接方式选择合适的片选(连接LCD_CS)和地址线(连接LCD_RS)
* F407电机开发板使用FSMC_NE4连接LCD_CS, FSMC_A10连接LCD_RS ,16位数据线,计算方法如下:
* 首先FSMC_NE4的基地址为: 0x6C00 0000; NEx的基址为(x=1/2/3/4): 0x6000 0000 + (0x400 0000 * (x - 1))
* FSMC_A10对应地址值: 2^10 * 2 = 0x800; FSMC_Ay对应的地址为(y = 0 ~ 25): 2^y * 2
*
* LCD->LCD_REG,对应LCD_RS = 0(LCD寄存器); LCD->LCD_RAM,对应LCD_RS = 1(LCD数据)
* 则 LCD->LCD_RAM的地址为: 0x6C00 0000 + 2^10 * 2 = 0x6C00 0800
* LCD->LCD_REG的地址可以为 LCD->LCD_RAM之外的任意地址.
* 由于我们使用结构体管理LCD_REG 和 LCD_RAM(REG在前,RAM在后,均为16位数据宽度)
* 因此 结构体的基地址(LCD_BASE) = LCD_RAM - 2 = 0x6C00 0800 -2
*
* 更加通用的计算公式为((片选脚FSMC_NEx)x=1/2/3/4, (RS接地址线FSMC_Ay)y=0~25):
* LCD_BASE = (0x6000 0000 + (0x400 0000 * (x - 1))) | (2^y * 2 -2)
* 等效于(使用移位操作)
* LCD_BASE = (0x6000 0000 + (0x400 0000 * (x - 1))) | ((1 << y) * 2 -2)
*/
#define LCD_BASE (uint32_t)((0x60000000 + (0x4000000 * (LCD_FSMC_NEX - 1))) | (((1 << LCD_FSMC_AX) * 2) -2))
#define LCD ((LCD_TypeDef *) LCD_BASE)
/******************************************************************************************/
/* LCD扫描方向和颜色 定义 */
/* 扫描方向定义 */
#define L2R_U2D 0 /* 从左到右,从上到下 */
#define L2R_D2U 1 /* 从左到右,从下到上 */
#define R2L_U2D 2 /* 从右到左,从上到下 */
#define R2L_D2U 3 /* 从右到左,从下到上 */
#define U2D_L2R 4 /* 从上到下,从左到右 */
#define U2D_R2L 5 /* 从上到下,从右到左 */
#define D2U_L2R 6 /* 从下到上,从左到右 */
#define D2U_R2L 7 /* 从下到上,从右到左 */
#define DFT_SCAN_DIR L2R_U2D /* 默认的扫描方向 */
/* 常用画笔颜色 */
#define WHITE 0xFFFF /* 白色 */
#define BLACK 0x0000 /* 黑色 */
#define RED 0xF800 /* 红色 */
#define GREEN 0x07E0 /* 绿色 */
#define BLUE 0x001F /* 蓝色 */
#define MAGENTA 0xF81F /* 品红色/紫红色 = BLUE + RED */
#define YELLOW 0xFFE0 /* 黄色 = GREEN + RED */
#define CYAN 0x07FF /* 青色 = GREEN + BLUE */
/* 非常用颜色 */
#define BROWN 0xBC40 /* 棕色 */
#define BRRED 0xFC07 /* 棕红色 */
#define GRAY 0x8430 /* 灰色 */
#define DARKBLUE 0x01CF /* 深蓝色 */
#define LIGHTBLUE 0x7D7C /* 浅蓝色 */
#define GRAYBLUE 0x5458 /* 灰蓝色 */
#define LIGHTGREEN 0x841F /* 浅绿色 */
#define LGRAY 0xC618 /* 浅灰色(PANNEL),窗体背景色 */
#define LGRAYBLUE 0xA651 /* 浅灰蓝色(中间层颜色) */
#define LBBLUE 0x2B12 /* 浅棕蓝色(选择条目的反色) */
/******************************************************************************************/
/* SSD1963相关配置参数(一般不用改) */
/* LCD分辨率设置 */
#define SSD_HOR_RESOLUTION 800 /* LCD水平分辨率 */
#define SSD_VER_RESOLUTION 480 /* LCD垂直分辨率 */
/* LCD驱动参数设置 */
#define SSD_HOR_PULSE_WIDTH 1 /* 水平脉宽 */
#define SSD_HOR_BACK_PORCH 46 /* 水平前廊 */
#define SSD_HOR_FRONT_PORCH 210 /* 水平后廊 */
#define SSD_VER_PULSE_WIDTH 1 /* 垂直脉宽 */
#define SSD_VER_BACK_PORCH 23 /* 垂直前廊 */
#define SSD_VER_FRONT_PORCH 22 /* 垂直前廊 */
/* 如下几个参数,自动计算 */
#define SSD_HT (SSD_HOR_RESOLUTION + SSD_HOR_BACK_PORCH + SSD_HOR_FRONT_PORCH)
#define SSD_HPS (SSD_HOR_BACK_PORCH)
#define SSD_VT (SSD_VER_RESOLUTION + SSD_VER_BACK_PORCH + SSD_VER_FRONT_PORCH)
#define SSD_VPS (SSD_VER_BACK_PORCH)
初始化:
void lcd_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
FSMC_NORSRAM_TimingTypeDef fsmc_read_handle;
FSMC_NORSRAM_TimingTypeDef fsmc_write_handle;
LCD_CS_GPIO_CLK_ENABLE(); /* LCD_CS脚时钟使能 */
LCD_WR_GPIO_CLK_ENABLE(); /* LCD_WR脚时钟使能 */
LCD_RD_GPIO_CLK_ENABLE(); /* LCD_RD脚时钟使能 */
LCD_RS_GPIO_CLK_ENABLE(); /* LCD_RS脚时钟使能 */
LCD_BL_GPIO_CLK_ENABLE(); /* LCD_BL脚时钟使能 */
gpio_init_struct.Pin = LCD_CS_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽复用 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = GPIO_AF12_FSMC; /* 复用为FSMC */
HAL_GPIO_Init(LCD_CS_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_CS引脚 */
gpio_init_struct.Pin = LCD_WR_GPIO_PIN;
HAL_GPIO_Init(LCD_WR_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_WR引脚 */
gpio_init_struct.Pin = LCD_RD_GPIO_PIN;
HAL_GPIO_Init(LCD_RD_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_RD引脚 */
gpio_init_struct.Pin = LCD_RS_GPIO_PIN;
HAL_GPIO_Init(LCD_RS_GPIO_PORT, &gpio_init_struct); /* 初始化LCD_RS引脚 */
gpio_init_struct.Pin = LCD_BL_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
HAL_GPIO_Init(LCD_BL_GPIO_PORT, &gpio_init_struct); /* LCD_BL引脚模式设置(推挽输出) */
g_sram_handle.Instance = FSMC_NORSRAM_DEVICE;
g_sram_handle.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
g_sram_handle.Init.NSBank = FSMC_NORSRAM_BANK4; /* 使用NE4 */
g_sram_handle.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE; /* 地址/数据线不复用 */
g_sram_handle.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16; /* 16位数据宽度 */
g_sram_handle.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE; /* 是否使能突发访问,仅对同步突发存储器有效,此处未用到 */
g_sram_handle.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW; /* 等待信号的极性,仅在突发模式访问下有用 */
g_sram_handle.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS; /* 存储器是在等待周期之前的一个时钟周期还是等待周期期间使能NWAIT */
g_sram_handle.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE; /* 存储器写使能 */
g_sram_handle.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE; /* 等待使能位,此处未用到 */
g_sram_handle.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE; /* 读写使用不同的时序 */
g_sram_handle.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE; /* 是否使能同步传输模式下的等待信号,此处未用到 */
g_sram_handle.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE; /* 禁止突发写 */
/* FSMC读时序控制寄存器 */
fsmc_read_handle.AddressSetupTime = 0x0F; /* 地址建立时间(ADDSET)为15个fsmc_ker_ck(1/168=6)即6*15=90ns */
fsmc_read_handle.AddressHoldTime = 0x00; /* 地址保持时间(ADDHLD) 模式A是没有用到 */
fsmc_read_handle.DataSetupTime = 60; /* 数据保存时间(DATAST)为60个fsmc_ker_ck=6*60=360ns */
/* 因为液晶驱动IC的读数据的时候,速度不能太快,尤其是个别奇葩芯片 */
fsmc_read_handle.AccessMode = FSMC_ACCESS_MODE_A; /* 模式A */
/* FSMC写时序控制寄存器 */
fsmc_write_handle.AddressSetupTime = 9; /* 地址建立时间(ADDSET)为9个fsmc_ker_ck=6*9=54ns */
fsmc_write_handle.AddressHoldTime = 0x00; /* 地址保持时间(ADDHLD) 模式A是没有用到 */
fsmc_write_handle.DataSetupTime = 9; /* 数据保存时间(DATAST)为9个fsmc_ker_ck=6*9=54ns */
/* 注意:某些液晶驱动IC的写信号脉宽,最少也得50ns */
fsmc_write_handle.AccessMode = FSMC_ACCESS_MODE_A; /* 模式A */
HAL_SRAM_Init(&g_sram_handle, &fsmc_read_handle, &fsmc_write_handle);
delay_ms(50);
/* 尝试9341 ID的读取 */
lcd_wr_regno(0xD3);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读到0x00 */
lcddev.id = lcd_rd_data(); /* 读取93 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读取41 */
if (lcddev.id != 0x9341) /* 不是 9341 , 尝试看看是不是 ST7789 */
{
lcd_wr_regno(0x04);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读到0x85 */
lcddev.id = lcd_rd_data(); /* 读取0x85 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读取0x52 */
if (lcddev.id == 0x8552) /* 将8552的ID转换成7789 */
{
lcddev.id = 0x7789;
}
if (lcddev.id != 0x7789) /* 也不是ST7789, 尝试是不是 NT35310 */
{
lcd_wr_regno(0xD4);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读回0x01 */
lcddev.id = lcd_rd_data(); /* 读回0x53 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 这里读回0x10 */
if (lcddev.id != 0x5310) /* 也不是NT35310,尝试看看是不是ST7796 */
{
lcd_wr_regno(0XD3);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读到0X00 */
lcddev.id = lcd_rd_data(); /* 读取0X77 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读取0X96 */
if (lcddev.id != 0x7796) /* 也不是ST7796,尝试看看是不是NT35510 */
{
/* 发送密钥(厂家提供) */
lcd_write_reg(0xF000, 0x0055);
lcd_write_reg(0xF001, 0x00AA);
lcd_write_reg(0xF002, 0x0052);
lcd_write_reg(0xF003, 0x0008);
lcd_write_reg(0xF004, 0x0001);
lcd_wr_regno(0xC500); /* 读取ID低八位 */
lcddev.id = lcd_rd_data(); /* 读回0x80 */
lcddev.id <<= 8;
lcd_wr_regno(0xC501); /* 读取ID高八位 */
lcddev.id |= lcd_rd_data(); /* 读回0x00 */
delay_ms(5); /* 等待5ms, 因为0XC501指令对1963来说就是软件复位指令, 等待5ms让1963复位完成再操作 */
if (lcddev.id != 0x5510) /* 也不是NT5510,尝试看看是不是ILI9806 */
{
lcd_wr_regno(0XD3);
lcddev.id = lcd_rd_data(); /* dummy read */
lcddev.id = lcd_rd_data(); /* 读回0X00 */
lcddev.id = lcd_rd_data(); /* 读回0X98 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读回0X06 */
if (lcddev.id != 0x9806) /* 也不是ILI9806,尝试看看是不是SSD1963 */
{
lcd_wr_regno(0xA1);
lcddev.id = lcd_rd_data();
lcddev.id = lcd_rd_data(); /* 读回0x57 */
lcddev.id <<= 8;
lcddev.id |= lcd_rd_data(); /* 读回0x61 */
if (lcddev.id == 0x5761) lcddev.id = 0x1963; /* SSD1963读回的ID是5761H,为方便区分,我们强制设置为1963 */
}
}
}
}
}
}
/* 特别注意, 如果在main函数里面屏蔽串口1初始化, 则会卡死在printf
* 里面(卡死在f_putc函数), 所以, 必须初始化串口1, 或者屏蔽掉下面
* 这行 printf 语句 !!!!!!!
*/
printf("LCD ID:%x\r\n", lcddev.id); /* 打印LCD ID */
if (lcddev.id == 0x7789)
{
lcd_ex_st7789_reginit(); /* 执行ST7789初始化 */
}
else if (lcddev.id == 0x9341)
{
lcd_ex_ili9341_reginit(); /* 执行ILI9341初始化 */
}
else if (lcddev.id == 0x5310)
{
lcd_ex_nt35310_reginit(); /* 执行NT35310初始化 */
}
else if (lcddev.id == 0x7796)
{
lcd_ex_st7796_reginit(); /* 执行ST7796初始化 */
}
else if (lcddev.id == 0x5510)
{
lcd_ex_nt35510_reginit(); /* 执行NT35510初始化 */
}
else if (lcddev.id == 0x9806)
{
lcd_ex_ili9806_reginit(); /* 执行ILI9806初始化 */
}
else if (lcddev.id == 0x1963)
{
lcd_ex_ssd1963_reginit(); /* 执行SSD1963初始化 */
lcd_ssd_backlight_set(100); /* 背光设置为最亮 */
}
/* 初始化完成以后,提速 */
if (lcddev.id == 0x7789 || lcddev.id == 0x9341 || lcddev.id == 0x1963) /* 7789/9341/1963 提速 */
{
/* 重新配置写时序控制寄存器的时序 */
fsmc_write_handle.AddressSetupTime = 3; /* 地址建立时间(ADDSET)为3个fsmc_ker_ck=6*3=18ns */
fsmc_write_handle.DataSetupTime = 3; /* 数据保持时间(DATAST)为3个fsmc_ker_ck=6*3=18ns */
FSMC_NORSRAM_Extended_Timing_Init(g_sram_handle.Extended, &fsmc_write_handle, g_sram_handle.Init.NSBank, g_sram_handle.Init.ExtendedMode);
}
else if (lcddev.id == 0x5310 || lcddev.id == 0x7796 || lcddev.id == 0x5510 || lcddev.id == 0x9806) /* 如果是这几个IC, 则设置WR时序为最快 */
{
/* 重新配置写时序控制寄存器的时序 */
fsmc_write_handle.AddressSetupTime = 2; /* 地址建立时间(ADDSET)为2个fsmc_ker_ck=6*2=12ns */
fsmc_write_handle.DataSetupTime = 2; /* 数据保持时间(DATAST)为2个fsmc_ker_ck=6*2=12ns */
FSMC_NORSRAM_Extended_Timing_Init(g_sram_handle.Extended, &fsmc_write_handle, g_sram_handle.Init.NSBank, g_sram_handle.Init.ExtendedMode);
}
lcd_display_dir(0); /* 默认为竖屏 */
LCD_BL(1); /* 点亮背光 */
lcd_clear(WHITE);
}
void lcd_wr_regno(volatile uint16_t regno)
{
regno = regno; /* 使用-O2优化的时候,必须插入的延时 */
LCD->LCD_REG = regno; /* 写入要写的寄存器序号 */
}
void lcd_wr_data(volatile uint16_t data)
{
data = data; /* 使用-O2优化的时候,必须插入的延时 */
LCD->LCD_RAM = data;
}
void lcd_write_reg(uint16_t regno, uint16_t data)
{
LCD->LCD_REG = regno; /* 写入要写的寄存器序号 */
LCD->LCD_RAM = data; /* 写入数据 */
}
static void lcd_opt_delay(uint32_t i)
{
while (i--); /* 使用AC6时空循环可能被优化,可使用while(1) __asm volatile(""); */
}
static uint16_t lcd_rd_data(void)
{
volatile uint16_t ram; /* 防止被优化 */
lcd_opt_delay(2);
ram = LCD->LCD_RAM;
return ram;
}
void lcd_write_ram_prepare(void)
{
LCD->LCD_REG = lcddev.wramcmd;
}
uint32_t lcd_read_point(uint16_t x, uint16_t y)
{
uint16_t r = 0, g = 0, b = 0;
if (x >= lcddev.width || y >= lcddev.height)
{
return 0; /* 超过了范围,直接返回 */
}
lcd_set_cursor(x, y); /* 设置坐标 */
if (lcddev.id == 0x5510)
{
lcd_wr_regno(0x2E00); /* 5510 发送读GRAM指令 */
}
else
{
lcd_wr_regno(0x2E); /* 9341/5310/1963/7789/7796/9806 等发送读GRAM指令 */
}
r = lcd_rd_data(); /* 假读(dummy read) */
if (lcddev.id == 0x1963)
{
return r; /* 1963直接读就可以 */
}
r = lcd_rd_data(); /* 实际坐标颜色 */
if (lcddev.id == 0x7796) /* 7796 一次读取一个像素值 */
{
return r;
}
/* 9341/5310/5510/7789/9806要分2次读出 */
b = lcd_rd_data();
g = r & 0xFF; /* 对于9341/5310/5510/7789/9806,第一次读取的是RG的值,R在前,G在后,各占8位 */
g <<= 8;
return (((r >> 11) << 11) | ((g >> 10) << 5) | (b >> 11)); /* ILI9341/NT35310/NT35510/ST7789/ILI9806需要公式转换一下 */
}
void lcd_display_on(void)
{
if (lcddev.id == 0x5510)
{
lcd_wr_regno(0x2900); /* 开启显示 */
}
else /* 9341/5310/1963/7789/7796/9806 等发送开启显示指令 */
{
lcd_wr_regno(0x29); /* 开启显示 */
}
}
void lcd_display_off(void)
{
if (lcddev.id == 0x5510)
{
lcd_wr_regno(0x2800); /* 关闭显示 */
}
else /* 9341/5310/1963/7789/7796/9806 等发送关闭显示指令 */
{
lcd_wr_regno(0x28); /* 关闭显示 */
}
}
void lcd_set_cursor(uint16_t x, uint16_t y)
{
if (lcddev.id == 0x1963)
{
if (lcddev.dir == 0) /* 竖屏模式, x坐标需要变换 */
{
x = lcddev.width - 1 - x;
lcd_wr_regno(lcddev.setxcmd);
lcd_wr_data(0);
lcd_wr_data(0);
lcd_wr_data(x >> 8);
lcd_wr_data(x & 0xFF);
}
else /* 横屏模式 */
{
lcd_wr_regno(lcddev.setxcmd);
lcd_wr_data(x >> 8);
lcd_wr_data(x & 0xFF);
lcd_wr_data((lcddev.width - 1) >> 8);
lcd_wr_data((lcddev.width - 1) & 0xFF);
}
lcd_wr_regno(lcddev.setycmd);
lcd_wr_data(y >> 8);
lcd_wr_data(y & 0xFF);
lcd_wr_data((lcddev.height - 1) >> 8);
lcd_wr_data((lcddev.height - 1) & 0xFF);
}
else if (lcddev.id == 0x5510)
{
lcd_wr_regno(lcddev.setxcmd);
lcd_wr_data(x >> 8);
lcd_wr_regno(lcddev.setxcmd + 1);
lcd_wr_data(x & 0xFF);
lcd_wr_regno(lcddev.setycmd);
lcd_wr_data(y >> 8);
lcd_wr_regno(lcddev.setycmd + 1);
lcd_wr_data(y & 0xFF);
}
else /* 9341/5310/7789/7796/9806 等 设置坐标 */
{
lcd_wr_regno(lcddev.setxcmd);
lcd_wr_data(x >> 8);
lcd_wr_data(x & 0xFF);
lcd_wr_regno(lcddev.setycmd);
lcd_wr_data(y >> 8);
lcd_wr_data(y & 0xFF);
}
}
void lcd_scan_dir(uint8_t dir)
{
uint16_t regval = 0;
uint16_t dirreg = 0;
uint16_t temp;
/* 横屏时,对1963不改变扫描方向!竖屏时1963改变方向(这里仅用于1963的特殊处理,对其他驱动IC无效) */
if ((lcddev.dir == 1 && lcddev.id != 0x1963) || (lcddev.dir == 0 && lcddev.id == 0x1963))
{
switch (dir) /* 方向转换 */
{
case 0:
dir = 6;
break;
case 1:
dir = 7;
break;
case 2:
dir = 4;
break;
case 3:
dir = 5;
break;
case 4:
dir = 1;
break;
case 5:
dir = 0;
break;
case 6:
dir = 3;
break;
case 7:
dir = 2;
break;
}
}
/* 根据扫描方式 设置 0x36/0x3600 寄存器 bit 5,6,7 位的值 */
switch (dir)
{
case L2R_U2D: /* 从左到右,从上到下 */
regval |= (0 << 7) | (0 << 6) | (0 << 5);
break;
case L2R_D2U: /* 从左到右,从下到上 */
regval |= (1 << 7) | (0 << 6) | (0 << 5);
break;
case R2L_U2D: /* 从右到左,从上到下 */
regval |= (0 << 7) | (1 << 6) | (0 << 5);
break;
case R2L_D2U: /* 从右到左,从下到上 */
regval |= (1 << 7) | (1 << 6) | (0 << 5);
break;
case U2D_L2R: /* 从上到下,从左到右 */
regval |= (0 << 7) | (0 << 6) | (1 << 5);
break;
case U2D_R2L: /* 从上到下,从右到左 */
regval |= (0 << 7) | (1 << 6) | (1 << 5);
break;
case D2U_L2R: /* 从下到上,从左到右 */
regval |= (1 << 7) | (0 << 6) | (1 << 5);
break;
case D2U_R2L: /* 从下到上,从右到左 */
regval |= (1 << 7) | (1 << 6) | (1 << 5);
break;
}
dirreg = 0x36; /* 对绝大部分驱动IC, 由0x36寄存器控制 */
if (lcddev.id == 0x5510)
{
dirreg = 0x3600; /* 对于5510, 和其他驱动ic的寄存器有差异 */
}
/* 9341 & 7789 & 7796 要设置BGR位 */
if (lcddev.id == 0x9341 || lcddev.id == 0x7789 || lcddev.id == 0x7796)
{
regval |= 0x08;
}
lcd_write_reg(dirreg, regval);
if (lcddev.id != 0x1963) /* 1963不做坐标处理 */
{
if (regval & 0x20)
{
if (lcddev.width < lcddev.height) /* 交换X,Y */
{
temp = lcddev.width;
lcddev.width = lcddev.height;
lcddev.height = temp;
}
}
else
{
if (lcddev.width > lcddev.height) /* 交换X,Y */
{
temp = lcddev.width;
lcddev.width = lcddev.height;
lcddev.height = temp;
}
}
}
/* 设置显示区域(开窗)大小 */
if (lcddev.id == 0x5510)
{
lcd_wr_regno(lcddev.setxcmd);
lcd_wr_data(0);
lcd_wr_regno(lcddev.setxcmd + 1);
lcd_wr_data(0);
lcd_wr_regno(lcddev.setxcmd + 2);
lcd_wr_data((lcddev.width - 1) >> 8);
lcd_wr_regno(lcddev.setxcmd + 3);
lcd_wr_data((lcddev.width - 1) & 0xFF);
lcd_wr_regno(lcddev.setycmd);
lcd_wr_data(0);
lcd_wr_regno(lcddev.setycmd + 1);
lcd_wr_data(0);
lcd_wr_regno(lcddev.setycmd + 2);
lcd_wr_data((lcddev.height - 1) >> 8);
lcd_wr_regno(lcddev.setycmd + 3);
lcd_wr_data((lcddev.height - 1) & 0xFF);
}
else
{
lcd_wr_regno(lcddev.setxcmd);
lcd_wr_data(0);
lcd_wr_data(0);
lcd_wr_data((lcddev.width - 1) >> 8);
lcd_wr_data((lcddev.width - 1) & 0xFF);
lcd_wr_regno(lcddev.setycmd);
lcd_wr_data(0);
lcd_wr_data(0);
lcd_wr_data((lcddev.height - 1) >> 8);
lcd_wr_data((lcddev.height - 1) & 0xFF);
}
}
void lcd_draw_point(uint16_t x, uint16_t y, uint32_t color)
{
lcd_set_cursor(x, y); /* 设置光标位置 */
lcd_write_ram_prepare(); /* 开始写入GRAM */
LCD->LCD_RAM = color;
}
void lcd_ssd_backlight_set(uint8_t pwm)
{
lcd_wr_regno(0xBE); /* 配置PWM输出 */
lcd_wr_data(0x05); /* 1设置PWM频率 */
lcd_wr_data(pwm * 2.55); /* 2设置PWM占空比 */
lcd_wr_data(0x01); /* 3设置C */
lcd_wr_data(0xFF); /* 4设置D */
lcd_wr_data(0x00); /* 5设置E */
lcd_wr_data(0x00); /* 6设置F */
}
void lcd_display_dir(uint8_t dir)
{
lcddev.dir = dir; /* 竖屏/横屏 */
if (dir == 0) /* 竖屏 */
{
lcddev.width = 240;
lcddev.height = 320;
if (lcddev.id == 0x5510)
{
lcddev.wramcmd = 0x2C00;
lcddev.setxcmd = 0x2A00;
lcddev.setycmd = 0x2B00;
lcddev.width = 480;
lcddev.height = 800;
}
else if (lcddev.id == 0x1963)
{
lcddev.wramcmd = 0x2C; /* 设置写入GRAM的指令 */
lcddev.setxcmd = 0x2B; /* 设置写X坐标指令 */
lcddev.setycmd = 0x2A; /* 设置写Y坐标指令 */
lcddev.width = 480; /* 设置宽度480 */
lcddev.height = 800; /* 设置高度800 */
}
else /* 其他IC, 包括: 9341/5310/7789/7796/9806等IC */
{
lcddev.wramcmd = 0x2C;
lcddev.setxcmd = 0x2A;
lcddev.setycmd = 0x2B;
}
if (lcddev.id == 0x5310 || lcddev.id == 0x7796) /* 如果是5310/7796 则表示是 320*480分辨率 */
{
lcddev.width = 320;
lcddev.height = 480;
}
if (lcddev.id == 0X9806) /* 如果是9806 则表示是 480*800 分辨率 */
{
lcddev.width = 480;
lcddev.height = 800;
}
}
else /* 横屏 */
{
lcddev.width = 320; /* 默认宽度 */
lcddev.height = 240; /* 默认高度 */
if (lcddev.id == 0x5510)
{
lcddev.wramcmd = 0x2C00;
lcddev.setxcmd = 0x2A00;
lcddev.setycmd = 0x2B00;
lcddev.width = 800;
lcddev.height = 480;
}
else if (lcddev.id == 0x1963 || lcddev.id == 0x9806)
{
lcddev.wramcmd = 0x2C; /* 设置写入GRAM的指令 */
lcddev.setxcmd = 0x2A; /* 设置写X坐标指令 */
lcddev.setycmd = 0x2B; /* 设置写Y坐标指令 */
lcddev.width = 800; /* 设置宽度800 */
lcddev.height = 480; /* 设置高度480 */
}
else /* 其他IC, 包括:9341/5310/7789/7796等IC */
{
lcddev.wramcmd = 0x2C;
lcddev.setxcmd = 0x2A;
lcddev.setycmd = 0x2B;
}
if (lcddev.id == 0x5310 || lcddev.id == 0x7796) /* 如果是5310/7796 则表示是 320*480分辨率 */
{
lcddev.width = 480;
lcddev.height = 320;
}
}
lcd_scan_dir(DFT_SCAN_DIR); /* 默认扫描方向 */
}
void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_FSMC_CLK_ENABLE(); /* 使能FSMC时钟 */
__HAL_RCC_GPIOD_CLK_ENABLE(); /* 使能GPIOD时钟 */
__HAL_RCC_GPIOE_CLK_ENABLE(); /* 使能GPIOE时钟 */
/* 初始化PD0,1, 8,9,10,14,15 */
gpio_init_struct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 \
| GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15;
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽复用 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = GPIO_AF12_FSMC; /* 复用为FSMC */
HAL_GPIO_Init(GPIOD, &gpio_init_struct); /* 初始化 */
/* 初始化PE7,8,9,10,11,12,13,14,15 */
gpio_init_struct.Pin = GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 \
| GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
HAL_GPIO_Init(GPIOE, &gpio_init_struct);
}
void lcd_clear(uint16_t color)
{
uint32_t index = 0;
uint32_t totalpoint = lcddev.width;
totalpoint *= lcddev.height; /* 得到总点数 */
lcd_set_cursor(0x00, 0x0000); /* 设置光标位置 */
lcd_write_ram_prepare(); /* 开始写入GRAM */
for (index = 0; index < totalpoint; index++)
{
LCD->LCD_RAM = color;
}
}
主函数:
int main(void)
{
uint8_t x = 0;
uint8_t lcd_id[12];
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
g_point_color = RED;
sprintf((char *)lcd_id, "LCD ID:%04X", lcddev.id); /* 将LCD ID打印到lcd_id数组 */
lcd_clear(BLUE);
while (1)
{
lcd_show_string(10, 40, 240, 32, 32, "STM32", RED);
lcd_show_string(10, 80, 240, 24, 24, "TFTLCD TEST", RED);
lcd_show_string(10, 110, 240, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(10, 130, 240, 16, 16, (char *)lcd_id, RED); /* 显示LCD ID */
LED0_TOGGLE(); /* LED0闪烁 */
delay_ms(1000);
}
}
寄存器初始化:
/**
* @brief NT35510寄存器初始化代码
* @param 无
* @retval 无
*/
void lcd_ex_nt35510_reginit(void)
{
lcd_write_reg(0xF000, 0x55);
lcd_write_reg(0xF001, 0xAA);
lcd_write_reg(0xF002, 0x52);
lcd_write_reg(0xF003, 0x08);
lcd_write_reg(0xF004, 0x01);
/* AVDD Set AVDD 5.2V */
lcd_write_reg(0xB000, 0x0D);
lcd_write_reg(0xB001, 0x0D);
lcd_write_reg(0xB002, 0x0D);
/* AVDD ratio */
lcd_write_reg(0xB600, 0x34);
lcd_write_reg(0xB601, 0x34);
lcd_write_reg(0xB602, 0x34);
/* AVEE -5.2V */
lcd_write_reg(0xB100, 0x0D);
lcd_write_reg(0xB101, 0x0D);
lcd_write_reg(0xB102, 0x0D);
/* AVEE ratio */
lcd_write_reg(0xB700, 0x34);
lcd_write_reg(0xB701, 0x34);
lcd_write_reg(0xB702, 0x34);
/* VCL -2.5V */
lcd_write_reg(0xB200, 0x00);
lcd_write_reg(0xB201, 0x00);
lcd_write_reg(0xB202, 0x00);
/* VCL ratio */
lcd_write_reg(0xB800, 0x24);
lcd_write_reg(0xB801, 0x24);
lcd_write_reg(0xB802, 0x24);
/* VGH 15V (Free pump) */
lcd_write_reg(0xBF00, 0x01);
lcd_write_reg(0xB300, 0x0F);
lcd_write_reg(0xB301, 0x0F);
lcd_write_reg(0xB302, 0x0F);
/* VGH ratio */
lcd_write_reg(0xB900, 0x34);
lcd_write_reg(0xB901, 0x34);
lcd_write_reg(0xB902, 0x34);
/* VGL_REG -10V */
lcd_write_reg(0xB500, 0x08);
lcd_write_reg(0xB501, 0x08);
lcd_write_reg(0xB502, 0x08);
lcd_write_reg(0xC200, 0x03);
/* VGLX ratio */
lcd_write_reg(0xBA00, 0x24);
lcd_write_reg(0xBA01, 0x24);
lcd_write_reg(0xBA02, 0x24);
/* VGMP/VGSP 4.5V/0V */
lcd_write_reg(0xBC00, 0x00);
lcd_write_reg(0xBC01, 0x78);
lcd_write_reg(0xBC02, 0x00);
/* VGMN/VGSN -4.5V/0V */
lcd_write_reg(0xBD00, 0x00);
lcd_write_reg(0xBD01, 0x78);
lcd_write_reg(0xBD02, 0x00);
/* VCOM */
lcd_write_reg(0xBE00, 0x00);
lcd_write_reg(0xBE01, 0x64);
/* Gamma Setting */
lcd_write_reg(0xD100, 0x00);
lcd_write_reg(0xD101, 0x33);
lcd_write_reg(0xD102, 0x00);
lcd_write_reg(0xD103, 0x34);
lcd_write_reg(0xD104, 0x00);
lcd_write_reg(0xD105, 0x3A);
lcd_write_reg(0xD106, 0x00);
lcd_write_reg(0xD107, 0x4A);
lcd_write_reg(0xD108, 0x00);
lcd_write_reg(0xD109, 0x5C);
lcd_write_reg(0xD10A, 0x00);
lcd_write_reg(0xD10B, 0x81);
lcd_write_reg(0xD10C, 0x00);
lcd_write_reg(0xD10D, 0xA6);
lcd_write_reg(0xD10E, 0x00);
lcd_write_reg(0xD10F, 0xE5);
lcd_write_reg(0xD110, 0x01);
lcd_write_reg(0xD111, 0x13);
lcd_write_reg(0xD112, 0x01);
lcd_write_reg(0xD113, 0x54);
lcd_write_reg(0xD114, 0x01);
lcd_write_reg(0xD115, 0x82);
lcd_write_reg(0xD116, 0x01);
lcd_write_reg(0xD117, 0xCA);
lcd_write_reg(0xD118, 0x02);
lcd_write_reg(0xD119, 0x00);
lcd_write_reg(0xD11A, 0x02);
lcd_write_reg(0xD11B, 0x01);
lcd_write_reg(0xD11C, 0x02);
lcd_write_reg(0xD11D, 0x34);
lcd_write_reg(0xD11E, 0x02);
lcd_write_reg(0xD11F, 0x67);
lcd_write_reg(0xD120, 0x02);
lcd_write_reg(0xD121, 0x84);
lcd_write_reg(0xD122, 0x02);
lcd_write_reg(0xD123, 0xA4);
lcd_write_reg(0xD124, 0x02);
lcd_write_reg(0xD125, 0xB7);
lcd_write_reg(0xD126, 0x02);
lcd_write_reg(0xD127, 0xCF);
lcd_write_reg(0xD128, 0x02);
lcd_write_reg(0xD129, 0xDE);
lcd_write_reg(0xD12A, 0x02);
lcd_write_reg(0xD12B, 0xF2);
lcd_write_reg(0xD12C, 0x02);
lcd_write_reg(0xD12D, 0xFE);
lcd_write_reg(0xD12E, 0x03);
lcd_write_reg(0xD12F, 0x10);
lcd_write_reg(0xD130, 0x03);
lcd_write_reg(0xD131, 0x33);
lcd_write_reg(0xD132, 0x03);
lcd_write_reg(0xD133, 0x6D);
lcd_write_reg(0xD200, 0x00);
lcd_write_reg(0xD201, 0x33);
lcd_write_reg(0xD202, 0x00);
lcd_write_reg(0xD203, 0x34);
lcd_write_reg(0xD204, 0x00);
lcd_write_reg(0xD205, 0x3A);
lcd_write_reg(0xD206, 0x00);
lcd_write_reg(0xD207, 0x4A);
lcd_write_reg(0xD208, 0x00);
lcd_write_reg(0xD209, 0x5C);
lcd_write_reg(0xD20A, 0x00);
lcd_write_reg(0xD20B, 0x81);
lcd_write_reg(0xD20C, 0x00);
lcd_write_reg(0xD20D, 0xA6);
lcd_write_reg(0xD20E, 0x00);
lcd_write_reg(0xD20F, 0xE5);
lcd_write_reg(0xD210, 0x01);
lcd_write_reg(0xD211, 0x13);
lcd_write_reg(0xD212, 0x01);
lcd_write_reg(0xD213, 0x54);
lcd_write_reg(0xD214, 0x01);
lcd_write_reg(0xD215, 0x82);
lcd_write_reg(0xD216, 0x01);
lcd_write_reg(0xD217, 0xCA);
lcd_write_reg(0xD218, 0x02);
lcd_write_reg(0xD219, 0x00);
lcd_write_reg(0xD21A, 0x02);
lcd_write_reg(0xD21B, 0x01);
lcd_write_reg(0xD21C, 0x02);
lcd_write_reg(0xD21D, 0x34);
lcd_write_reg(0xD21E, 0x02);
lcd_write_reg(0xD21F, 0x67);
lcd_write_reg(0xD220, 0x02);
lcd_write_reg(0xD221, 0x84);
lcd_write_reg(0xD222, 0x02);
lcd_write_reg(0xD223, 0xA4);
lcd_write_reg(0xD224, 0x02);
lcd_write_reg(0xD225, 0xB7);
lcd_write_reg(0xD226, 0x02);
lcd_write_reg(0xD227, 0xCF);
lcd_write_reg(0xD228, 0x02);
lcd_write_reg(0xD229, 0xDE);
lcd_write_reg(0xD22A, 0x02);
lcd_write_reg(0xD22B, 0xF2);
lcd_write_reg(0xD22C, 0x02);
lcd_write_reg(0xD22D, 0xFE);
lcd_write_reg(0xD22E, 0x03);
lcd_write_reg(0xD22F, 0x10);
lcd_write_reg(0xD230, 0x03);
lcd_write_reg(0xD231, 0x33);
lcd_write_reg(0xD232, 0x03);
lcd_write_reg(0xD233, 0x6D);
lcd_write_reg(0xD300, 0x00);
lcd_write_reg(0xD301, 0x33);
lcd_write_reg(0xD302, 0x00);
lcd_write_reg(0xD303, 0x34);
lcd_write_reg(0xD304, 0x00);
lcd_write_reg(0xD305, 0x3A);
lcd_write_reg(0xD306, 0x00);
lcd_write_reg(0xD307, 0x4A);
lcd_write_reg(0xD308, 0x00);
lcd_write_reg(0xD309, 0x5C);
lcd_write_reg(0xD30A, 0x00);
lcd_write_reg(0xD30B, 0x81);
lcd_write_reg(0xD30C, 0x00);
lcd_write_reg(0xD30D, 0xA6);
lcd_write_reg(0xD30E, 0x00);
lcd_write_reg(0xD30F, 0xE5);
lcd_write_reg(0xD310, 0x01);
lcd_write_reg(0xD311, 0x13);
lcd_write_reg(0xD312, 0x01);
lcd_write_reg(0xD313, 0x54);
lcd_write_reg(0xD314, 0x01);
lcd_write_reg(0xD315, 0x82);
lcd_write_reg(0xD316, 0x01);
lcd_write_reg(0xD317, 0xCA);
lcd_write_reg(0xD318, 0x02);
lcd_write_reg(0xD319, 0x00);
lcd_write_reg(0xD31A, 0x02);
lcd_write_reg(0xD31B, 0x01);
lcd_write_reg(0xD31C, 0x02);
lcd_write_reg(0xD31D, 0x34);
lcd_write_reg(0xD31E, 0x02);
lcd_write_reg(0xD31F, 0x67);
lcd_write_reg(0xD320, 0x02);
lcd_write_reg(0xD321, 0x84);
lcd_write_reg(0xD322, 0x02);
lcd_write_reg(0xD323, 0xA4);
lcd_write_reg(0xD324, 0x02);
lcd_write_reg(0xD325, 0xB7);
lcd_write_reg(0xD326, 0x02);
lcd_write_reg(0xD327, 0xCF);
lcd_write_reg(0xD328, 0x02);
lcd_write_reg(0xD329, 0xDE);
lcd_write_reg(0xD32A, 0x02);
lcd_write_reg(0xD32B, 0xF2);
lcd_write_reg(0xD32C, 0x02);
lcd_write_reg(0xD32D, 0xFE);
lcd_write_reg(0xD32E, 0x03);
lcd_write_reg(0xD32F, 0x10);
lcd_write_reg(0xD330, 0x03);
lcd_write_reg(0xD331, 0x33);
lcd_write_reg(0xD332, 0x03);
lcd_write_reg(0xD333, 0x6D);
lcd_write_reg(0xD400, 0x00);
lcd_write_reg(0xD401, 0x33);
lcd_write_reg(0xD402, 0x00);
lcd_write_reg(0xD403, 0x34);
lcd_write_reg(0xD404, 0x00);
lcd_write_reg(0xD405, 0x3A);
lcd_write_reg(0xD406, 0x00);
lcd_write_reg(0xD407, 0x4A);
lcd_write_reg(0xD408, 0x00);
lcd_write_reg(0xD409, 0x5C);
lcd_write_reg(0xD40A, 0x00);
lcd_write_reg(0xD40B, 0x81);
lcd_write_reg(0xD40C, 0x00);
lcd_write_reg(0xD40D, 0xA6);
lcd_write_reg(0xD40E, 0x00);
lcd_write_reg(0xD40F, 0xE5);
lcd_write_reg(0xD410, 0x01);
lcd_write_reg(0xD411, 0x13);
lcd_write_reg(0xD412, 0x01);
lcd_write_reg(0xD413, 0x54);
lcd_write_reg(0xD414, 0x01);
lcd_write_reg(0xD415, 0x82);
lcd_write_reg(0xD416, 0x01);
lcd_write_reg(0xD417, 0xCA);
lcd_write_reg(0xD418, 0x02);
lcd_write_reg(0xD419, 0x00);
lcd_write_reg(0xD41A, 0x02);
lcd_write_reg(0xD41B, 0x01);
lcd_write_reg(0xD41C, 0x02);
lcd_write_reg(0xD41D, 0x34);
lcd_write_reg(0xD41E, 0x02);
lcd_write_reg(0xD41F, 0x67);
lcd_write_reg(0xD420, 0x02);
lcd_write_reg(0xD421, 0x84);
lcd_write_reg(0xD422, 0x02);
lcd_write_reg(0xD423, 0xA4);
lcd_write_reg(0xD424, 0x02);
lcd_write_reg(0xD425, 0xB7);
lcd_write_reg(0xD426, 0x02);
lcd_write_reg(0xD427, 0xCF);
lcd_write_reg(0xD428, 0x02);
lcd_write_reg(0xD429, 0xDE);
lcd_write_reg(0xD42A, 0x02);
lcd_write_reg(0xD42B, 0xF2);
lcd_write_reg(0xD42C, 0x02);
lcd_write_reg(0xD42D, 0xFE);
lcd_write_reg(0xD42E, 0x03);
lcd_write_reg(0xD42F, 0x10);
lcd_write_reg(0xD430, 0x03);
lcd_write_reg(0xD431, 0x33);
lcd_write_reg(0xD432, 0x03);
lcd_write_reg(0xD433, 0x6D);
lcd_write_reg(0xD500, 0x00);
lcd_write_reg(0xD501, 0x33);
lcd_write_reg(0xD502, 0x00);
lcd_write_reg(0xD503, 0x34);
lcd_write_reg(0xD504, 0x00);
lcd_write_reg(0xD505, 0x3A);
lcd_write_reg(0xD506, 0x00);
lcd_write_reg(0xD507, 0x4A);
lcd_write_reg(0xD508, 0x00);
lcd_write_reg(0xD509, 0x5C);
lcd_write_reg(0xD50A, 0x00);
lcd_write_reg(0xD50B, 0x81);
lcd_write_reg(0xD50C, 0x00);
lcd_write_reg(0xD50D, 0xA6);
lcd_write_reg(0xD50E, 0x00);
lcd_write_reg(0xD50F, 0xE5);
lcd_write_reg(0xD510, 0x01);
lcd_write_reg(0xD511, 0x13);
lcd_write_reg(0xD512, 0x01);
lcd_write_reg(0xD513, 0x54);
lcd_write_reg(0xD514, 0x01);
lcd_write_reg(0xD515, 0x82);
lcd_write_reg(0xD516, 0x01);
lcd_write_reg(0xD517, 0xCA);
lcd_write_reg(0xD518, 0x02);
lcd_write_reg(0xD519, 0x00);
lcd_write_reg(0xD51A, 0x02);
lcd_write_reg(0xD51B, 0x01);
lcd_write_reg(0xD51C, 0x02);
lcd_write_reg(0xD51D, 0x34);
lcd_write_reg(0xD51E, 0x02);
lcd_write_reg(0xD51F, 0x67);
lcd_write_reg(0xD520, 0x02);
lcd_write_reg(0xD521, 0x84);
lcd_write_reg(0xD522, 0x02);
lcd_write_reg(0xD523, 0xA4);
lcd_write_reg(0xD524, 0x02);
lcd_write_reg(0xD525, 0xB7);
lcd_write_reg(0xD526, 0x02);
lcd_write_reg(0xD527, 0xCF);
lcd_write_reg(0xD528, 0x02);
lcd_write_reg(0xD529, 0xDE);
lcd_write_reg(0xD52A, 0x02);
lcd_write_reg(0xD52B, 0xF2);
lcd_write_reg(0xD52C, 0x02);
lcd_write_reg(0xD52D, 0xFE);
lcd_write_reg(0xD52E, 0x03);
lcd_write_reg(0xD52F, 0x10);
lcd_write_reg(0xD530, 0x03);
lcd_write_reg(0xD531, 0x33);
lcd_write_reg(0xD532, 0x03);
lcd_write_reg(0xD533, 0x6D);
lcd_write_reg(0xD600, 0x00);
lcd_write_reg(0xD601, 0x33);
lcd_write_reg(0xD602, 0x00);
lcd_write_reg(0xD603, 0x34);
lcd_write_reg(0xD604, 0x00);
lcd_write_reg(0xD605, 0x3A);
lcd_write_reg(0xD606, 0x00);
lcd_write_reg(0xD607, 0x4A);
lcd_write_reg(0xD608, 0x00);
lcd_write_reg(0xD609, 0x5C);
lcd_write_reg(0xD60A, 0x00);
lcd_write_reg(0xD60B, 0x81);
lcd_write_reg(0xD60C, 0x00);
lcd_write_reg(0xD60D, 0xA6);
lcd_write_reg(0xD60E, 0x00);
lcd_write_reg(0xD60F, 0xE5);
lcd_write_reg(0xD610, 0x01);
lcd_write_reg(0xD611, 0x13);
lcd_write_reg(0xD612, 0x01);
lcd_write_reg(0xD613, 0x54);
lcd_write_reg(0xD614, 0x01);
lcd_write_reg(0xD615, 0x82);
lcd_write_reg(0xD616, 0x01);
lcd_write_reg(0xD617, 0xCA);
lcd_write_reg(0xD618, 0x02);
lcd_write_reg(0xD619, 0x00);
lcd_write_reg(0xD61A, 0x02);
lcd_write_reg(0xD61B, 0x01);
lcd_write_reg(0xD61C, 0x02);
lcd_write_reg(0xD61D, 0x34);
lcd_write_reg(0xD61E, 0x02);
lcd_write_reg(0xD61F, 0x67);
lcd_write_reg(0xD620, 0x02);
lcd_write_reg(0xD621, 0x84);
lcd_write_reg(0xD622, 0x02);
lcd_write_reg(0xD623, 0xA4);
lcd_write_reg(0xD624, 0x02);
lcd_write_reg(0xD625, 0xB7);
lcd_write_reg(0xD626, 0x02);
lcd_write_reg(0xD627, 0xCF);
lcd_write_reg(0xD628, 0x02);
lcd_write_reg(0xD629, 0xDE);
lcd_write_reg(0xD62A, 0x02);
lcd_write_reg(0xD62B, 0xF2);
lcd_write_reg(0xD62C, 0x02);
lcd_write_reg(0xD62D, 0xFE);
lcd_write_reg(0xD62E, 0x03);
lcd_write_reg(0xD62F, 0x10);
lcd_write_reg(0xD630, 0x03);
lcd_write_reg(0xD631, 0x33);
lcd_write_reg(0xD632, 0x03);
lcd_write_reg(0xD633, 0x6D);
/* LV2 Page 0 enable */
lcd_write_reg(0xF000, 0x55);
lcd_write_reg(0xF001, 0xAA);
lcd_write_reg(0xF002, 0x52);
lcd_write_reg(0xF003, 0x08);
lcd_write_reg(0xF004, 0x00);
/* Display control */
lcd_write_reg(0xB100, 0xCC);
lcd_write_reg(0xB101, 0x00);
/* Source hold time */
lcd_write_reg(0xB600, 0x05);
/* Gate EQ control */
lcd_write_reg(0xB700, 0x70);
lcd_write_reg(0xB701, 0x70);
/* Source EQ control (Mode 2) */
lcd_write_reg(0xB800, 0x01);
lcd_write_reg(0xB801, 0x03);
lcd_write_reg(0xB802, 0x03);
lcd_write_reg(0xB803, 0x03);
/* Inversion mode (2-dot) */
lcd_write_reg(0xBC00, 0x02);
lcd_write_reg(0xBC01, 0x00);
lcd_write_reg(0xBC02, 0x00);
/* Timing control 4H w/ 4-delay */
lcd_write_reg(0xC900, 0xD0);
lcd_write_reg(0xC901, 0x02);
lcd_write_reg(0xC902, 0x50);
lcd_write_reg(0xC903, 0x50);
lcd_write_reg(0xC904, 0x50);
lcd_write_reg(0x3500, 0x00);
lcd_write_reg(0x3A00, 0x55); /* 16-bit/pixel */
lcd_wr_regno(0x1100);
delay_us(120);
lcd_wr_regno(0x2900);
}
测试结果:

修改以下:
int main(void)
{
uint8_t x = 0;
uint8_t lcd_id[12];
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
g_point_color = RED;
sprintf((char *)lcd_id, "LCD ID:%04X", lcddev.id); /* 将LCD ID打印到lcd_id数组 */
lcd_clear(BLUE);
lcd_fill(150, 150, 250, 250, RED);
lcd_draw_line(300, 200, 400, 300, RED);
lcd_draw_hline(100, 300, 200, RED);
lcd_draw_rectangle(100, 350, 400, 350, RED);
lcd_draw_circle(100, 400, 50, RED);
lcd_fill_circle(200, 500, 100, RED);
while (1)
{
lcd_show_string(10, 40, 240, 32, 32, "STM32", RED);
lcd_show_string(10, 80, 240, 24, 24, "TFTLCD TEST", RED);
lcd_show_string(10, 110, 240, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(10, 130, 240, 16, 16, (char *)lcd_id, RED); /* 显示LCD ID */
LED0_TOGGLE(); /* LED0闪烁 */
delay_ms(1000);
}
}
结果:
