当前位置: 首页 > news >正文

2-1嵌入式进阶指南:P169H002 基于 ST7789T3 和 CST816D 驱动的 LCD 触摸显示屏开发手册(3)

基于P169H002的LCD 触摸显示屏的驱动板制作

学会驱动板制作就可以将LCD 触摸显示屏添加到你的任何项目中。
本教程覆盖全面,看完即可自己从0完成,包含了:
硬件: 原理图、PCB 、器件选型。
软件:新建工程、LCD底层驱动、触摸屏底层驱动、LVGL的UI界面。

本文是基于P169H002的LCD触摸显示屏的第三部分。
如果有需要可以点击下方链接跳转
前一节:第二部分:软件底层基础实现
后一节:触摸屏的驱动程序 (未完待续。。。)

第三部分:LCD屏幕驱动程序编写

在这之前,我们已经完成了P169H002的主控板制作,通过软件验证了硬件没有问题之后,现在开始写LCD屏幕显示的底层驱动。完成底层驱动后可以自己设计UI界面或者利用LVGL实现界面显示。

1、PWM调光

在文章最开始提到了LED背光是共阴极,所以背光引脚给低电平点亮。
但为了能调节背光的亮度(即屏幕的亮度),所以用到了MOS管控制。

①结合MOS管的共阴极LED背光调光原理

图中用到的MOS管是 N—MOS。
当LCD_BLK输出2.5V以上时,此时N—MOS导通,此时FPC连接器的17引脚连接的是P169H002屏幕模块的LED背光共阴极引脚被接通到GND,LED点亮。
所以我们就可以通过输出高电平在2.5V以上的PWM来调整LCD屏幕的亮度了。
之所以不直接用PWM连接LCD的背光引脚(FPC连接器的17引脚),是因为MCU的GPIO的电流通过能力有限,LCD屏幕的背光LED正常工作需要比较大的电流,让MOS管去承担背光电流更加安全且高效。

在这里插入图片描述

②定时器PWM输出初始化

TIMER.h文件

#ifndef _TIMER_H_
#define _TIMER_H_#include "stm32f4xx.h"/* 宏定义 */
#define TIM3_PERIOD         300
#define TIM3_PULSE_INIT     0/* 外部变量 */
extern TIM_HandleTypeDef TIMER3_Handle;
/* 函数声明 */
void TIM3_PWM_Init(void);#endif

TIMER.c文件

#include "TIMER.h"TIM_HandleTypeDef TIMER3_Handle;void TIM3_PWM_Init(void)
{TIM_OC_InitTypeDef TIM_OC_InitStructure;/* 时基单元配置 */TIMER3_Handle.Instance = TIM3;TIMER3_Handle.Init.Prescaler = 100 - 1;    //PSCTIMER3_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;TIMER3_Handle.Init.Period = TIM3_PERIOD;           //ARRTIMER3_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;TIMER3_Handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;HAL_TIM_PWM_Init(&TIMER3_Handle);/* 配置PWM输出通道 */TIM_OC_InitStructure.OCMode = TIM_OCMODE_PWM1;TIM_OC_InitStructure.Pulse = TIM3_PULSE_INIT;TIM_OC_InitStructure.OCPolarity = TIM_OCPOLARITY_HIGH;TIM_OC_InitStructure.OCFastMode = TIM_OCFAST_DISABLE;HAL_TIM_PWM_ConfigChannel(&TIMER3_Handle,&TIM_OC_InitStructure,TIM_CHANNEL_3);
}void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{GPIO_InitTypeDef GPIO_InitStructure;if(htim->Instance == TIM3){__HAL_RCC_TIM3_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();GPIO_InitStructure.Pin = GPIO_PIN_0;GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStructure.Alternate = GPIO_AF2_TIM3;HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);}
}

2、通信驱动

P169H022这款屏幕采用的是ST7789T3 4线串行通信模式(可以用硬件SPI或软件模拟来实现),这样的优点是实现简单,但是串行通信的速率远低于并行通信。

①HAL库的SPI初始化

在这里插入图片描述
通过 4线串行通信 的时序图可以得出如下配置

(1)SPI模式配置:

采用硬件SPI进行如下配置
SPI_MODE_MASTER:SPI主机模式。
SPI_DIRECTION_2LINES:只用到MOSI但这样配置适配4线串行通信。
SPI_DATASIZE_8BIT:一次传输8位
SPI_POLARITY_HIGH:CPOL = 1,时钟空闲时为高电平。
SPI_PHASE_2EDGE:CPHA = 1,数据在时钟的第二个边沿采样。
SPI_FIRSTBIT_MSB:高位先行。
SPI_NSS_SOFT:软件控制CS片选。
SPI_BAUDRATEPRESCALER_2:SPI时钟频率 = 系统时钟频率 / 2。

