ESP32实验03:0.96tft液晶显示屏驱动

基于ST7735s的0.96寸tft屏幕显示

效果展示

ESP32实验03:0.96tft液晶显示屏驱动_第1张图片

  • 实现了时钟显示,基于ds1307模块,时钟字体采用的模拟数码管字体
  • 实现了图标显示,后续用于天气以及状态指示
  • 暂未添加网络校时,以及网络获取天气数据等功能
  • 界面显示没有采用第三方库(暂未找到合适的),采用原始的一个一个图标画点显示

整个实验断断续续耗时接近快2周时间,主要消耗的精力的有几个方面

  1. 熟悉和了解ST7735原理接口,及操控方法。难点在于理解其初始化代码和显示原理。
  2. 屏幕点亮画点调试,这一部分难点在于找到屏幕的(0,0)坐标,以及屏幕的偏移量,由于该屏幕的分辨率不是ST7735默认的两种分辨率,故存在x轴或者y轴的偏移量,这一点也是在不停的测试过程中测试出来的,这一部分耗了相当一大部分的精力。
  3. 文字及图片取模软件的深入了解,及测试。这里面特别坑的一点是,图片取模软件直接取得单色图片直接显示是有问题的,图片先要用图片取模软件转成要求尺寸的bmp图片,然后再将该图片导入文字取模软件取模,最终才能正常显示,这个坑也卡了很久。剩下就是取模扫描方式以及取模的高低字节顺序。

本文的重点讲解的方面也就是上述3个采坑较多的地方,最后一部分就简单展示下关键的代码,具体的代码连接间本文末尾。话不多讲,开始正文部分。

1、模块及开发环境简介

ESP32实验03:0.96tft液晶显示屏驱动_第2张图片
tft屏幕参数

分辨率:160*80
驱动芯片:ST7735S
通信接口:SPI
供电电压:3.3V

tft屏幕与ESP32模块连线

TFT ESP32
GND GND
VCC 3.3v
SCL 19(CLK)
SDA 23(MOSI)
DC 21
RST 18

其中
DC引脚用于控制spi总线传输的是命令还是数据。
DC:0传送命令,DC:1传送数数据,可以这么理解,要向st7735某个寄存器写入值,那么一般的逻辑是,先传输寄存器地址,再传输数据。当传输地址前,DC引脚置为low,当传输数据前,DC引脚置为high。也就是说DC引脚实际控制的是接下来是要写地址还是写数据。

RST引脚是硬件复位tft屏幕,当RST=0时,硬件复位。需要将RST=1然后重新初始化屏幕,才能正常显示。正常如果不用该引脚可以直接用上拉电阻拉高。在程序中,初始化前,需要将该引脚拉高。

开发环境

开发环境 vscode + platformIO
开发框架 esp-idf
开发语言 C

2、ST7735S说明

备注:ST775S是内置的tft屏幕面板内部的,一般情况下是看不到该芯片的样子。 所以不要拿到了屏幕模块后就想拆开看下ST7735芯片长啥样子,其实,笔者也很好奇芯片的样子。

2.1主要特性

支持3线或者4线SPI(区别在于3线没有用DC pin)
支持8位/16位并行接口
数据显示RAM 132H18RGB162V bits
颜色深度最高支持262K颜色,通常用的是64K
供电电压3.15V to 5V
最大分辨率132*162

2.2 3&4线spi数据图

ESP32实验03:0.96tft液晶显示屏驱动_第3张图片
3线spi实际每次传输的数据是9bit,最高为实现的就是DC引脚功能。
ESP32实验03:0.96tft液晶显示屏驱动_第4张图片

4线spi采用DC硬件引脚控制写命令和写数据。正常来说选择3线还是4线,屏幕在出厂的时候就确定了。3线还是4线是由ST7735内部的SPI4W引脚来决定的。目前市面上默认的液晶屏都是采用4线模式
spi选择
选择是串口还是spi实际也是出厂就设置好了的,其由内部的IM2引脚来确定。
并行选择
所以不要妄想将买到的并口屏幕改为spi串行通信,除非将整个屏幕拆开,重新连线,这基本是不现实的。

2.3初始化注意事项

在屏幕初始化过程中,会对st7735中的多个寄存器进行赋值,其中有一些寄存器的值直接影响到屏幕的点亮和显示,现将调试过程中出现的一些重要的寄存器初始化进行说明。

