STM32F4X TFTLCD ST7735S使用

TFTLCD简介

TFT-LCD 即薄膜晶体管液晶显示器。其英文全称为:Thin Film Transistor-Liquid Crystal Display。TFT-LCD与无源 TN-LCD、STN-LCD 的简单矩阵不同,它在液晶显示屏的每一个像素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。TFT-LCD 也被叫做真彩液晶显示器。

TFTLCD使用

TFTLCD特点

  1. 分辨率高:常用的嵌入式TFTLCD屏幕分辨率有320 * 480、480 * 320、800 * 480、1024 * 600等。
  2. 颜色丰富:常见的TFTLCD支持的颜色有RGB565、RGB666和RGB888
  3. 操作接口丰富:TFTLCD支持并口的8080、串口的SPI、I2C等通信协议
  4. 自带触摸屏:TFTLCD可以外接触摸芯片,实现触摸屏的效果。

TFTLCD的概念

  1. 尺寸:尺寸是代表LCD的物理大小,其定义是屏幕对角线的距离。
  2. 分辨率:分辨率代表的是LCD能够显示多少个像素点,比如800 * 480分辨率的LCD,其水平距离可以显示800个像素点,垂直距离可以显示480个像素点,合计可以显示384000个像素点的大小。
  3. 颜色:LCD的颜色通常有RGB565、RGB666和RGB888,不同的颜色分类代表LCD的图像显示细腻度,其细腻度大小为RGB888>RGB666>RGB565。

TFTLCD色彩空间

不同于黑白LCD和OLED,前两者只能显示黑白的图像,而TFTLCD则可以显示彩色图像,根据不同的TFTLCD类型,主流的TFTLCD显示屏主要可以显示以下3种颜色,分别是RGB565、RGB666和RGB888。

三原色

在了解TFTLCD的颜色显示前,先了解一下什么是三原色。三原色指色彩中不能再分解的三种基本颜色,我们通常说的三原色,是色彩三原色以及光学三原色。三原色分别是指红、绿、蓝3种,可以配置三原色的不同比列来得到其他的颜色。
在这里插入图片描述

RGB颜色

颜色是一种物理量,但是在计算机中要怎样表达这种物理量呢,人们将物理世界中的颜色进行量化,利用二进制来表示不同的颜色,从而有了RGB的概念。RGB又分为RGB565、RGB666、RGB888.

RGB565

在这里插入图片描述
RGB565的意思是用5位表示R分量,6位表示G分量和5位表示B分量,每个像素的颜色用2个字节来表示。RGB565最多可以显示65536种颜色。
一个800 * 480分辨率的LCD,显示一张图片的数据大小为800 * 480 * 2 = 768000字节的数据。

RGB666

在这里插入图片描述
RGB666的意思是用6位表示R分量,6位表示G分量和6位表示B分量,每个像素的颜色用3个字节来表示,高6位为0,RGB666最多可以显示262144种颜色。
一个800 * 480分辨率的LCD,显示一张图片的数据大小为800 * 480 * 3 = 1152000字节的数据。

RGB888

在这里插入图片描述
RGB565的意思是用8位表示R分量,8位表示G分量和8位表示B分量,每个像素的颜色用3个字节来表示,RGB888最多可以显示16777216种颜色。
一个800 * 480分辨率的LCD,显示一张图片的数据大小为800 * 480 * 3 = 1152000字节的数据。
RGB565、RGB666和RGB888之间是可以互相转换的,但是需要注意的,低像素转换成高像素其精度不会损失,但是高像素转换成低像素,其精度会损失

ST7735S驱动芯片

通常TFTLCD内部都会一块TFTLCD的驱动芯片,驱动芯片的作用是接收用户发送的数据,将数据进行管理,最后将数据显示到TFTLCD上。常见的TFTLCD驱动芯片有ILI9341、ILI9488、ST7789S、ST7796、ST7735S等,这些芯片虽然名字不一样,但是驱动基本类似。操作TFTLCD实际就是操作TFTLCD的驱动芯片。本次实验用的驱动芯片是ST7735S。