其他配置
TIMode:禁用TI帧格式模式,用标准的摩托罗拉SPI帧格式。
CRCCalculation:禁用CRC校验字节,对于显示屏驱动通常不需要。
CRCPolynomial:即使CRC计算被禁用,这个值仍然需要设置。

(2)SPI外设相关文件

SPI.h文件

#ifndef _SPI_H_
#define _SPI_H_#include "stm32f4xx.h"/* ST7789T3底层驱动方式 */
#define DRIVER_MODE  HARDWARE_SPI
#define HARDWARE_SPI 0
#define SOFTWARE_SPI 1/* 外部变量声明 */
extern SPI_HandleTypeDef SPI_ST7789T3;
extern DMA_HandleTypeDef DMA_SPI1_TX;/* 函数声明 */
void SPI_Init(void);
void SPI_Write_Byte(uint8_t Byte);
#endif

SPI.c文件

#include "SPI.h"SPI_HandleTypeDef SPI_ST7789T3;
DMA_HandleTypeDef DMA_SPI1_TX;void SPI_Init(void)
{SPI_ST7789T3.Instance = SPI1;SPI_ST7789T3.Init.Mode = SPI_MODE_MASTER;SPI_ST7789T3.Init.Direction = SPI_DIRECTION_2LINES;SPI_ST7789T3.Init.DataSize = SPI_DATASIZE_8BIT;SPI_ST7789T3.Init.CLKPolarity = SPI_POLARITY_HIGH;SPI_ST7789T3.Init.CLKPhase = SPI_PHASE_2EDGE;SPI_ST7789T3.Init.NSS = SPI_NSS_SOFT;SPI_ST7789T3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;SPI_ST7789T3.Init.FirstBit = SPI_FIRSTBIT_MSB;SPI_ST7789T3.Init.TIMode = SPI_TIMODE_DISABLE;SPI_ST7789T3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;SPI_ST7789T3.Init.CRCPolynomial = 10;HAL_SPI_Init(&SPI_ST7789T3);
}void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{GPIO_InitTypeDef GPIO_InitStructure;if(hspi->Instance == SPI1){__HAL_RCC_SPI1_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_DMA2_CLK_ENABLE();//SDA和SCLK引脚配置GPIO_InitStructure.Pin = GPIO_PIN_3|GPIO_PIN_5;GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;GPIO_InitStructure.Pull = GPIO_NOPULL;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStructure.Alternate = GPIO_AF5_SPI1;HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);//DMA配置DMA_SPI1_TX.Instance = DMA2_Stream2;DMA_SPI1_TX.Init.Channel = DMA_CHANNEL_2;DMA_SPI1_TX.Init.Direction = DMA_MEMORY_TO_PERIPH;DMA_SPI1_TX.Init.PeriphInc = DMA_PINC_DISABLE;DMA_SPI1_TX.Init.MemInc = DMA_MINC_ENABLE;DMA_SPI1_TX.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;DMA_SPI1_TX.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;DMA_SPI1_TX.Init.Mode = DMA_NORMAL;DMA_SPI1_TX.Init.Priority = DMA_PRIORITY_LOW;DMA_SPI1_TX.Init.FIFOMode = DMA_FIFOMODE_DISABLE;HAL_DMA_Init(&DMA_SPI1_TX);__HAL_LINKDMA(&SPI_ST7789T3,hdmatx,DMA_SPI1_TX);HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 5, 0);HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);}
}//*****************************
/*** @brief   ST7789T3_4线串行Write函数* @param   Byte:要写入的一字节数据* @retval  None
*/
//*****************************
void SPI_Write_Byte(uint8_t Byte)
{#if DRIVER_MODE == HARDWARE_SPI     //硬件SPIHAL_SPI_Transmit(&SPI_ST7789T3,&Byte,1,1);#else                               //软件SPIuint8_t i;for(i = 0; i < 8; i++){ST7789T3_SCLK_RESET();    //SCLK高读取数据,低写入数据if(Byte & 0x80)           //高位先行 MSB{ST7789T3_SDA_SET();   }else{ST7789T3_SDA_RESET();}ST7789T3_SCLK_SET();Byte <<= 1;               //左移一位,继续写入Bit}#endif//采用条件编译,让底层通信可选择软件或硬件来驱动LCD屏幕。
}

②ST7789T3驱动程序

用SPI与ST7789T3按芯片厂商的规定来通信。

(1)LCD显示方式

写一个LCD屏幕的驱动第一步就是考虑到屏幕显示方式的问题。
利用宏定义来定义好屏幕驱动的大小、方向(竖向横行)和显存写入顺序(eg:先行后列)。

(2)硬件接口宏定义

用宏定义替代具体的GPIO接口可以让程序复用性提高。
还有API宏来代替常用操作可以提高效率和可读性。

(3)阅读芯片手册控制LCD屏幕

利用芯片厂商提供的命令来让LCD显示我们希望的图像。
阅读芯片手册我们才知道初始化LCD屏幕我们需要配置哪些参数。
但是LCD显示时有很多的屏幕专业性参数,如果看不懂可以直接用默认值,不必纠结,除非你对显示性能有极高的要求(eg:低功耗,清晰度,屏幕刷新速度),这些要是展开的话就太多了,感兴趣可以自己仔细研究一下各各参数。
用到的命令配置后边我都写了注释,可以大致理解命令在干什么。

(4)ST7789T3驱动相关文件

ST7789T3.h文件

#ifndef _ST7789T3_H_
#define _ST7789T3_H_/* 头文件包含 */
#include "stm32f4xx.h"
#include "SPI.h"
#include "TIMER.h"/* LCD屏幕参数 */
#define USE_HORIZONTAL 0    //0,1为竖屏。2,3为横屏#if USE_HORIZONTAL == 0 || USE_HORIZONTAL == 1#define LCD_W 240#define LCD_H 280
#else#define LCD_W 280#define LCD_H 240
#endif/* -----------------ST7789T3硬件接口----------------- */
#define ST7789T3_SCLK_PORT       GPIOB
#define ST7789T3_SCLK_PIN        GPIO_PIN_3#define ST7789T3_SDA_PORT        GPIOB
#define ST7789T3_SDA_PIN         GPIO_PIN_5#define ST7789T3_RST_PORT        GPIOB
#define ST7789T3_RST_PIN         GPIO_PIN_7#define ST7789T3_DC_PORT         GPIOB
#define ST7789T3_DC_PIN          GPIO_PIN_9#define ST7789T3_CS_PORT         GPIOB
#define ST7789T3_CS_PIN          GPIO_PIN_8#define LCD_BLK_PORT             GPIOB
#define LCD_BLK_PIN              GPIO_PIN_0S//API宏定义
#define ST7789T3_SCLK_RESET()      HAL_GPIO_WritePin(ST7789T3_SCLK_PORT,ST7789T3_SCLK_PIN,GPIO_PIN_RESET)
#define ST7789T3_SCLK_SET()        HAL_GPIO_WritePin(ST7789T3_SCLK_PORT,ST7789T3_SCLK_PIN,GPIO_PIN_SET)#define ST7789T3_SDA_RESET()       HAL_GPIO_WritePin(ST7789T3_SDA_PORT,ST7789T3_SDA_PIN,GPIO_PIN_RESET)
#define ST7789T3_SDA_SET()         HAL_GPIO_WritePin(ST7789T3_SDA_PORT,ST7789T3_SDA_PIN,GPIO_PIN_SET)#define ST7789T3_RST_RESET()       HAL_GPIO_WritePin(ST7789T3_RST_PORT,ST7789T3_RST_PIN,GPIO_PIN_RESET)
#define ST7789T3_RST_SET()         HAL_GPIO_WritePin(ST7789T3_RST_PORT,ST7789T3_RST_PIN,GPIO_PIN_SET)#define ST7789T3_DC_RESET()        HAL_GPIO_WritePin(ST7789T3_DC_PORT,ST7789T3_DC_PIN,GPIO_PIN_RESET)
#define ST7789T3_DC_SET()          HAL_GPIO_WritePin(ST7789T3_DC_PORT,ST7789T3_DC_PIN,GPIO_PIN_SET)#define ST7789T3_CS_RESET()        HAL_GPIO_WritePin(ST7789T3_CS_PORT,ST7789T3_CS_PIN,GPIO_PIN_RESET)
#define ST7789T3_CS_SET()          HAL_GPIO_WritePin(ST7789T3_CS_PORT,ST7789T3_CS_PIN,GPIO_PIN_SET)#define LCD_BLK_RESET()            HAL_GPIO_WritePin(ST7789T3_BLK_PORT,ST7789T3_BLK_PIN,GPIO_PIN_RESET)
#define LCD_BLK_SET()              HAL_GPIO_WritePin(ST7789T3_BLK_PORT,ST7789T3_BLK_PIN,GPIO_PIN_SET)
/* --------------------END-------------------- *//*-----------------------ST778T3命令宏定义区------------------*/
#define ST7789T3_CMD_CASET       0X2A    //Column Address Set, 列地址设置
#define ST7789T3_CMD_RASET       0X2B    //Row Address Set, 行地址设置
#define ST7789T3_CMD_RAMWR       0X2C    //Memory write, 内存写入#define ST7789T3_CMD_MADCTL      0X36    //Memory Data Access Control,内存数据访问控制
#define ST7789T3_CMD_COLMOD      0X3A    //Interface Pixel Format,界面像素格式
#define ST7789T3_CMD_PORCTRL     0XB2    //Porch Setting,设置显示时序中的"空白间隔",这些间隔虽然不显示图像,但对于确保显示稳定、同步正确和图像定位至关重要
#define ST7789T3_CMD_GCTRL       0XB7    //Gate Control,配置栅极驱动电压
#define ST7789T3_CMD_VCOMS       0XBB    //VCOMS Setting,公共电极电压,施加在液晶层公共端的参考电压,用于与像素电压形成电压差来驱动液晶分子。主要影响图像闪烁、对比度、均匀性
#define ST7789T3_CMD_LCMCTRL     0XC0    //LCM Control,硬件加速、实现屏幕自动旋转、实现屏幕自动旋转等
#define ST7789T3_CMD_VDVVRHEN    0XC2    //VDV and VRH Command Enable,VDV和VRH命令启用
#define ST7789T3_CMD_VRHS        0XC3    //VRH Set,电压调节器高电平设置,影响图像高亮部分该有多亮
#define ST7789T3_CMD_VDVS        0XC4    //VDV Set,VCOM驱动电压,主要用来消除屏幕闪烁和提高显示均匀性
#define ST7789T3_CMD_FRCTRL2     0XC6    //Frame Rate Control in Normal Mode,正常模式下的帧率控制,主要用来提升显示色彩深度和平滑度
#define ST7789T3_CMD_PWCTRL1     0XD0    //Power Control 1,通过调节AVDD、AVCL和VDS来优化显示性能和功耗平衡
#define ST7789T3_CMD_PVGAMCTRL   0XE0    //Positive Voltage Gamma Control,正电压伽玛控制,影响高亮细节、亮部对比度和整体图像的亮度分布,需要与负电压Gamma配合实现完整的伽马校正
#define ST7789T3_CMD_NVGAMCTRL   0XE1    //Negative Voltage Gamma Control ,负电压伽玛控制,主要影响黑色纯度、暗部细节、阴影层次和低亮度色彩准确性,与正电压Gamma控制共同构成完整的伽马校正
#define ST7789T3_CMD_INVON       0X21    //Display Inversion On,显示反转打开,用于夜间模式、特殊视觉效果或在特定光照条件下改善可读性,但会破坏正常的色彩表现
#define ST7789T3_CMD_DISPON      0X29    //Display On,开启显示,默认关闭
/************************END**************************//*-----------------------函数声明区------------------*/
void LCD_Init(void);             //LCD初始化函数
void LCD_Address_Set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); //LCD显示范围设置函数
void ST7789T3_Write_HalfWord(uint16_t Data_HalfWord);   //ST7789T3写16位数据/************************END**************************/#endif