**10h Sleep In & 11h Sleep Out **
进入睡眠模式,上电后,或者软件或者硬件重置后,屏幕默认进入sleep 模式,此时屏幕是不会有任何显示的。
退出睡眠模式只有一个方式,通过设置11h
在这里插入图片描述
初始化时只需要将11h中写入0 即可。

**28h DisplayOff & 29h Display On **
上电默认是显示关闭模式,初始化时需要将液晶设置为显示开启模式
ESP32实验03:0.96tft液晶显示屏驱动_第5张图片
初始化时只需要将 29h中写入0即可打开显示开启模式。

** 3ah Interface Pixel Format **
屏幕色彩格式,设置屏幕的色彩位数。通常应用情况下,采用的都是16bit色彩模式,也就是常说的64K颜色。上电默认是18bit颜色。
ESP32实验03:0.96tft液晶显示屏驱动_第6张图片
初始化时,只需要在31h中写入5,即可将其设置为64K色模式。

2.4液晶显示原理分析

与屏幕显示位置及显示方向相关的寄存器主要有:

36h Memory Data Access Control 内存数据控制,用于控制,屏幕(0,0)原点的位置,及x轴和y轴的方向
2ah 列地址设置寄存器
2bh 行地址设置寄存器
2c 内存写入寄存器,某个像素点显示的颜色数据
其中最需要耗时也最需要深入了解的是36h寄存器,其涉及到屏幕的显示方向及显示位置。

36h 寄存器
ESP32实验03:0.96tft液晶显示屏驱动_第7张图片
在谈寄存器具体内容及含义前,先说明下一般比较推荐的显示方式。
一般是针对屏幕,将屏幕的左上脚默认为屏幕原点(0,0),X轴往右,Y轴往下。扫描方向,从左到右,从上到下,这比较符合人正常的书写顺序。可能不太好理解扫描,举个简单的例子
比如要在屏幕上显示8bit英文 HELLO WORLD
那么 H 起始坐标 (0,0),终点坐标 (7,7)
E 起始坐标 (8,0),终点坐标(15,7)
。。。。。
依次类推,那么D的起始和终点坐标分别是(80,0)(87,7)
显示的步骤如下

1、 设置行列地址,起始坐标和终点坐标
2、向屏幕内存写入每个像素点的颜色数据
3、屏幕将内存中的数据按照扫描顺序显示在屏幕上
扫描顺序从左到右,则先显示(0,0)到(7,7)区域的 H,显示顺序 H -> E -> …-> D
如果是从右向左,则先显示(80,0)(87,7)的D-> L … -> H
上下扫描也是如此,如果有多行,上下扫描,显示上衣行再显示下一行,如果是下上扫描,则先显示下一行再显示上一行。

一般情况下,不影响最终显示结果,但是为了便于理解和习惯,推荐扫描顺序从左到右,从上到小

ESP32实验03:0.96tft液晶显示屏驱动_第8张图片

再回到36h寄存器本身
MY 是镜像Y轴
MX是镜像X轴
MV是XY轴调换位置
以上图为例,假设此时 MY =0; MX =0 ,MV =0 则
当MY=1 MX =0 ,MV =0,坐标原点在左下角
当MY=0 MX =1 ,MV =0,坐标原点在右上角
当MY=1 MX =1 ,MV =0,坐标原点在右下角

ML 竖直方向扫描顺序
MH水平方向扫描顺序
通常都设置为0 从左到右,从上到下

屏幕原点的方向就依靠36H寄存器进行调整,当拿到一个新的屏幕的时候,就要选择屏幕的坐标原点,通过调整36H,实现正对屏幕,原点位于左上角。

**2ah列地址设置 **

ESP32实验03:0.96tft液晶显示屏驱动_第9张图片
列地址对应的是X轴,其由4个字节组成,第一个字节是起始地址高8位,第二个字节是起始地址低8为,第三个字节是终点坐标高8位,第四个字节是终点坐标低8位。

这一值得注意的是,采用的大端模式,低地址存储的高位字节,高地址存储的低位字节
比如如果地址是0xa0b1,则传输大端模式是应该先传输0xa0,然后是0xb1;通常的用小端模式都是先传输0xb1然后是0xa0

**2bh行地址设置 **
ESP32实验03:0.96tft液晶显示屏驱动_第10张图片
行地址方式与列地址完全一致,就不过多说明。

