21.1 stm32使用LTDC驱动LCD--配置说明

02-27 1682阅读

本文讲解如何配置LTDC驱动LCD的参数配置,以及CubeMx参数配置说明

本文使用的是淘宝买的一块带电容触摸的液晶显示屏:5寸TFT液晶显示屏高清800*480免驱40P通用RGBIPS全视角彩屏GT911

说实话,价格还是相对挺便宜的,值得入手,哈哈哈

21.1 stm32使用LTDC驱动LCD--配置说明

21.1 stm32使用LTDC驱动LCD--配置说明

21.1 stm32使用LTDC驱动LCD--配置说明

这款屏幕采用的是RGB888格式

这里面也就是常用的引脚:

R0-R7、G0-G7、B0-B7

DCLK–时钟线

HSYNC\VSYNC–同步线

DE–数据使能

DISP是显示使能,控制屏幕的哈

背光是通过控制LED+\LED-的电流实现的

21.1 stm32使用LTDC驱动LCD--配置说明

21.1 stm32使用LTDC驱动LCD--配置说明

由此可以找到,LED需要流过20mA电流,下面是它的推荐电路

21.1 stm32使用LTDC驱动LCD--配置说明

接着我就绘制了我的PCB,如下所示:我的是电容触摸屏,所以电阻触摸引脚位置悬空的

21.1 stm32使用LTDC驱动LCD--配置说明

21.1 stm32使用LTDC驱动LCD--配置说明

接下来,我们就来CubeMx配置LTDC驱动它吧

CubeMx配置LTDC

硬件相关参数设置

21.1 stm32使用LTDC驱动LCD--配置说明

注意:这里的HSYNC、VSYNC、DE的有效极性需要和实际相反

21.1 stm32使用LTDC驱动LCD--配置说明

由此图可以看出HSYNC、VSYNC、DE的有效极性都是高,clk的下降沿采样

21.1 stm32使用LTDC驱动LCD--配置说明

上面我的LTDC配置取得都是典型值

Pulse Width对应的是HSW和VSW

引脚需要全部高速

21.1 stm32使用LTDC驱动LCD--配置说明

然后就还有LTDC输出给LCD的时钟信号,由上面的数据手册给出的典型值配置25MHz,LTDC会由LTDC_PCLK引脚输出给LCD

21.1 stm32使用LTDC驱动LCD--配置说明

21.1 stm32使用LTDC驱动LCD--配置说明

到此,LTDC硬件相关的参数配置完毕

LTDC图像层配置

21.1 stm32使用LTDC驱动LCD--配置说明

开启全局中断,并且优先级可以设置低点

21.1 stm32使用LTDC驱动LCD--配置说明

DMA2D在代码里重新配置过得,可以按此设置

21.1 stm32使用LTDC驱动LCD--配置说明

关于FMC的SDRAM存储属性设置可以参考如下:

21.1 stm32使用LTDC驱动LCD--配置说明

21.1 stm32使用LTDC驱动LCD--配置说明

调试

如何判定硬件问题:

在函数void MX_LTDC_Init(void)中的HAL_LTDC_Init()后如下处理:

21.1 stm32使用LTDC驱动LCD--配置说明

如果LCD能显示红色说明硬件正常,否则有问题

lcd_base_backlight_set是开启屏幕背光

完整工程下载:(旧版本,不建议使用,LCD显示刷新没处理后续说的cache更新)

链接:https://pan.baidu.com/s/1g_VezTfR_-fgqSpPFlvtqQ

提取码:qqio

补充:

该屏幕GT911驱动:

需要注意的是INT引脚禁止上下拉,应配置为浮空输入

触摸屏手指触摸时会触摸70ms左右,这段时间其实坐标是同一点,INT引脚持续输出方波信号10ms间隔

所以应采集判定坐标避免重复点如下函数:

/****************************************************
@function:触摸芯片扫描
@param:(x,y)--点
@return:-1--无触摸,0--触摸
@note:只读取一个点,建议10ms执行一次
注意:此函数未处理重复触摸点,尤其是在两次点击相同像素点的情况下,但是概率不大
****************************************************/
int GT911_Scan(uint16_t *x,uint16_t *y)
{
    static uint16_t xlast = 0,ylast = 0;
    
    if(!gt911.Enable)return -1;
    if(!GT911_PenInt())return -1;//没有触摸
    GT911_TouchPointRead(x,y);
    if((*x == xlast) && (*y == ylast))return -1;//移除重复点
    xlast = *x;
    ylast = *y;
    return 0;
}

完整驱动代码:

GT911_driver.c

GT911_driver.h

i2c_driver.c//模拟IIC

i2c_driver.h

delay_driver.c//定时器微秒精确延时

delay_driver.h

GT911_driver.h

#ifndef _GT911_driver_H_
#define _GT911_driver_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
uint16_t GT911_ScreenWidthGet(void);
uint16_t GT911_ScreenHeigthGet(void);
int GT911_Init(void);
int GT911_Scan(uint16_t *x,uint16_t *y);
#ifdef __cplusplus
}
#endif
#endif

GT911_driver.c