C函数的文件就不多说了,基本上每句都有注释。

ST7789T3.c文件

#include "ST7789T3.h"/* ------------------------------------------------ST7789T3函数-------------------------------------------------- */
//*****************************
/*** @brief  ST7789T3硬件GPIO初始化* @param  None* @retval None
*/
//*****************************
static void ST7789T3_GPIO_Init(void)
{/* RST(复位) D/C(数据/命令) CS(片选) 引脚初始化  */__HAL_RCC_GPIOB_CLK_ENABLE();GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = ST7789T3_RST_PIN | ST7789T3_DC_PIN | ST7789T3_CS_PIN;GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);/* RST低电平复位,CS低电平选中 */HAL_GPIO_WritePin(GPIOB,ST7789T3_RST_PIN | ST7789T3_DC_PIN | ST7789T3_CS_PIN,GPIO_PIN_SET);
}//*****************************
/*** @brief  ST7789T3写入8位数据函数* @param  Byte:要写入的8位数据* @retval None
*/
//*****************************
static void ST7789T3_Write_Byte(uint8_t Byte)
{SPI_Write_Byte(Byte);
}//*****************************
/*** @brief  ST7789T3写入16位数据函数* @param  DATA_HalfWord:要写入的16位数据* @retval None
*/
//*****************************
void ST7789T3_Write_HalfWord(uint16_t Data_HalfWord)
{#if DRIVER_MODE == HARDWARE_SPI     //硬件SPIuint8_t Temp[2];Temp[0] = (Data_HalfWord >> 8) & 0XFF;      //16位 高8位移动低8位 与上0XFF预防错误Temp[1] = Data_HalfWord & 0XFF;             //Temp[0] 存储高8位,Temp[1] 存储低8位HAL_SPI_Transmit(&SPI_ST7789T3,Temp,2,1);   //软件触发 SPI 发送#else/* 调用两次发送字节函数,发送16位数据 */SPI_Write_Byte((Data_HalfWord >> 8) & 0XFF);SPI_Write_Byte(Data_HalfWord & 0XFF);#endif
}//*****************************
/*** @brief  ST7789T3写入一字节命令函数* @param  Command:要写入一字节的命令* @retval None
*/
//*****************************
static void ST7789T3_Write_Command(uint8_t Command)
{ST7789T3_DC_RESET();  //DC低电平,写命令ST7789T3_Write_Byte(Command);ST7789T3_DC_SET();  //DC高电平,写完命令之后,直接切换写数据,因为一般MCU发送命令后,ST7789T3准备接收数据
}//*****************************
/*** @brief  ST7789T3进入睡眠模式睡眠模式:此命令使液晶显示模块进入最低功耗模式。在此模式下,DC/DC 转换器停止工作,内部振荡器停止,面板扫描停止。MCU 接口和存储器仍在工作,存储器保持其内容。* @param  None* @retval None
*/
//*****************************
static void ST7789T3_SleepIn(void)
{ST7789T3_Write_Command(0X10);//在发送此命令后,需要等待,才能向模块发送任何新命令,以便供电电压和时钟电路稳定。HAL_Delay(100);
}//*****************************
/*** @brief  ST7789T3退出睡眠模式DC/DC转换器被启用,内部显示振荡器启动,并且面板扫描开始。* @param  None* @retval None
*/
//*****************************
static void ST7789T3_SleepOut(void)
{ST7789T3_Write_Command(0X11);HAL_Delay(100);
}
/* ****************************************************END********************************************************** *//* ----------------------------------------------封装成LCD函数------------------------------------------------------ */
/* ----------------------------------------------封装成LCD函数------------------------------------------------------ */
//*****************************
/*** @brief  LCD显示范围设置函数。在控制LCD显示之前都要规定好地址范围之后,填充各各点的像素。* @param  X1,X2:设置列的起止地址Y1,Y2:设置行的起止地址* @retval None
*/
//*****************************
void LCD_Address_Set(uint16_t X1, uint16_t X2, uint16_t Y1, uint16_t Y2)
{/* 列地址设置,需要两个16位数据确定列地址的起止位置 */ST7789T3_Write_Command(ST7789T3_CMD_CASET); ST7789T3_Write_HalfWord(X1);ST7789T3_Write_HalfWord(X2);/* 行地址设置,也需要两个16位数据确定行地址的起止位置 */ST7789T3_Write_Command(ST7789T3_CMD_RASET);ST7789T3_Write_HalfWord(Y1);ST7789T3_Write_HalfWord(Y2);/* 内存写入  */ST7789T3_Write_Command(ST7789T3_CMD_RAMWR);/* 在发送该命令后,后续通过串行传输的所有数据,将按照此前设定的列地址、行地址依次写入帧内存的对应位置,直至发送新命令(如停止写入的命令)或地址范围结束*//* 发送 0X2C 命令后,驱动芯片进入 “数据接收就绪” 状态,此时 MCU 传输的 RGB 像素数据(如 16 位 / 18 位颜色数据)会被逐像素存储到帧内存中。 *//* 按 “先列后行” 或 “先行后列” 的顺序填充至(XE, YE)的地址范围*//* 若需写入连续区域的多个像素(如整屏图像),发送 0X2C 后可连续传输所有像素数据,无需重复发送命令,ST7789T3会自动递增地址指针,直至覆盖设定的地址范围。*/
}//*****************************
/*** @brief  LCD初始化函数* @param  None* @retval None
*/
//*****************************
void LCD_Init(void)
{/* 配置驱动芯片GPIO */ST7789T3_GPIO_Init();TIM3_PWM_Init();SPI_Init();/* 拉低GPIO片选,开始操作ST7789T3 */ST7789T3_CS_RESET();/* 复位操作 *///拉低复位引脚开始复位ST7789T3_RST_RESET();HAL_Delay(100);//拉高停止复位ST7789T3_RST_SET();HAL_Delay(100);/* 唤醒ST7789T3 */ST7789T3_SleepOut();/* 设置LCD画面显示方向 */ST7789T3_Write_Command(ST7789T3_CMD_MADCTL);if(USE_HORIZONTAL == 0){/* 默认方向:配置列地址从左到右递增(MX=0)行地址从上到下递增(MY=0)RGB 颜色顺序为默认(RGB=0)无地址交换(MV=0) */ST7789T3_Write_Byte(0x00);}else if(USE_HORIZONTAL == 1){/* 横向反转:通过位 7(MY=1,行地址反转,从上到下变为从下到上)和位 6(MX=1,列地址反转,从左到右变为从右到左)实现横向画面反转,同时保留 RGB 默认顺序 */ST7789T3_Write_Byte(0xC0);}else if(USE_HORIZONTAL == 2){/* 纵向正向:通过位 5(MV=1,行 / 列地址交换,实现纵向显示)位 4(ML=1,扫描方向调整)等组合适配纵向屏幕的像素扫描顺序 */ST7789T3_Write_Byte(0x70);}else{/* 备用横向方向:通过位 7(MY=1)位 4(ML=0)等组合,实现横向正向显示确保画面无反转、扫描顺序正确 */ST7789T3_Write_Byte(0xA0);}/* 配置像素格式:配置为 16 位像素格式(RGB565,65K 色) */ST7789T3_Write_Command(ST7789T3_CMD_COLMOD);ST7789T3_Write_Byte(0X05);/* Porch 设置为默认值 */ST7789T3_Write_Command(ST7789T3_CMD_PORCTRL);ST7789T3_Write_Byte(0X0C);ST7789T3_Write_Byte(0X0C);ST7789T3_Write_Byte(0X00);ST7789T3_Write_Byte(0X33);ST7789T3_Write_Byte(0X33);/* 配置栅极驱动电压为默认值 */ST7789T3_Write_Command(ST7789T3_CMD_GCTRL);ST7789T3_Write_Byte(0X35);/* 公共电极电压设置 */ST7789T3_Write_Command(ST7789T3_CMD_GCTRL);ST7789T3_Write_Byte(0X19);/* LCM Control 为默认值 */ST7789T3_Write_Command(ST7789T3_CMD_LCMCTRL);ST7789T3_Write_Byte(0X2C);/* VDV和VRH命令不启用 */ST7789T3_Write_Command(ST7789T3_CMD_VDVVRHEN);ST7789T3_Write_Byte(0X01);/* -4.45 +(vcom + vcom偏移 - vdv) */ST7789T3_Write_Command(ST7789T3_CMD_VRHS);ST7789T3_Write_Byte(0X12);/* 默认为0V */ST7789T3_Write_Command(ST7789T3_CMD_VDVS);ST7789T3_Write_Byte(0X20);/* 默认值 */ST7789T3_Write_Command(ST7789T3_CMD_FRCTRL2);ST7789T3_Write_Byte(0X0F);/* A4为默认,A1:模拟电源电压6.6V,模拟公共电压-4.6V */ST7789T3_Write_Command(ST7789T3_CMD_PWCTRL1);ST7789T3_Write_Byte(0XA4);ST7789T3_Write_Byte(0XA1);/* 根据数据手册填写 */ST7789T3_Write_Command(ST7789T3_CMD_PVGAMCTRL);ST7789T3_Write_Byte(0XD0);ST7789T3_Write_Byte(0X04);ST7789T3_Write_Byte(0X0D);ST7789T3_Write_Byte(0X11);ST7789T3_Write_Byte(0X13);ST7789T3_Write_Byte(0X2B);ST7789T3_Write_Byte(0X3F);ST7789T3_Write_Byte(0X54);ST7789T3_Write_Byte(0X4C);ST7789T3_Write_Byte(0X18);ST7789T3_Write_Byte(0x0D);ST7789T3_Write_Byte(0x0B);ST7789T3_Write_Byte(0x1F);ST7789T3_Write_Byte(0x23);/* 根据数据手册填写 */ST7789T3_Write_Command(ST7789T3_CMD_NVGAMCTRL);ST7789T3_Write_Byte(0xD0);ST7789T3_Write_Byte(0x04);ST7789T3_Write_Byte(0x0C);ST7789T3_Write_Byte(0x11);ST7789T3_Write_Byte(0x13);ST7789T3_Write_Byte(0x2C);ST7789T3_Write_Byte(0x3F);ST7789T3_Write_Byte(0x44);ST7789T3_Write_Byte(0x51);ST7789T3_Write_Byte(0x2F);ST7789T3_Write_Byte(0x1F);ST7789T3_Write_Byte(0x1F);ST7789T3_Write_Byte(0x20);ST7789T3_Write_Byte(0x23);/* 启动显示反相 */ST7789T3_Write_Command(ST7789T3_CMD_INVON);/* 开启显示,默认关闭 */ST7789T3_Write_Command(ST7789T3_CMD_DISPON);
}
/************************END**************************/