ST7735S引脚定义

在这里插入图片描述

ST7735S 4线SPI模式

因本章中使用的TFTLCD是4线SPI模式,所以下面就来说一下4线SPI RGB565模式的波形图,其他模式的波形图可以在ST7735S的数据手册中查看。
在这里插入图片描述

  1. IM2要为0,选择串行接口
  2. RESX为高电平
  3. 在开始传输数据前,要把CSX拉低,代表选中TFTLCD
  4. D/CX拉高,代表写数据
  5. 将颜色数据按照RGB格式进行组合
  6. 将组合好的RGB数据按照高位在前,低位在后的方式在SCL的高电平期间依次发送出去

ST7735S显示原理

ST7735S分辨率

ST7735S有两种分辨率,分别是128 * 160和132 * 162。这两种分辨率的选择是通过GM0和GM1两个引脚决定。实验中用到的ST7735S分辨率是132* 162。
在这里插入图片描述

ST7735S显存结构

由于LCD本身只是一块屏幕,只负责显示图像,其内部是没有存储图像数据的功能,这部分功能都是由LCD驱动芯片提供,下面就来看一下ST7735S的显存结构。以128 * 160分辨率、RGB565为例。
在这里插入图片描述
ST7735S把显存分成了128 * 160个格子,一共是20480个格子,每个格子代表一个像素,需要注意的是,因为我们使用的是RGB565的颜色格式,所以一个像素需要2个字节来表示,所以在分辨率为128 * 160,RGB565的模式下,ST7735S的显存大小一共是128 * 160 * 2 = 40960字节的数据大小。

ST7735S像素点扫描模式

通常TFTLCD的像素点的扫描模式都是从左到右,从上到下的模式进行扫描,当然用户也可以通过配置MV MX MY这几个寄存器位来修改像素点的扫描方向。
在这里插入图片描述
在这里插入图片描述

MCU操作ST7735S显存方法

针对ST7735S的显存存储结构,MCU每次修改数据的时候都需要将ST7735S的显存数据读出来,确保旧的数据跟新的数据没有冲突,但是这就有一个问题,每次修改数据的数据都需要读显存数据,这样就很浪费时间。所以在实际应用中,一般都会在MCU中定义一个128 * 160 * 2大小的二维数组,这个数组可以看做是ST7735S的外部显存,每次需要更新数据时,都会更新这个外部显存,最后再通过命令把整个显存数据刷新到ST7735S内部。

TFTLCD字库制作

由于ST7735S的内部没有字库,所以当我们需要在LCD上显示字符的时候,需要先自己制作字库,通过调用把字库中的字摸数据显示到LCD上。

ASCII码字模制作

ASCII码字模的制作软件是PCtoLCD2002,软件大家可以自行到网上进行下载。
我们需要制作常用的ASCII码字符,需要制作的字符如下,第一个ASCII码为空格

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
  • 首先打开PCtoLCD2002,设置软件为字符模式
    在这里插入图片描述
  • 点击选项,进入设置模式,按照以下方法进行取模设置
    -在这里插入图片描述
  • 以生成8x16字符为例
    在这里插入图片描述
    在这里插入图片描述
    在生成字符前先选择字符的高度和宽度,然后将需要生成的字符复制到输入框内,点击生成字模,最后点击保存字模,生成后的字模就会保存到文件中。

图片取模制作

图片取模的制作软件是Img2Lcd,软件大家可以自行到网上进行下载。

  • 设置图片大小
    打开windows的画图软件,设置图片大小为132* 162,并保存
    在这里插入图片描述

  • 打开Img2Lcd,按照下图方式设置
    在这里插入图片描述

  • 点击保存,将图片数据保存到文件中
    在这里插入图片描述

STM32F4X TFTLCD例程

TFTLCD关键函数

硬件SPI初始化

由于LCD的传输协议为4线SPI协议,所以用到了STM32F4X的硬件SPI进行传输,如果是传输大批量数据,可以使用SPI DMA功能,加快传输速率。