再说下st7735屏幕分辩率的选择。ST7735最大支持两种分辨率 132162和128160
到底最大支持哪种分辨率是在屏幕模块一出厂就确定了的,其取决月GM1和GM0两个引脚
ESP32实验03:0.96tft液晶显示屏驱动_第11张图片
由于笔者用的屏幕是160*80所以不管是哪种方式,都不受影响。这主要是山寨屏幕,没有出场说明书,不知道出场的配置是怎么样的。这里当时也想了好久才想明白。
ESP32实验03:0.96tft液晶显示屏驱动_第12张图片
这张图里面实际上就将36h的设置写明白了。看图吧就不多赘述了。

3、文字取模和图片取模软件

文字取模和图片取模软件都是将要在屏幕上显示的转化成为一个色彩集合数组。显示是设置好地址后将该数组按照顺序写入屏幕内存,最终在屏幕上显示。这里面也有一些坑,如果没注意,可能会显示不正常。在此一次将这两种取模软件整理清楚。

3.1文字取模软件

文字取模软件通常使用的是PCtoLCD2002,界面如下图
ESP32实验03:0.96tft液晶显示屏驱动_第13张图片
其中的关键点主要是在设置选项里面。
那么一个一个来测试,以生活的“生”字为例:

点阵格式 取模方式 取模走向 字模
阴码 逐行 逆向 0x80,0x00,0x88,0x00,0x88,0x00,0x88,0x00,0xFC,0x3F,0x84,0x00,0x82,0x00,0x81,0x00,
0x80,0x00,0xFC,0x1F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x7F,0x00,0x00
阴码 逐行 顺向 0x01,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x3F,0xFC,0x21,0x00,0x41,0x00,0x81,0x00,
0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00,
阴码 逐列 顺向 0x01,0x02,0x02,0x02,0x0C,0x42,0x78,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0xFF,0xFE,
0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x02,0x00,0x02,0x00,0x00,
阴码 逐列 逆向 0x80,0x40,0x40,0x40,0x30,0x42,0x1E,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0xFF,0x7F,
0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x40,0x00,0x40,0x00,0x00,

阴码:需要点亮的点为1,如上图,生活的“生”字最上面一个点占的bit7,如果是左往右写点就是0x80。
逐行就是从左往右一个bit一个bit点亮数码管,逆向是低位在前,顺向是高位在前
分析表格最上面两行,逆向第一个字节是0x80,顺向第一个字节是0x01,将二者转换为二进制

走向 HEX 二进制
逆向 0x80 1000 0000
顺向 0x01 0000 0001

逆向顺向的区别是转成二进制后,二者顺序颠倒。

ESP32实验03:0.96tft液晶显示屏驱动_第14张图片
如图数码管,假设地址(0,0)在左上角。如果要显示“生”字最上面的一个点
逆向:写入顺序(0,0)(1,0)(2,0)(3,0)(4,0)(5,0)… (7,0)
顺向:写入顺序(7,0)(6,0)… (2,0)(1,0)(0,0)
都是在(7,0)坐标写入1,其他未写入0,则点亮了“生”字最上面的一个点。对应到tft屏幕写入的就是颜色需要点亮就写入前景色,需要灭的就写入背景色。

这里要注意:在写代码向st7735的2c寄存器写入的时候,逆向时要先判断bit0的值,如果是1则写入前景,0背景,然后是bit1,bit2…。顺向的时候,则要先判断bit7的值,然后bit6,bit5…

当设置逐列时,则写入顺序为
逆向:(0,0)(0,1)(0,2)… (0,7)
顺向:(0,7)(0,6)…(0,1) (0,0)
再此就不在进行二进制转换分析了。感兴趣的可以自行研究下

从上述取模方式来看,由于st7735我们推荐的扫描方式是从左到右从上到小,这对应的取模顺序是逐行,逆向。所以只要任何屏幕我们都采用这种方式的时候,取模时就可以固定逐行+逆向

3.2图片取模软件

图片取模软件通常使用的是Image2Lcd V2.9版本。其机密如下图所示
ESP32实验03:0.96tft液晶显示屏驱动_第15张图片

扫描模式与文字取模一致,16位真彩色,取出来的数组一共是3200个,40402。每个像素点颜色占2个字节。
这里的高位在前,是色彩的高8字节在前。正常颜色0xfbba,正常生成的数组是,0xba,0xfb。高位在前则为:0xfb,0xba。
这与文字取模里的顺向和逆向是有区别的。

正常情况下建议,采用默认的低位在前的方式。

3.3图片取单色模