③LCD显示的简单驱动程序

(1)显存的地址偏移修正

用来校准屏幕显示位置,让图像显示在正确的位置上。

作用:有些LCD控制器内部有地址偏移;实际显示区域与逻辑坐标不一致;OFFSET_Y 用来补偿这个差异。

原因:不同LCD控制器设计不同;有些控制器从RAM某个位置开始显示;偏移量让程序员可以"骗过"控制器,实现精确定位。

OFFSET_Y就是个"位置修正值",让显示内容不会偏上或偏下,永远显示在正确位置

(2)LCD相关文件

LCD.h文件

#ifndef _LCD_H_
#define _LCD_H_/* 头文件包含 */
#include "stm32f4xx.h"
#include "ST7789T3.h"
#include "TIMER.h"/* 图像显示参数宏定义 */
#define OFFSET_Y 20		//屏幕Y轴地址偏移#define WHITE         	 0xFFFF
#define BLACK         	 0x0000
#define RED           	 0xF800
#define GREEN         	 0x07E0
#define BLUE           	 0x001F/* 外部变量声明 *//* 函数声明 */
void LCD_MonochromeFill(uint16_t X_Start, uint16_t X_End, uint16_t Y_Start, uint16_t Y_End, uint16_t Color);void LCD_SetLight(uint8_t BLK_Duty);
void LCD_CloseLight(void);
void LCD_OpenLight(void);
#endif

