最近的项目,之前用的是st7735 TFT显示屏,128 * 160的,客户希望能显示更多的信息,又希望屏的尺寸不能大,所以我们找到了ST7789驱动的TFT显示屏,分辨率240 * 240,屏幕尺寸比之前的还要小一些。
在网上搜索了一下,有不少st7789的micropython代码,但很多都只能支持GB2312汉字库,只能想显示哪些汉字把对应的汉字点阵字模数据写到代码中,很不方便。就算有少部分提到支持汉字库,但没有提供汉字库文件。所以决定在st7735的基础上修改代码支持st7789。
st7735 TFT显示屏的驱动我们就不多说,有兴趣的朋友可以参考:
MicroPython 开发ESP32应用教程 之 WIFI简单应用 :时间同步、天气信息获取,ST7735 TFT屏驱动及任意中文字符显示
一、硬件准备:
1、支持Micropython的ESP32s3开发板
2、st7735 TFT 128*160 显示屏
3、st7789 TFT 240 * 240显示屏
4、面包板及连接线若干
显示屏与开发板的连接方式:
st7735与st7789显示屏连接ESP32s3的方式相同。
st7735或st7789 | ESP32S3 |
SCL | IO4 |
SDA | IO5 |
RST | IO6 |
DC | IO7 |
CS | IO15 |
BLK | IO18 |
二、驱动代码修改
如前面所说,我们st7789的驱动代码是在st7735的代码基础上修改而来。
主要修改的部分如下:
1、初始化:
初始化主要是向显示屏的驱动芯片寄存器写入不同的数据,具体的可以查阅ST7735 及ST 7789的规格书,我们这里直接给出代码,大家可以对比一下:
#st7735初始化
def _init(self):
self._reset()
init_commands = [
(0x01, None), # Software reset
(0x11, None), # Sleep exit
(0xB1, b'\x01\x2C\x2D'), # Frame Rate Control (normal mode)
(0xB2, b'\x01\x2C\x2D'), # Frame Rate Control (idle mode)
(0xB3, b'\x01\x2C\x2D\x01\x2C\x2D'), # Frame Rate Control (partial mode)
(0xB4, b'\x07'), # Display Inversion Control
(0xC0, b'\xA2\x02\x84'), # Power Control 1
(0xC1, b'\xC5'), # Power Control 2
(0xC2, b'\x0A\x00'), # Power Control 3
(0xC3, b'\x8A\x2A'), # Power Control 4
(0xC4, b'\x8A\xEE'), # Power Control 5
(0xC5, b'\x0E'), # VCOM Control 1
(0x20, None), # Display Inversion Off
(0x36, b'\xC8' if self.rotate == 0 else b'\x08'), # MADCTL
(0x3A, b'\x05'), # Color Mode (16-bit)
(0x29, None), # Display On
]
for cmd, data in init_commands:
self._write(cmd, data)
time.sleep_ms(10)
#st7789 初始化
def _init(self):
self._reset()
init_commands = [
(0x01, None), # Software reset
(0x11, None), # Sleep exit
(0x36, b'\xC0' if self.rotate == 0 else b'\x00'),
(0x3A, b'\x55'), # Color Mode (16-bit)
(0xB2, b'\x0C\x0C\x00\x33\x33'),
(0xB7, b'\x35'),
(0xBB, b'\x32'),
(0xC2, b'\x01'),
(0xC3, b'\x19'),
(0xC4, b'\x20'),
(0xC6, b'\x0F'),
(0xD0, b'\xA4\xA1'),
(0xE0, b'\xD0\x08\x0E\x09\x09\x05\x31\x33\x48\x17\x14\x15\x31\x34'), # VCOM Control 1
(0xE1, b'\xD0\x08\x0E\x09\x09\x15\x31\x33\x48\x17\x14\x15\x31\x34'), # VCOM Control 1
(0x21, None),
(0x2A, b'\x00\x00\x00\xEF'), #column address set
(0x2B, b'\x00\x00\x00\xEF'), #row address set
(0x29, None)
]
for cmd, data in init_commands:
self._write(cmd, data)
time.sleep_ms(10)
2、显示分辨率
因为显示分辨率的不同,需要修改的主要有以下三个地方:
1)、主程序中对st7735及st7789类的初始化
DISPLAY_ST7735 = const(0)
DISPLAY_ST7789 = const(1)
DISPLAY_DEVICE = DISPLAY_ST7735
spi = SPI(2,
baudrate=80000000,
polarity=0,
phase=0,
sck=Pin(4),
mosi=Pin(5),
miso=Pin(16))
# 定义控制引脚
dc = Pin(7,Pin.OUT)
cs = Pin(15,Pin.OUT)
rst= Pin(6,Pin.OUT)
bl = Pin(18,Pin.OUT)
# 初始化显示屏 (128x160)
if DISPLAY_DEVICE == DISPLAY_ST7735:
tft = ST7735(128, 160, spi, dc, cs, rst,None,rotate=0)
else:
tft = ST7789(240, 240, spi, dc, cs, rst,bl,rotate=1)
2)、st7735及st7789类中显示函数的分辨率不同
#st7735
def show(self):
if self.bl is not None:
self.bl(1)
self._write(0x2A, b'\x00\x00\x00\x7F') # Column address set
self._write(0x2B, b'\x00\x00\x00\x9F') # Row address set
self._write(0x2C, self.buffer) # Memory write
#ST7789
def show(self):
if self.bl is not None:
self.bl(1)
self._write(0x2A, b'\x00\x00\x00\xF0') # Column address set
self._write(0x2B, b'\x00\x00\x00\xF0') # Row address set
self._write(0x2C, self.buffer) # Memory write
3)、修改字库类,支持不同的分辨率
def __init__(self, font_file,x_max=240,y_max=240):
self.font_file = font_file
self.font = open(font_file, "rb", buffering=0xff)
self.bmf_info = self.font.read(16)
if self.bmf_info[0:2] != b"BM":
raise TypeError("字体文件格式不正确: " + font_file)
self.version = self.bmf_info[2]
if self.version != 3:
raise TypeError("字体文件版本不正确: " + str(self.version))
self.map_mode = self.bmf_info[3] # 映射方式
self.start_bitmap = struct.unpack(">I", b'\x00' + self.bmf_info[4:7])[0] # 位图开始字节
self.font_size = self.bmf_info[7] # 字体大小
self.bitmap_size = self.bmf_info[8] # 点阵所占字节
self.x_max = x_max #增加分辨率
self.y_max = y_max
#根据分辨率的不同,判断自动换行
def text(self, display, string, x, y, color=1, font_size=24, reverse=False, clear=False, show=False,
half_char=True, auto_wrap=True):
"""通过显示屏显示文字
使用此函数显示文字,必须先确认显示对象是否继承与 framebuf.FrameBuffer。
如果显示对象没有 clear 方法,需要自行调用 fill 清屏
Args:
display: 显示实例
string: 字符串
x: 字体左上角 x 轴
y: 字体左上角 y 轴
color: 颜色
font_size: 字号
reverse: 是否反转背景
clear: 是否清除之前显示的内容
show: 是否立刻显示
half_char: 是否半字节显示 ASCII 字符
auto_wrap: 自动换行
**kwargs:
Returns:
None
"""
font_size = font_size or self.font_size
initial_x = x
# 清屏
try:
display.clear() if clear else 0
except AttributeError:
print("请自行调用 display.fill(*) 清屏")
for char in range(len(string)):
# 是否自动换行
if auto_wrap:
if auto_wrap and ((x + font_size // 2 >= self.x_max and ord(string[char]) < self.x_max and half_char) or
(x + font_size >= self.x_max and (not half_char or ord(string[char]) > self.x_max))):
y += font_size
x = initial_x
# 回车
if string[char] == '\n':
y += font_size
x = initial_x
continue
# Tab
elif string[char] == '\t':
x = ((x // font_size) + 1) * font_size + initial_x % font_size
continue
# 其它的控制字符不显示
elif ord(string[char]) < 16:
continue
# 超过范围的字符不会显示*
if x > self.x_max or y > self.y_max:
continue
byte_data = list(self.get_bitmap(string[char]))
# print(string[char],hex(ord(string[char])))
# print(byte_data)
# 反转
if reverse:
for _pixel in range(len(byte_data)):
byte_data[_pixel] = ~byte_data[_pixel] & 0xff
# 缩放和色彩*
if color > 1 or font_size != self.font_size:
bit_data = self._to_bit_list(byte_data, font_size)
if color > 1:
display.blit(
framebuf.FrameBuffer(bytearray(self._color_render(bit_data, color)), font_size, font_size,
framebuf.RGB565), x, y)
# print(bytearray(self._color_render(bit_data, color)))
else:
display.blit(
framebuf.FrameBuffer(bytearray(self._bit_list_to_byte_data(bit_data)), font_size, font_size,
framebuf.MONO_HLSB), x, y)
else:
display.blit(framebuf.FrameBuffer(bytearray(byte_data), font_size, font_size, framebuf.MONO_HLSB), x, y)
# 英文字符半格显示
if ord(string[char]) < self.x_max and half_char:
x += font_size // 2
else:
x += font_size
display.show() if show else 0
至此,我们驱动st7789TFT显示屏的代码就修改好了,完整代码及字库文件可以从下面的链接下载:
Micropythonforesp32s3st7735TFT显示屏驱动、st7789TFT显示屏驱动、支持中文字符显示资源-优快云文库