void SPI1_Init(void)
{	 
  GPIO_InitTypeDef  GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;
	
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//使能SPI1时钟
 
  //GPIOFB3,4,5初始化设置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;//PB3~5复用功能输出	
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
	
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_SPI1); //PB3复用为 SPI1
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_SPI1); //PB4复用为 SPI1
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_SPI1); //PB5复用为 SPI1
 
	//这里只针对SPI口初始化
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);//复位SPI1
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);//停止复位SPI1

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;		//串行同步时钟的空闲状态为高电平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	//串行同步时钟的第二个跳变沿(上升或下降)数据被采样
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;		//定义波特率预分频的值:波特率预分频值为2
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值计算的多项式
	SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
 
	SPI_Cmd(SPI1, ENABLE); //使能SPI外设


	
}  
u8 SPI1_ReadWriteByte(u8 TxData)
{		 			 
 
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空  
	
	SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个byte  数据
		
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个byte  
 
	return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据	
 		    
}
 
void spi_dma_init(DMA_Stream_TypeDef* DMAy_Streamx,u32 dam_channel,u32 src,u32 dst,u32 len)
{
	DMA_InitTypeDef DMA_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_DMA1,ENABLE);   

	DMA_DeInit(DMAy_Streamx);
	DMA_Cmd(DMAy_Streamx, DISABLE);
	DMA_InitStructure.DMA_Channel = dam_channel;                                           //通道选择
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)dst;                                //DMA外设地址
	DMA_InitStructure.DMA_Memory0BaseAddr = (u32)src;                                   //DMA 存储器0地址
	DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                        //存储器到外设模式
	DMA_InitStructure.DMA_BufferSize = len;                                       //数据传输量 
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;               //外设非增量模式
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                        //存储器增量模式
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    //外设数据长度:8位
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;            //存储器数据长度:8位
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                //使用普通模式 
	DMA_InitStructure.DMA_Priority = DMA_Priority_High;                          //中等优先级
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;      
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                    //存储器突发单次传输
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;            //外设突发单次传输
	DMA_Init(DMAy_Streamx, &DMA_InitStructure);    

	
	while (DMA_GetCmdStatus(DMAy_Streamx) != DISABLE){}
	DMA_Cmd(DMAy_Streamx, ENABLE);


}

void spi_dma_cmd(unsigned char enable)
{
	SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,enable);
}

数据传输函数
void tftlcd_send_data(unsigned char type,unsigned char data,unsigned int len)
{
	
	
	if(SPI_TFTLCD_CMD == type) // 写命令
	{
		GPIO_ResetBits(TFTLCD_CS_PIN_PORT,TFTLCD_CS_PIN); // 拉低CS信号,选中LCD
		GPIO_ResetBits(TFTLCD_DC_PIN_PORT,TFTLCD_DC_PIN); // 拉低DC信号,传输命令
		SPI1_ReadWriteByte(data);                         // 通过硬件·SPI传输
		GPIO_SetBits(TFTLCD_CS_PIN_PORT,TFTLCD_CS_PIN);   // 拉高CS信号
		GPIO_SetBits(TFTLCD_DC_PIN_PORT,TFTLCD_DC_PIN);   // 拉高DC信号
		
	}
	else if(SPI_TFTLCD_DATA == type) // 写数据
	{
		GPIO_ResetBits(TFTLCD_CS_PIN_PORT,TFTLCD_CS_PIN); // 拉低CS信号,选中LCD
		GPIO_SetBits(TFTLCD_DC_PIN_PORT,TFTLCD_DC_PIN);   // 拉高DC信号,传输数据
		SPI1_ReadWriteByte(data);                         // 通过硬件·SPI传输
		GPIO_SetBits(TFTLCD_CS_PIN_PORT,TFTLCD_CS_PIN);   // 拉高CS信号
		GPIO_SetBits(TFTLCD_DC_PIN_PORT,TFTLCD_DC_PIN);   // 拉高DC信号
	}
	else if(SPI_TFTLCD_DELAY == type)
		delay_ms(data);
}