LCD.c文件

#include "LCD.h"
/*-----------------------------------------LCD背光控制------------------*/
//*****************************
/*** @brief  LCD调节背光大小函数* @param  BLK_Duty:设置背光的占空比 范围5 - 100* @retval None
*/
//*****************************
void LCD_SetLight(uint8_t BLK_Duty)
{if(BLK_Duty >= 5 && BLK_Duty <= 100)    //保证数据在合理范围{//设置TIM3的通道3的CCR寄存器值__HAL_TIM_SetCompare(&TIMER3_Handle, TIM_CHANNEL_3, BLK_Duty * TIM3_PERIOD / 100);}
}//*****************************
/*** @brief  LCD关闭背光函数* @param  None* @retval None
*/
//*****************************
void LCD_CloseLight(void)
{//占空比设置为0,关闭背光————熄屏__HAL_TIM_SetCompare(&TIMER3_Handle, TIM_CHANNEL_3, 0);
}//*****************************
/*** @brief  LCD开启背光* @param  None* @retval None
*/
//*****************************
void LCD_OpenLight(void)
{//占空比设置为0,关闭背光————熄屏HAL_TIM_PWM_Start(&TIMER3_Handle, TIM_CHANNEL_3);
}
/**************************************************END**************************//*-----------------------LCD简单显示------------------*/
//*****************************
/*** @brief  LCD单色填充函数,主要用于测试* @param  XY的坐标的起止点* @retval None
*/
//*****************************
void LCD_MonochromeFill(uint16_t X_Start, uint16_t X_End, uint16_t Y_Start, uint16_t Y_End, uint16_t Color)
{uint16_t i,j;//显示范围LCD_Address_Set(X_Start,X_End,Y_Start + OFFSET_Y,Y_End + OFFSET_Y);//发送填充颜色数据for(i = Y_Start; i < Y_End; i++){for(j = X_Start; j < X_End; j++){ST7789T3_Write_HalfWord(Color);}}
}
/************************END**************************/