如果要将上述的qq图片成为40*40单色显示,直接用Image2Lcd设置为单色是不行的。经过多次测试,这种方法取出模,数组是错误的。

ESP32实验03:0.96tft液晶显示屏驱动_第16张图片
正确的方式是:
1、先用Image2Lcd将图片保存为单色图片
ESP32实验03:0.96tft液晶显示屏驱动_第17张图片
2、再将单色图片导入到文字取模软件PCtoLcd2002中,
ESP32实验03:0.96tft液晶显示屏驱动_第18张图片
3、生成数组。阴码,逐行式,逆向

单色qq图片文字取模软件取模结果如下。共有200个字节,40*40/8 每8个像素点占用一个字节

0x00,0x00,0x30,0x00,0x00,0x00,0x00,0xFE,0x03,0x00,0x00,0x80,0xFF,0x0F,0x00,0x00,
0x60,0xFE,0x1F,0x00,0x00,0xB0,0xFF,0x7F,0x00,0x00,0xF8,0xFF,0x7F,0x00,0x00,0xFC,
0xFF,0xFF,0x00,0x00,0xFC,0xF1,0xFC,0x01,0x00,0xFE,0xF3,0xF9,0x01,0x00,0xFE,0xF0,
0xF9,0x03,0x00,0xFF,0xB0,0xF8,0x03,0x08,0xFF,0x30,0xF8,0x03,0x1F,0xFF,0x70,0xF8,
0x03,0x3E,0xFF,0xFF,0xFC,0x03,0x7E,0xFF,0xFF,0xFF,0x07,0xFC,0x7F,0x00,0xFC,0x07,
0xF8,0x1F,0x00,0xF0,0x0F,0xF8,0x5F,0x00,0xEC,0x0F,0xF0,0xFF,0x01,0xFE,0x0F,0xE0,
0xFF,0xFF,0xFF,0x0F,0xC0,0xDF,0xFF,0xFF,0x1F,0x80,0x7F,0xFC,0xFF,0x3F,0x80,0xFF,
0xE7,0xFF,0x3F,0x80,0xF9,0xFF,0xFF,0x7E,0x80,0xE1,0xFF,0x7F,0x7C,0x80,0x01,0xFE,
0x7F,0xFC,0x80,0x01,0x00,0x7E,0xFC,0x80,0x01,0x00,0x7E,0xFC,0x80,0x01,0x00,0x7E,
0xFC,0x00,0x01,0x00,0x7E,0xEE,0x00,0x03,0x00,0x3C,0xC6,0x00,0x02,0x00,0x00,0x07,
0x00,0x06,0x00,0x00,0x03,0x00,0x0C,0x00,0x80,0x03,0x00,0x19,0x00,0xC0,0x04,0x80,
0x30,0x00,0x70,0x08,0x80,0xC0,0x01,0x3C,0x08,0x80,0x00,0xDF,0x0F,0x08,0x00,0x03,
0x8C,0x01,0x04,0x00,0xFC,0x03,0xFE,0x03,/*"C:\Users\yp\Downloads\0.96TFT测试程序\0.96TFT测试程序\图片取模软件(赠送)\单色qq.bmp",0*/
/* (40 X 40 )*/

经测试能正常显示。

而直接用图片取模软件,生成的数组如下:

0X00,0X00,0X0C,0X00,0X00,0X00,0X00,0X7F,0XC0,0X00,0X00,0X01,0XFF,0XF0,0X00,0X00,
0X06,0X7F,0XF8,0X00,0X00,0X0D,0XFF,0XFE,0X00,0X00,0X1F,0XFF,0XFE,0X00,0X00,0X3F,
0XFF,0XFF,0X00,0X00,0X3F,0X8F,0X3F,0X80,0X00,0X7F,0XCF,0X9F,0X80,0X00,0X7F,0X0F,
0X9F,0XC0,0X00,0XFF,0X0D,0X1F,0XC0,0X10,0XFF,0X0C,0X1F,0XC0,0XF8,0XFF,0X0E,0X1F,
0XC0,0X7C,0XFF,0XFF,0X3F,0XC0,0X7E,0XFF,0XFF,0XFF,0XE0,0X3F,0XFE,0X00,0X3F,0XE0,
0X3F,0XF8,0X00,0X0F,0XF0,0X1F,0XFA,0X00,0X37,0XF0,0X0F,0XFF,0X80,0X7F,0XF0,0X07,
0XFF,0XFF,0XFF,0XF0,0X03,0XFB,0XFF,0XFF,0XF8,0X01,0XFE,0X3F,0XFF,0XFC,0X01,0XFF,
0XC3,0XFF,0XFC,0X01,0X9F,0XFF,0XFF,0X7E,0X01,0X87,0XFF,0XFE,0X3E,0X01,0X80,0X7F,
0XFE,0X3F,0X01,0X80,0X00,0X7E,0X3F,0X01,0X80,0X00,0X7E,0X3F,0X01,0X80,0X00,0X7E,
0X3F,0X01,0X80,0X00,0X7E,0X77,0X00,0XC0,0X00,0X3C,0X63,0X00,0X40,0X00,0X00,0XE0,
0X00,0X60,0X00,0X00,0XC0,0X00,0X30,0X00,0X01,0X80,0X00,0X98,0X00,0X03,0X80,0X01,
0X0C,0X00,0X0E,0X20,0X01,0X03,0X00,0X3C,0X10,0X01,0X01,0XFF,0XF0,0X10,0X00,0XC0,
0X71,0XC0,0X60,0X00,0X3F,0XC0,0X7F,0X80

