ST7735S简介

ST7735S是一块1.8英寸采用SPI通信的TFT全彩屏,分辨率是128*160,这里采用RGB565 16bit的色块编译模式(RGB565即高五位为Red,第五位为Blue,中间六位为Green,共16位)。本文仅设计该屏幕的简单应用,不对底层原理进行深究。

ST7735S接口说明

BLK:这里用不到,可以不用连接
CS:片选信号
DC:数据模式选择信号 1为写命令/0为写数据
RST:复位信号
SDA:SPI数据线
SCL:SPI时钟线
VDD:兼容+5V和+3.3V
GND:接地

ST7735S STM32引脚配置

用的单片机是STM32F103C8T6,主频72MHz,硬件模拟SPI,CubeMX的GPIO配置如下
在这里插入图片描述

ST7735S控制流程

ST7735S控制流程

复位信号

在这里插入图片描述
复位信号低电平有效,要求时间大于10us,复位后最好再等待120ms`

void lcd_reset()
{
	RST_L;//RST引脚拉低
	HAL_Delay(1);
	RST_H;//RST引脚拉高
	HAL_Delay(120);
}

参数配置

参数配置的大体流程如下:
1.执行0X11命令,退出睡眠模式,执行命令后延时120ms
在这里插入图片描述

2.配置0XB1,0XB2,0XB3,0XB4寄存器,配置在不同颜色模式下屏幕的刷新率,0XB4寄存器配置屏幕是否反色

在这里插入图片描述
3.配置0XC0,0XC1,0XC2,0XC3,0XC4寄存器,配置显示屏在不同颜色不同模式下的电压

4.配置0X36寄存器,设置显存数据访问方式。我在复制代码的时候没有仔细地阅读手册,导致到最后的颜色不正,研究了半天才发现是用的BGR的颜色顺序,最开始还以为是屏幕坏了,还特地写了一个调换顺序的函数,到后来仔细读了一遍手册之后发现是有一位可以控制顺序的,36H的RGB位从1变到0颜色就正常了。
在这里插入图片描述
5.配置0XE0,0XE1寄存器,配置伽马极性
6.执行0X3A,设置像素格式
在这里插入图片描述
7.执行0X29命令,进行显示
在这里插入图片描述

如果不想了解具体的寄存器参数配置的话可以直接使用官方给出的程序进行初始化,直接复制下面的代码就可以了

void lcd_init()
{
	lcd_reset();//Reset before LCD Init.
		
	//LCD Init For 1.44Inch LCD Panel with ST7735R.
	lcd_write_command(0x11);//Sleep exit 
	HAL_Delay(120);
		
	//ST7735R Frame Rate	 4
	lcd_write_command(0xB1); 
	lcd_write_data(0x01); 
	lcd_write_data(0x2C); 
	lcd_write_data(0x2D); 
									
	lcd_write_command(0xB2); 
	lcd_write_data(0x01); 
	lcd_write_data(0x2C); 
	lcd_write_data(0x2D); 

	lcd_write_command(0xB3); 
	lcd_write_data(0x01); 
	lcd_write_data(0x2C); 
	lcd_write_data(0x2D); 
	lcd_write_data(0x01); 
	lcd_write_data(0x2C); 
	lcd_write_data(0x2D); 
	
	lcd_write_command(0xB4); //Column inversion 
	lcd_write_data(0x07); 
	
	//ST7735R Power Sequence
	lcd_write_command(0xC0); 
	lcd_write_data(0xA2); 
	lcd_write_data(0x02); 
	lcd_write_data(0x84); 
	lcd_write_command(0xC1); 
	lcd_write_data(0xC5); 

	lcd_write_command(0xC2); 
	lcd_write_data(0x0A); 
	lcd_write_data(0x00); 

	lcd_write_command(0xC3); 
	lcd_write_data(0x8A); 
	lcd_write_data(0x2A); 
	lcd_write_command(0xC4); 
	lcd_write_data(0x8A); 
	lcd_write_data(0xEE); 
	
	lcd_write_command(0xC5); //VCOM 
	lcd_write_data(0x0E); 
	
	lcd_write_command(0x36); //MX, MY, RGB mode 
	lcd_write_data(0xA0); //竖屏C8 横屏08 A8
//	lcd_write_data(0xC0); //竖屏C8 横屏08 A8 
	
	//ST7735R Gamma Sequence
	lcd_write_command(0xe0); 
	lcd_write_data(0x0f); 
	lcd_write_data(0x1a); 
	lcd_write_data(0x0f); 
	lcd_write_data(0x18); 
	lcd_write_data(0x2f); 
	lcd_write_data(0x28); 
	lcd_write_data(0x20); 
	lcd_write_data(0x22); 
	lcd_write_data(0x1f); 
	lcd_write_data(0x1b); 
	lcd_write_data(0x23); 
	lcd_write_data(0x37); 
	lcd_write_data(0x00); 	
	lcd_write_data(0x07); 
	lcd_write_data(0x02); 
	lcd_write_data(0x10); 

	lcd_write_command(0xe1); 
	lcd_write_data(0x0f); 
	lcd_write_data(0x1b); 
	lcd_write_data(0x0f); 
	lcd_write_data(0x17); 
	lcd_write_data(0x33); 
	lcd_write_data(0x2c); 
	lcd_write_data(0x29); 
	lcd_write_data(0x2e); 
	lcd_write_data(0x30); 
	lcd_write_data(0x30); 
	lcd_write_data(0x39); 
	lcd_write_data(0x3f); 
	lcd_write_data(0x00); 
	lcd_write_data(0x07); 
	lcd_write_data(0x03); 
	lcd_write_data(0x10);  
	
	lcd_write_command(0x2a);
	lcd_write_data(0x00);
	lcd_write_data(0x00+2);
	lcd_write_data(0x00);
	lcd_write_data(0x80+2);

	lcd_write_command(0x2b);
	lcd_write_data(0x00);
	lcd_write_data(0x00+3);
	lcd_write_data(0x00);
	lcd_write_data(0x80+3);
	
	lcd_write_command(0xF0); //Enable test command  
	lcd_write_data(0x01); 
	lcd_write_command(0xF6); //Disable ram power save mode 
	lcd_write_data(0x00); 
	
	lcd_write_command(0x3A); //65k mode 
	lcd_write_data(0x05); 
	
	
	lcd_write_command(0x29);//Display on
}

坐标位置控制

ST7735S的分辨率为128*160,直接可以用四个八位的数据表示,分别是X的起始坐标和终点坐标,Y的起始坐标和终点坐标,通过写入0X2A和0X2B寄存器将四个八位坐标发送至屏幕,因为分辨率仅用低八位就可以表示,所以高八位全为0。之后配置0X2C寄存器,进行坐标范围内的颜色配置。
在这里插入图片描述
在这里插入图片描述

//写入屏幕地址函数
void lcd_write_address(uint8_t x_start,uint8_t y_start,uint8_t x_end,uint8_t y_end)
{
	lcd_write_command(0x2a);
	lcd_write_data(x_start >> 8);
	lcd_write_data(x_start);
	lcd_write_data(x_end >> 8);
	lcd_write_data(x_end);
	
	lcd_write_command(0x2b);
	lcd_write_data(y_start >> 8);
	lcd_write_data(y_start);
	lcd_write_data(y_end >> 8);
	lcd_write_data(y_end);	
	
	lcd_write_command(0x2c);
}

全屏颜色填充

颜色填充大概的思路是先选定颜色区域最后用两个for循环遍历区域,每个像素点都写入一个16位的颜色数据就可以了。

//常用的颜色数据
#define RED  		0xf800
#define GREEN		0x07e0
#define BLUE 		0x001f
#define WHITE		0xffff
#define BLACK		0x0000
#define YELLOW      0xFFE0
//全屏颜色填充
void lcd_set_color(uint16_t color)
{
	lcd_write_address(0,0,159,127);//像素160*128
	for(int i = 0; i < 160; i++)
	{
		for(int j = 0; j < 128; j++)
		{
			lcd_write_data_u16(color);
		}
	}
} 

区域颜色填充

区域填充原理也是和全屏填充的原理一样,划定区域后计算出区域的长和宽的像素点个数,之后用两个for循环对区域的每个像素点进行遍历然后写入16位的颜色数据就可以了。

//区域颜色填充
void lcd_set_area_color(uint8_t x_start,uint8_t y_start,uint8_t x_end,uint8_t y_end,uint16_t color)
{
	lcd_write_address(x_start,y_start,x_end,y_end);
	//计算填充区域的长度和宽度,终点坐标减起点坐标+1
	uint8_t x_len = x_end - x_start + 1;//计算x坐标的长度
	uint8_t y_len = y_end - y_start + 1;//计算y坐标的长度
	for(int i = 0; i < x_len; i++)
	{
		for(int j = 0; j < y_len; j++)
		{
			lcd_write_data_u16(color);
		}
	}
}

画点

描点函数就不用计算x与y坐标的长度了,直接写入要描的点的x,y坐标后写入颜色数据就可以了。

//描点函数
void lcd_set_point_color(uint8_t x_point,uint8_t y_point,uint16_t color)
{
	lcd_write_address(x_point,y_point,x_point,y_point);
	lcd_write_data_u16(color);
}

画图

画图函数需要在像素点软件上生成一个图像数组后直接遍历数组就可以了,但是要手动的填写你需要显示的图片的分辨率,比如我现在要显示的图像的分辨率是160*120的,把地址的x和y的起始坐标写到0,终点坐标写到160-1和120-1就可以了。因为软件生成的数组是八位的,所以需要一个for循环把前后两个数据合并成一个16位的颜色数据发送出去,然后遍历一下就可以了。

void showimage(const unsigned char *p) //显示图片
{
	unsigned char picH,picL;
	lcd_set_color(0XFFFF); //清屏  

	lcd_write_address(0,0,159,119);
	for(uint16_t i=0;i<160*120;i++)
	 {	
		picL=*(p+i*2);	//数据低位在前
		picH=*(p+i*2+1);				
	   lcd_write_data_u16(picH<<8|picL);  						
	 }	
}

ST7735S图片取模

如果我们想要在屏幕上显示我们想要的图片,那么就需要用到图片取模软件来把对应的图片进行取模,也就是转换成数组进行显示。我用的是image2lcd这个软件,下面来简单介绍一下这个软件。
在这里插入图片描述
生成好数组后直接把数组拷贝到程序中然后遍历这个数组就可以了,要注意的是单片机的flash能不能容得下这个图片大小。

基本函数

在这里放上一些硬件SPI的基本函数,如果不想自己写的话可以直接copy。

#define	SCL_H HAL_GPIO_WritePin(GPIOA,SCL_Pin,GPIO_PIN_SET) 	//SCL --> High
#define	SCL_L HAL_GPIO_WritePin(GPIOA,SCL_Pin,GPIO_PIN_RESET) //SCL --> Low

#define	SDA_H HAL_GPIO_WritePin(GPIOA,SDA_Pin,GPIO_PIN_SET) 	//SDA --> High
#define	SDA_L HAL_GPIO_WritePin(GPIOA,SDA_Pin,GPIO_PIN_RESET) //SDA --> Low

#define	RST_H HAL_GPIO_WritePin(GPIOA,RST_Pin,GPIO_PIN_SET) 	//RST --> High
#define	RST_L HAL_GPIO_WritePin(GPIOA,RST_Pin,GPIO_PIN_RESET) //RST --> Low

#define	DC_H HAL_GPIO_WritePin(GPIOA,DC_Pin,GPIO_PIN_SET) 		//DC --> High
#define	DC_L HAL_GPIO_WritePin(GPIOA,DC_Pin,GPIO_PIN_RESET) 	//DC --> Low

#define	CS_H HAL_GPIO_WritePin(GPIOA,CS_Pin,GPIO_PIN_SET) 		//CS --> High
#define	CS_L HAL_GPIO_WritePin(GPIOA,CS_Pin,GPIO_PIN_RESET) 	//CS --> Low

//写数据: DC = 0
void lcd_write_data(uint8_t data)
{
	CS_L;
	DC_H;
	for(int i = 0; i < 8; i++)
	{
		if(data & 0x80)	SDA_H;
		else			SDA_L;
		SCL_L;
		SCL_H;
		data = data << 1;
	}
	CS_H;
}

//写操作: DC = 1
void lcd_write_command(uint8_t data)
{
	CS_L;
	DC_L;
	for(int i = 0; i < 8; i++)
	{
		if(data & 0x80)	SDA_H;
		else			SDA_L;
		SCL_L;
		SCL_H;
		data = data << 1;
	}
	CS_H;
}

//写十六位数据
void lcd_write_data_u16(uint16_t data)
{
	lcd_write_data(data >> 8);	
	lcd_write_data(data & 0x0f);	
}

发送数据的逻辑遵循下面的时序图
在这里插入图片描述

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