3、测试驱动程序 以及 程序问题的发现与解决

在完成以上步骤,我们就可以测试一下程序能不能正常驱动LCD屏幕了。

(1)、PWM调光测试:

直接在main函数中初始化定时器,随后给PWM的占空比直接给到100,看屏幕的背光亮不亮。

随后检查背光调节能不能实现。

注意:屏幕的背光亮不亮不能直接看屏幕,因为此时屏幕没有被驱动,所以要看背板有没有光发出来。

PWM测试程序

#include "main.h"uint32_t HCLK = 0;int main(void)
{/* 系统初始化 */System_Init();UART_Debug_Init();/* 启动正常提示 */HAL_Delay(50);HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"STM32F411RET6 开机\r\n",20,100);HAL_Delay(200);/* 初始化定时器 */TIM3_PWM_Init();HAL_Delay(100);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"已初始化完成\r\n",14,100);HAL_Delay(200);/* 开启背光 */LCD_OpenLight();LCD_SetLight(100);HAL_Delay(1000);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"背光已经开启\r\n",14,100);HAL_Delay(200);/* 测试背光调节 */LCD_SetLight(95);HAL_Delay(500);LCD_SetLight(85);HAL_Delay(500);LCD_SetLight(75);HAL_Delay(500);LCD_SetLight(65);HAL_Delay(500);LCD_SetLight(55);HAL_Delay(500);LCD_SetLight(45);HAL_Delay(500);LCD_SetLight(35);HAL_Delay(500);LCD_SetLight(25);HAL_Delay(500);LCD_SetLight(15);HAL_Delay(500);LCD_SetLight(5);HAL_Delay(500);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"准备关闭背光\r\n",14,100);HAL_Delay(200);/* 关闭背光 */LCD_CloseLight();HAL_Delay(500);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"已经关闭背光\r\n",14,100);HAL_Delay(200);