该数组显示不正常。

切记,单色图片取模要先用Imag2Lcd转成单色bmp图片,然后用PCtoLcd转成数组

4、重点部分代码展示

设置显示区域起始坐标和终点坐标。传送方式为大端模式,要先传送地址的高8位,然后再是低8位。

void lcd_set_region(uint8_t  x_s,uint8_t y_s,uint8_t x_e,uint8_t y_e)
{
    /*in st7735 col address set regeister 2Ah ,first byte send high 8bit second byte send lou 8bit,row address 2Bh is same*/
    uint8_t x_data[4]={0x00,x_s,0x00,x_e};
    uint8_t y_data[4]={0x00,y_s+24,0x00,y_e+24};
    lcd_cmd(my_spi,0x2A);
    lcd_data(my_spi,x_data,4);

    lcd_cmd(my_spi,0x2b);
    lcd_data(my_spi,y_data,4);
    lcd_cmd(my_spi,0x2c);
}

比较坑的是,这块0.96寸tft屏幕,像素不是从0开始的,所以y轴有一个24的偏移量,这一点太坑了,如果不知道,直接在(0,0)显示一个颜色,实际是没有的,因为这个点超出屏幕的显示范围。

画点函数,要先传送颜色的高8位,然后是低8位,采用的也是大端传输方式。

void lcd_draw_point(uint8_t x ,uint8_t y,uint16_t color)
{
    uint8_t temp[2];
    temp[0]=color>>8;
    temp[1]=color;
    lcd_set_region(x,y,x+1,y+1);
    lcd_data(my_spi,temp,2);

}

显示单色图片,注意大端模式。另外取模时是逆向,则先要判断bit0的值 data>>0&0x01;如果是顺向。则先要判断bit7的值,data<<0&0x80

void lcd_draw_pic(uint8_t x,uint8_t y,uint8_t x_pixel,uint8_t y_pixel, uint16_t fc,uint16_t bc,char *s)
{
	uint16_t i,j,k;
	uint8_t  x_length = x_pixel/8;
	uint8_t x_yu = x_pixel%8;
	uint16_t fc_temp,bc_temp;
	/*st7735 */
	fc_temp =(fc <<8)|(fc>>8);
	bc_temp =(bc <<8)|(bc>>8);
	if(x_yu!=0)
	{
		x_length = x_length +1;
	}
	lcd_set_region(x,y,x+x_pixel-1,y+y_pixel-1);
	// lcd_set_region(x,y,x+39,y+39);
	for(i=0;i<y_pixel;i++)
	{
		for(j=0;j<x_length;j++)
		{
			for (k=0;k<8;k++)
			{
				if(((*(s+j+i*x_length))>>k)&0x01)
				{
					lcd_write_data16bit(fc_temp);
				}
				else 
				{
					lcd_write_data16bit(bc_temp);
				}
				/*check the last none 8bit byte of one row*/
				if (x_yu!=0 && j==(x_length-1) && k==(x_yu-1))
				{
					printf("break \r\n");
					break;
				}
			}
		}
	}
}

具体代码链接如下
https://gitee.com/yvany/esp32projects.git

ESP32实验03:0.96tft液晶显示屏驱动_第19张图片

欢迎各位大佬指导和交流!!!

你可能感兴趣的:(esp32,stm32,esp32,tft,st7735)