MicroPython for ESP32开发st7789 TFT显示屏驱动、ST7735TFT 显示屏驱动

 最近的项目,之前用的是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或st7789ESP32S3         
SCLIO4
SDAIO5
RSTIO6
DCIO7
CSIO15
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显示屏驱动、支持中文字符显示资源-优快云文库

 

### 使用 MicroPython 和 LVGL 驱动 ST7789 显示屏 要在 ESP32-S3 上使用 MicroPython 和 LVGL 框架来驱动 ST7789 显示屏,需完成几个主要部分的工作。首先是硬件连接设置,其次是软件配置。 #### 硬件连接 确保 ESP32-S3 板通过 SPI 接口正确连接到 ST7789 屏幕。通常情况下,这涉及到 MOSI, MISO, SCK, CS (Chip Select), DC (Data/Command),以及 RST (Reset) 引脚之间的适当配对[^1]。 #### 软件环境准备 安装最新版本的 MicroPython 固件至 ESP32-S3 设备,并确认设备能够正常运行基础命令。对于 LVGL 的集成,则需要下载并导入 lv_micropython 库文件夹中的必要组件。 #### 初始化显示模块 利用 MicroPython 提供的功能初始化屏幕参数: ```python from machine import Pin,SPI,PWM import st7789py as st7789 # 假设已存在此库用于简化说明 spi = SPI(1, baudrate=40000000, sck=Pin(6), mosi=Pin(7)) tft=st7789.ST7789(spi, width=240,height=240, reset=Pin(14), dc=Pin(15), cs=Pin(16), backlight=Pin(17)) ``` 上述代码片段展示了如何创建一个 SPI 对象并与特定引脚关联起来;接着实例化了一个 `ST7789` 类的对象来进行具体的显示器控制操作。 #### 设置 LVGL 图形界面 为了使能图形绘制功能,在启动时加载 LVGL 并注册触摸回调函数(如果适用)。下面是一个简单的例子展示怎样开始使用 LVGL 创建窗口和按钮等控件: ```python import lvgl as lv lv.init() disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) # Registering the display driver to LVGL and linking it with TFT object. disp_drv.buffer = tft.buf disp_drv.flush_cb = tft.flush lv.disp_drv_register(disp_drv) scr = lv.obj() # Create a new screen object. btn = lv.btn(scr) # Add button on this screen. label = lv.label(btn) label.set_text("Hello") lv.scr_load(scr) # Load the newly created screen. ``` 这段程序首先初始化了 LVGL 库本身,随后定义了一个新的显示驱动器结构体变量 disp_drv ,并通过调用相应的方法将其与之前建立好的 tft 实例相联系。最后一步是在屏幕上添加了一些基本 UI 组件作为演示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永远的元子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值