(2)、SPI通信测试

这里我用的是硬件方式验证,如果想用软件方式验证的话,可以读取ST7789T3寄存器的数据。例如通过读取芯片ID来验证SPI硬件或者软件4线串行的通信正确性。

读取模式(4线)
为了实现读取功能,MCU首先必须发送一个命令(读取 ID 或寄存器命令),然后接下来的字节将以相反的方向传输(MCU接收8bit)。
之后,CSX 必须在发送新命令之前变为高电平(见下图)。
驱动程序在 SCL 的下降沿对 SDA(输出数据)进行移位。因此,MCU要在 SCL 的上升沿进行读取。
在发送读状态命令后,SDA线必须在最后一个比特的SCL下降沿之前设置为高阻态模式。

4线串行协议(用于RDID1/RDID2/RDID3/0Ah/0Bh/0Ch/0Dh/0Eh/0Fh命令:8位读取):
在这里插入图片描述

(3)、LCD驱动测试程序

main.c

#include "main.h"uint32_t HCLK = 0;int main(void)
{/* 初始化 */System_Init();UART_Debug_Init();/* 启动正常提示 */HAL_Delay(50);HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"STM32F411RET6 开机\r\n",20,100);HAL_Delay(200);/* 初始化LCD */LCD_Init();HAL_Delay(100);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"已初始化完成\r\n",14,100);HAL_Delay(200);while(1){//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"准备开启背光\r\n",14,100);HAL_Delay(200);/* LCD测试程序 *//* 开启背光 */LCD_OpenLight();LCD_SetLight(100);HAL_Delay(500);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"背光已经开启\r\n",14,100);HAL_Delay(200);/* 填充纯白 */LCD_MonochromeFill(0,240,0,280,WHITE);HAL_Delay(1000);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"白色已经填充\r\n",14,100);HAL_Delay(200);/* 填充纯黑 */LCD_MonochromeFill(0,240,0,280,BLACK);HAL_Delay(1000);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"黑色已经填充\r\n",14,100);HAL_Delay(200);/* 填充纯红 */LCD_MonochromeFill(0,240,0,280,RED);HAL_Delay(1000);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"红色已经填充\r\n",14,100);HAL_Delay(200);/* 填充纯绿 */LCD_MonochromeFill(0,240,0,280,GREEN);HAL_Delay(1000);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"绿色已经填充\r\n",14,100);HAL_Delay(200);/* 填充纯蓝 */LCD_MonochromeFill(0,240,0,280,BLUE);HAL_Delay(1000);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"蓝色已经填充\r\n",14,100);HAL_Delay(200);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"开始背光调节\r\n",14,100);HAL_Delay(200);/* 测试背光调节 */LCD_SetLight(85);HAL_Delay(500);LCD_SetLight(75);HAL_Delay(500);LCD_SetLight(65);HAL_Delay(500);LCD_SetLight(55);HAL_Delay(500);LCD_SetLight(45);HAL_Delay(500);LCD_SetLight(35);HAL_Delay(500);LCD_SetLight(25);HAL_Delay(500);LCD_SetLight(15);HAL_Delay(500);LCD_SetLight(5);HAL_Delay(500);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"准备关闭背光\r\n",14,100);HAL_Delay(200);/* 关闭背光 */LCD_CloseLight();HAL_Delay(500);//测试提示————————HAL_UART_Transmit(&UART_Debug.Uart,(uint8_t *)"已经关闭背光\r\n",14,100);HAL_Delay(200);}
}void System_Init(void)
{/* HAL库初始化 */HAL_Init();/* 选择内部高速时钟,配置为HCLK:100MHz*/HCLK = RCC_Init();/* 低功耗初始化 */LowPowerConsumption_Init();/* 初始化硬件看门狗 */HardwareWatchdog_Init();/* 关闭看门狗——1.6s复位 */XJJ_HARDWAREWATCHGOD_DISENABLE();  
}