/**********************************************************************
*file:自己编写的GT911触摸检测
*author:残梦
*versions:V1.0
*date:2023.11.8
*note:
注意GT911的INT引脚会在触摸时出现10ms的方波信号,手指单次触摸维持在70ms左右,
持续触摸会一直到释放,默认高电平,触摸低电平,引脚应浮空严禁上下拉
**********************************************************************/
#include "GT911_driver.h"
#include "i2c_driver.h"
#include "delay_driver.h"
#include "gpio.h"
#include "stdio.h"
/* 定义触笔中断INT的GPIO端口 */
#define TP_INT_GPIO_CLK_ENABLE()	__HAL_RCC_GPIOD_CLK_ENABLE()
#define TP_INT_GPIO_PORT              GPIOD
#define TP_INT_PIN                    GPIO_PIN_4
#define TP_RST_GPIO_CLK_ENABLE()	__HAL_RCC_GPIOD_CLK_ENABLE()
#define TP_RST_GPIO_PORT              GPIOD
#define TP_RST_PIN                    GPIO_PIN_5
//#define GT911_I2C_ADDR1		 0xBA
#define GT911_READ_XY_REG    0x814E /* 坐标寄存器 */ 
#define GT911_CLEARBUF_REG   0x814E /* 清除坐标寄存器 */ 
#define GT911_CONFIG_REG     0x8047 /* 配置参数寄存器 */ 
#define GT911_COMMAND_REG    0x8040 /* 实时命令 */ 
#define GT911_PRODUCT_ID_REG 0x8140 /* 芯片ID */ 
#define GT911_VENDOR_ID_REG  0x814A /* 当前模组选项信息 */ 
#define GT911_CONFIG_VERSION_REG   0x8047 /* 配置文件版本号 */ 
#define GT911_CONFIG_CHECKSUM_REG  0x80FF /* 配置文件校验码 */ 
#define GT911_FIRMWARE_VERSION_REG 0x8144 /* 固件版本号 */ 
typedef struct
{
    //芯片参数
	uint8_t	i2cAddress;//i2c地址
	uint16_t width;//屏幕宽度
	uint16_t height;//屏幕高度
    //用户变量
	uint8_t Enable;//使能状态,初始化成功则为1,失败为0
}GT911_StructDef;
static GT911_StructDef gt911 = \
{
    .Enable = 0,
};//触摸屏结构体变量
static void GT911_WriteReg(uint16_t _usRegAddr, uint8_t *_pRegBuf, uint8_t _ucLen);
static void GT911_ReadReg(uint16_t _usRegAddr, uint8_t *_pRegBuf, uint8_t _ucLen);
static void GT911_ReadMaxXY(uint16_t *_X, uint16_t *_Y);
static void GT911_InitPin(void);
static uint32_t GT911_ReadID(void);
static int GT911_DetectID(void);
static uint8_t GT911_PenInt(void);
static void GT911_TouchPointRead(uint16_t *x,uint16_t *y);
/****************************************************
@function:写1个或连续的多个寄存器
@param: _usRegAddr : 寄存器地址
        _pRegBuf : 寄存器数据缓冲区
        _ucLen : 数据长度
@return:void
@note:
****************************************************/
static void GT911_WriteReg(uint16_t _usRegAddr, uint8_t *_pRegBuf, uint8_t _ucLen)
{
	uint8_t i;
    i2c_Start();					/* 总线开始信号 */
    i2c_SendByte(gt911.i2cAddress);	/* 发送设备地址+写信号 */
	i2c_WaitAck();
    i2c_SendByte(_usRegAddr >> 8);	/* 地址高8位 */
	i2c_WaitAck();
    i2c_SendByte(_usRegAddr);		/* 地址低8位 */
	i2c_WaitAck();
	for (i = 0; i > 8);	/* 地址高8位 */
		i2c_WaitAck();
		i2c_SendByte(_usRegAddr);		/* 地址低8位 */
		i2c_WaitAck();
		i2c_Start();
		i2c_SendByte(gt911.i2cAddress + 0x01);	/* 发送设备地址+读信号 */
		i2c_WaitAck();
	}
	
	for (i = 0; i OPFCCR  = PixelFormat;                    
	/* 设置填充大小 */
	DMA2D->NLR     = (uint32_t)(xSize CR     |= DMA2D_CR_START; 
	/* 等待DMA2D传输完成 */
	while (DMA2D->CR & DMA2D_CR_START) 
	{
	}
}
/**********************************************************************************************************
*	函 数 名: _DMA2D_Copy
*	功能说明: 通过DMA2D从前景层复制指定区域的颜色数据到目标区域
*	形    参: pSrc          颜色数据源地址
*             pDst          颜色数据目的地址
*             xSize         目的区域的X轴大小,即每行像素数
*             ySize         目的区域的Y轴大小,即行数
*             OffLineSrc    前景层图像的行偏移
*             OffLineDst    输出的行偏移
*             PixelFormat   目标区颜色格式
*	返 回 值: 无
**********************************************************************************************************/
static void lcd_base_DMA2D_Copy(void * pSrc, void * pDst, uint32_t xSize, uint32_t ySize, uint32_t OffLineSrc, uint32_t OffLineDst, uint32_t PixelFormat) 
{
	/* DMA2D采用存储器到存储器模式, 这种模式是前景层作为DMA2D输入 */  
	DMA2D->CR      = 0x00000000UL | (1 FGMAR   = (uint32_t)pSrc;
	DMA2D->OMAR    = (uint32_t)pDst;
	DMA2D->FGOR    = OffLineSrc;
	DMA2D->OOR     = OffLineDst;
	
	/* 前景层和输出区域都采用的RGB565颜色格式 */
	DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565;
	DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_RGB565;
	
	DMA2D->NLR     = (uint32_t)(xSize CR   |= DMA2D_CR_START;   
	/* 等待DMA2D传输完成 */
	while (DMA2D->CR & DMA2D_CR_START) {} 
}
/****************************************************
@function:通过DMA2D对于指定区域进行颜色复制(图像复制)
@param:
    LayerIndex    图层
    pDst          颜色数据目的地址
    xSize         要复制区域的X轴大小,即每行像素数
    ySize         要复制区域的Y轴大小,即行数
    OffLine       前景层图像的行偏移
    ColorIndex    要填充的颜色值
@return:void
@note:只支持横屏
****************************************************/
void lcd_base_DMA2D_CopyBuffer(uint16_t x,uint16_t y,uint32_t xSize, uint32_t ySize,void * color)
{
    if((color == NULL) || (xSize == 0) || (ySize == 0))return;
	lcd_base_DMA2D_Copy((uint32_t *)color,                                        /* 位图地址 */
			    (uint32_t *)(s_CurrentFrameBuffer + g_LcdWidth*y*2 + x*2),       /* 显示起始地址(328, 20) */  
			    xSize,           /* 位图长 */
			    ySize,           /* 位图高 */
			    0,             /* 位图行偏移 */
			    g_LcdWidth-xSize,/* 目标区行偏移 */
			    LTDC_PIXEL_FORMAT_RGB565);                                    /* 目标区颜色格式 */
}

完整工程:(最新)

链接:https://pan.baidu.com/s/1I64wD4Ft7PBI0cIogGp45A

提取码:qpxx

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]