文章目录
一、TFT是什么?
TFT(Thin Film Transistor)彩屏是一种基于薄膜晶体管技术的液晶显示屏,它使用了薄膜晶体管作为每个像素点的开关,能够实现快速响应和高质量的图像显示。
这次用到的是1.44寸彩屏,该款LCD模块采用4线制SPI通信方式,驱动IC为ST7735S,分辨率为128*128,该模块包含有LCD显示屏,背光控制电路。
废话不多说,下面直接进入正文。
二、TFT使用步骤
1.硬件
1.1 引脚说明
引脚标号 | 说明 |
---|---|
GND | 接地 |
VCC | 5V/3.3V电源输入 |
SCL | SPI总线时钟信号 |
SDA | SPI总线写数据信号 |
RES | 液晶屏复位信号,低电平复位 |
DC | 液晶屏寄存器/数据选择信号,高电平:寄存器,低电平:数据 |
CS | 液晶屏片选信号,低电平使能 |
BLK | LED 背光控制,高电平点亮,如无需控制则接3.3V常亮 |
1.2 硬件电路
这里我是采用面包板和STM32F103核心板以及TFT彩屏自己搭建的一个硬件连接。
引脚定义如下:
#define LCD_CTRL GPIOB //定义TFT数据端口
#define LCD_LED GPIO_Pin_8 //PB9 连接至TFT--BLK
#define LCD_CS GPIO_Pin_7 //PB7连接至TFT--CS
#define LCD_RS GPIO_Pin_6 //PB6连接至TFT--DC
#define LCD_RST GPIO_Pin_5 //PB5连接至TFT--RES
#define LCD_SCL GPIO_Pin_11 //PB11连接至TFT--SCL
#define LCD_SDA GPIO_Pin_10 //PB10连接至TFT--SDA
2.软件
由于TFT彩屏用到的函数过多,我这里仅仅展示我用到的一些,感兴趣的可以下载附件查看完整工程。
2.1 初始化(示例):
TFT初始化流程是固定发这些指令的,无需深究,想了解的可以看下ST7735S驱动手册。
LCD_GPIOInit函数是将引脚配置为推挽输出模式。
/*******************************************************************************
* 函数名:LCD_Init
* 描述 :TFT初始化
* 输入 :void
* 输出 :void
* 调用 :初始化
* 备注 :
*******************************************************************************/
void LCD_Init(void)
{
LCD_GPIOInit();//使用模拟SPI
LCD_RESET(); //液晶屏复位
//************* Start Initial Sequence **********//
//开始初始化液晶屏
LCD_WR_REG(0x11);//Sleep exit
delay_syms (120);
//ST7735R Frame Rate
LCD_WR_REG(0xB1);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x2D);
LCD_WR_REG(0xB2);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x2D);
LCD_WR_REG(0xB3);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x2D);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x2D);
LCD_WR_REG(0xB4); //Column inversion
LCD_WR_DATA(0x07);
//ST7735R Power Sequence
LCD_WR_REG(0xC0);
LCD_WR_DATA(0xA2);
LCD_WR_DATA(0x02);
LCD_WR_DATA(0x84);
LCD_WR_REG(0xC1);
LCD_WR_DATA(0xC5);
LCD_WR_REG(0xC2);
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0x00);
LCD_WR_REG(0xC3);
LCD_WR_DATA(0x8A);
LCD_WR_DATA(0x2A);
LCD_WR_REG(0xC4);
LCD_WR_DATA(0x8A);
LCD_WR_DATA(0xEE);
LCD_WR_REG(0xC5); //VCOM
LCD_WR_DATA(0x0E);
LCD_WR_REG(0x36); //MX, MY, RGB mode
LCD_WR_DATA(0xC8);
//ST7735R Gamma Sequence
LCD_WR_REG(0xe0);
LCD_WR_DATA(0x0f);
LCD_WR_DATA(0x1a);
LCD_WR_DATA(0x0f);
LCD_WR_DATA(0x18);
LCD_WR_DATA(0x2f);
LCD_WR_DATA(0x28);
LCD_WR_DATA(0x20);
LCD_WR_DATA(0x22);
LCD_WR_DATA(0x1f);
LCD_WR_DATA(0x1b);
LCD_WR_DATA(0x23);
LCD_WR_DATA(0x37);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x07);
LCD_WR_DATA(0x02);
LCD_WR_DATA(0x10);
LCD_WR_REG(0xe1);
LCD_WR_DATA(0x0f);
LCD_WR_DATA(0x1b);
LCD_WR_DATA(0x0f);
LCD_WR_DATA(0x17);
LCD_WR_DATA(0x33);
LCD_WR_DATA(0x2c);
LCD_WR_DATA(0x29);
LCD_WR_DATA(0x2e);
LCD_WR_DATA(0x30);
LCD_WR_DATA(0x30);
LCD_WR_DATA(0x39);
LCD_WR_DATA(0x3f);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x07);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0x10);
LCD_WR_REG(0x2a);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x7f);
LCD_WR_REG(0x2b);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x9f);
LCD_WR_REG(0xF0); //Enable test command
LCD_WR_DATA(0x01);
LCD_WR_REG(0xF6); //Disable ram power save mode
LCD_WR_DATA(0x00);
LCD_WR_REG(0x3A); //65k mode
LCD_WR_DATA(0x05);
LCD_WR_REG(0x29);//Display on
LCD_SetParam();//设置LCD参数
LCD_LED_SET;//点亮背光
}
2.2 LCD复位(示例):
注意:液晶初始化前要调用此函数
/*******************************************************************************
* 函数名:LCD_Init
* 描述 :LCD复位函数
* 输入 :void
* 输出 :void
* 调用 :初始化
* 备注 :
*******************************************************************************/
void LCD_RESET(void)
{
LCD_RST_CLR;
delay_syms(100);
LCD_RST_SET;
delay_syms(50);
}
2.3 LCD写指令(示例):
#if USE_HARDWARE_SPI 在这里表示是硬件SPI还是软件模拟SPI,我这里用的是软件模拟SPI。
/*******************************************************************************
* 函数名:LCD_WR_REG
* 描述 :向液晶屏总线写入写16位指令
* 输入 :Reg:待写入的指令值
* 输出 :void
* 调用 :
* 备注 :
*******************************************************************************/
void LCD_WR_REG(u16 data)
{
LCD_CS_CLR;
LCD_RS_CLR;
#if USE_HARDWARE_SPI
SPI_WriteByte(SPI2,data);
#else
SPIv_WriteData(data);
#endif
LCD_CS_SET;
}
2.4 LCD写数据(示例):
#if USE_HARDWARE_SPI 在这里表示是硬件SPI还是软件模拟SPI,我这里用的是软件模拟SPI。
/*******************************************************************************
* 函数名:LCD_WR_DATA
* 描述 :向液晶屏总线写入写8位数据
* 输入 :Data:待写入的数据
* 输出 :void
* 调用 :
* 备注 :
*******************************************************************************/
void LCD_WR_DATA(u8 data)
{
LCD_CS_CLR;
LCD_RS_SET;
#if USE_HARDWARE_SPI
SPI_WriteByte(SPI2,data);
#else
SPIv_WriteData(data);
#endif
LCD_CS_SET;
}
2.5 设置LCD参数(示例):
/*******************************************************************************
* 函数名:LCD_SetParam
* 描述 :设置LCD参数
* 输入 :void
* 输出 :void
* 调用 :
* 备注 :方便进行横竖屏模式切换
*******************************************************************************/
void LCD_SetParam(void)
{
lcddev.wramcmd=0x2C;
#if USE_HORIZONTAL==1 //使用横屏
lcddev.dir=1;//横屏
lcddev.width=128;
lcddev.height=128;
lcddev.setxcmd=0x2A;
lcddev.setycmd=0x2B;
LCD_WriteReg(0x36,0xA8);
#else//竖屏
lcddev.dir=0;//竖屏
lcddev.width=128;
lcddev.height=128;
lcddev.setxcmd=0x2A;
lcddev.setycmd=0x2B;
LCD_WriteReg(0x36,0xC8);
#endif
}
这里说一下横屏和竖屏的定义,横屏宽度320高度240,竖屏反之宽度240高度320.
//支持横竖屏快速定义切换,支持8/16位模式切换
#define USE_HORIZONTAL 0 //定义是否使用横屏 0,不使用.1,使用.
//定义LCD的尺寸
#if USE_HORIZONTAL==1 //使用横屏
#define LCD_W 320
#define LCD_H 240
#else
#define LCD_W 240
#define LCD_H 320
#endif
2.6 LCD清屏(示例):
/*******************************************************************************
* 函数名:LCD_Clear
* 描述 :LCD全屏填充清屏函数
* 输入 :Color:要清屏的填充色
* 输出 :void
* 调用 :
* 备注 :
*******************************************************************************/
void LCD_Clear(u16 Color)
{
u16 i,j;
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);
for(i=0;i<lcddev.width;i++)
{
for(j=0;j<lcddev.height;j++)
LCD_WR_DATA_16Bit(Color); //写入数据
}
}
2.7 显示一个字符串(示例):
/*******************************************************************************
* 函数名:LCD_SetWindows
* 描述 :显示一个字符串,包含中英文显示
* 输入 : x,y :起点坐标
fc:前置画笔颜色
bc:背景颜色
str :字符串
size:字体大小
mode:模式 0,填充模式;1,叠加模式
* 输出 :void
* 调用 :
* 备注 :
*******************************************************************************/
void LCD_Show_Str(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *str,uint8_t size,uint8_t mode)
{
uint16_t x0=x;
uint18_t bHz=0;//字符或者中文
while(*str!=0)//数据未结束
{
if(!bHz)
{
if(x>(lcddev.width-size/2)||y>(lcddev.height-size))
return;
if(*str>0x80)bHz=1;//中文
else //字符
{
if(*str==0x0D)//换行符号
{
y+=size;
x=x0;
str++;
}
else
{
if(size==12||size==16)
{
LCD_ShowChar(x,y,fc,bc,*str,size,mode);
x+=size/2; //字符,为全字的一半
}
else//字库中没有集成16X32的英文字体,用8X16代替
{
LCD_ShowChar(x,y,fc,bc,*str,16,mode);
x+=8; //字符,为全字的一半
}
}
str++;
}
}else//中文
{
if(x>(lcddev.width-size)||y>(lcddev.height-size))
return;
bHz=0;//有汉字库
if(size==32)
GUI_DrawFont32(x,y,fc,bc,str,mode);
else if(size==24)
GUI_DrawFont24(x,y,fc,bc,str,mode);
else
GUI_DrawFont16(x,y,fc,bc,str,mode);
str+=2;
x+=size;//下一个汉字偏移
}
}
}
2.8 设置LCD显示窗口(示例):
/*******************************************************************************
* 函数名:LCD_SetWindows
* 描述 :设置lcd显示窗口,在此区域写点数据自动换行
* 输入 :xy起点和终点
* 输出 :void
* 调用 :
* 备注 :
*******************************************************************************/
void LCD_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd)
{
#if USE_HORIZONTAL==1 //使用横屏
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(xStar>>8);
LCD_WR_DATA(0x00FF&xStar+3);
LCD_WR_DATA(xEnd>>8);
LCD_WR_DATA(0x00FF&xEnd+3);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(yStar>>8);
LCD_WR_DATA(0x00FF&yStar+2);
LCD_WR_DATA(yEnd>>8);
LCD_WR_DATA(0x00FF&yEnd+2);
#else
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(xStar>>8);
LCD_WR_DATA(0x00FF&xStar+2);
LCD_WR_DATA(xEnd>>8);
LCD_WR_DATA(0x00FF&xEnd+2);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(yStar>>8);
LCD_WR_DATA(0x00FF&yStar+3);
LCD_WR_DATA(yEnd>>8);
LCD_WR_DATA(0x00FF&yEnd+3);
#endif
LCD_WriteRAM_Prepare(); //开始写入GRAM
}
2.9 TFT显示图片(示例):
/*******************************************************************************
* 函数名:TFT_Show_Image
* 描述 :TFT显示图片
* 输入 :x,y :起点坐标
x1,y1 :图片宽度,高度
*image 图片数组
* 输出 :void
* 调用 :
* 备注 :
*******************************************************************************/
void TFT_Show_Image(uint16_t x,uint16_t y,uint16_t x1,uint16_t y1,const uint8_t *image)
{
uint16_t i;
uint8_t picH,picL;
LCD_SetWindows(x,y,x+x1-1,y+y1-1);//窗口设置
for(i=0;i<x1*y1;i++)
{
picL=*(image+i*2);//数据低位在前
picH=*(image+i*2+1);
LCD_WR_DATA_16Bit(picH<<8|picL);
}
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复显示窗口为全屏
}
2.10 TFT_Test(测试)(示例):
/*******************************************************************************
* 函数名:TFT_Test
* 描述 :测试TFT
* 输入 :void
* 输出 :void
* 调用 :
* 备注 :
*******************************************************************************/
void TFT_Test(void)
{
/*TFT_Show_Image显示*/
TFT_Show_Image(0,0,128,63,xiaobuding);
LCD_Show_Str(10,80,BRED,WHITE,"2023-12-6",20,1);
LCD_Show_Str(10,100,RED,WHITE,"xiaobuding_QAQ",25,1);
}
2.11 测试结果:
3.取模软件Img2Lcd的使用
在我的另外一篇文章0.96寸OLED(IIC接口)显示屏的图像显示应用用到了PCtoLCD软件,今天我们用下Img2Lcd软件,有需要可以下载免激活码使用,
3.1 打开Img2Lcd软件
3.2 打开图片,进行相应配置
这里注意下右下角输出图像的大小,要显示图片的时候,用到函数TFT_Show_Image对图片宽度,高度进行设置要一致
3.3 保存数组数据
3.4 最后将数组数据复制到程序里面就可以了
四、 总结
本次的TFT彩屏的驱动主要来源于多种显示模块驱动,感兴趣的可以进去看下,里面有树莓派显示模块/SPI显示模块/Arduino显示模块/IPS彩屏等等相关资料,今天的内容就到这里了,感谢你的观看,谢谢!