效果图片:

背光熄灭
在这里插入图片描述
背光亮起

在这里插入图片描述
LCD屏幕显示全白
在这里插入图片描述

至此,以上就完成了屏幕的简单驱动和测试,之后完成触摸屏的驱动程序后,会有UI界面设计的案例。

未完待续。。。

下一步部分完成触摸屏的驱动程序

也可以收藏本文章,会接着本章内容进行更新。

可以关注我,第一时间获取最新内容。

本文结语:如果觉得不错可以点赞收藏一下,没准哪天你就用到了。

http://www.dtcms.com/a/447980.html

相关文章:

  • 优秀企业网站设计制作工程建设招标网都有哪些网站
  • 西安做网站的云阔网站开发小程序开发
  • 建设银行网站怎么登陆密码忘了怎么办正规建网站企业
  • 系统官网网站模板哪个做网站好
  • 链家网站谁做的现在还有做系统的网站吗
  • 游戏型网站开发如何做一网站
  • 深圳最好的网站建设返利网站开发
  • 做书app下载网站咸阳网站开发哪家好
  • 深圳网站建设中为网站建设应该注意哪些问题
  • 校园网站建设提升有学给宝宝做衣服的网站吗
  • 商城网站建设预算要多少钱wordpress sae 插件
  • win2003创建网站google图片搜索引擎入口
  • 北京企业网站seo平台网站更新前知道内容
  • 新闻资讯网站模板渭南免费做网站公司
  • 晋州 网站建设 网络推广衡水教育行业网站建设
  • 网站推广营销应该怎么做winserver wordpress
  • 湖南省建设银行网站官网应用商店下载安装2023最新版
  • 全国高速公路施工建设有没有网站kotlin做网站
  • 如何利用ps做网站做网站需要多大的显存
  • 桂林北站到龙脊梯田手机能制作软件吗
  • 语种网站建设wordpress移动导航
  • asp网站如何运行教程网网站源码php
  • 整站下载器 做网站地图重庆假山制作
  • 做网页要去哪个网站佛山网站建设收费标准
  • 国外好的设计网站有哪些深圳专业做网站哪家专业
  • 如何编写网站后台程序移动网站建设方面
  • wordpress整站手机端网游推广员
  • RAG检索增强LLM
  • 建设网站的内容规划镇江网站推广排名
  • 物业公司网站建设网站源码修改后怎么提交