void tftlcd_send_data_dma(unsigned char type,unsigned char *data,unsigned int len)
{
	

	if(SPI_TFTLCD_CMD == type)
	{
		GPIO_ResetBits(TFTLCD_CS_PIN_PORT,TFTLCD_CS_PIN);
		GPIO_ResetBits(TFTLCD_DC_PIN_PORT,TFTLCD_DC_PIN);
		spi_dma_cmd(DISABLE);
		spi_dma_init(DMA2_Stream3,DMA_Channel_3,(u32)data,(u32)&SPI1->DR,len);
		spi_dma_cmd(ENABLE);
		while(DMA_GetFlagStatus(DMA2_Stream3,DMA_FLAG_TCIF3) != SET);
		spi_dma_cmd(DISABLE);
		GPIO_SetBits(TFTLCD_CS_PIN_PORT,TFTLCD_CS_PIN);
		GPIO_SetBits(TFTLCD_DC_PIN_PORT,TFTLCD_DC_PIN);
		
	}
	else if(SPI_TFTLCD_DATA == type)
	{
		GPIO_ResetBits(TFTLCD_CS_PIN_PORT,TFTLCD_CS_PIN);
		GPIO_SetBits(TFTLCD_DC_PIN_PORT,TFTLCD_DC_PIN);
		spi_dma_cmd(DISABLE);
		spi_dma_init(DMA2_Stream3,DMA_Channel_3,(u32)data,(u32)&SPI1->DR,len);
		spi_dma_cmd(ENABLE);
		while(DMA_GetFlagStatus(DMA2_Stream3,DMA_FLAG_TCIF3) != SET);
		spi_dma_cmd(DISABLE);
		GPIO_SetBits(TFTLCD_CS_PIN_PORT,TFTLCD_CS_PIN);
		GPIO_SetBits(TFTLCD_DC_PIN_PORT,TFTLCD_DC_PIN);
	}
	else if(SPI_TFTLCD_DELAY == type)
		delay_ms(data[0]);
}

完整例程

由于程序过大,请到百度网盘下载
注:本例程基于正点原子STM32F4X系列例程和LCD厂商提供的LCD驱动例程编写。
链接:https://pan.baidu.com/s/1r9lXOBuMiD605mnE88Twfg?pwd=20g6
提取码:20g6

(%E9%93%BE%E6%8E%A5%EF%BC%9Ahttps://pan.baidu.com/s/1I6OKBH7uD3ixRnXObmeYLw)
在这里插入图片描述
在这里插入图片描述

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
OPPO R9s是一款大受欢迎的智能手机,而线刷包是一种用于刷写手机固件的工具。OPPO官方版本的线刷包是由OPPO官方推出的用于更新和修复设备软件的版本。 使用OPPO R9s线刷包官方版可以带来以下好处: 1. 系统更新:OPPO官方线刷包可以提供最新的系统版本,包括系统优化、安全更新和功能增加等。通过刷写官方线刷包,可以让手机系统保持最新状态,获得更好的用户体验和更高的稳定性。 2. 修复问题:有时候手机可能会遇到一些问题,比如卡顿、应用闪退等。通过刷写官方线刷包,可以修复这些问题并恢复手机的正常运行。 3. 解决系统错误:有时候手机可能会出现系统错误,导致无法正常开机或者进入系统。通过刷写官方线刷包,可以解决这些系统错误,使手机恢复正常运行。 4. 清除数据:刷写官方线刷包还可以清除手机上的数据,包括用户数据和应用程序。这可以帮助用户清理手机内存,提高手机的运行速度和性能。 需要注意的是,在刷写官方线刷包之前,我们应该备份重要的个人数据,因为刷机会清空手机数据。另外,刷机操作需要谨慎进行,最好在专业人士的指导下进行,以免出现意外情况。 总的来说,使用OPPO R9s线刷包官方版可以帮助我们保持手机系统更新、修复问题、解决系统错误和清除数据,提升手机的性能和稳定性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值