前言

平台:windows10,thonny,esp32s3wroom1u,1.44寸tft(128*128)st7735s lcd屏幕

接线:BL->3.3v, VCC->3.3v, CS->GPIO42, DC->GPIO41, RES->GPIO40, SDA->GPIO38, SCL->GPIO37

代码

复制即用

更新时间:2025.1.1

from time import sleep_ms,sleep
from ustruct import pack
from machine import SPI,Pin
import framebuf
from framebuf import FrameBuffer
from array import array

class ST7735():
    '''
    :spi: spi对象
    :dc: dc引脚对应的GPIO编号
    :rst: rst引脚对应的GPIO编号
    :cs: cs引脚对应的GPIO编号
    '''
    def __init__(self,spi,dc:int,rst:int,cs:int,bl:int=None):
        self.spi = spi
        self.dc=Pin(dc,Pin.OUT,value=0)
        self.rst=Pin(rst,Pin.OUT,value=1)
        self.cs=Pin(cs,Pin.OUT,value=1)
        if bl is not None:
            self.bl=Pin(bl,Pin.OUT,value=0) # 默认开启背光
        self.framebuf = framebuf.FrameBuffer(bytearray(128*128*2), 128, 128,framebuf.RGB565)
        self.reset()
        self._write(0x11)
        sleep_ms(100)
        buf=bytearray(128)
        for i in range(32):
            buf[i]=i*2
            buf[i+96]=i*2
        for i in range(64):
            buf[i+32]=i
        for command, data in (
            (0x3A, b"\x05"), # 选择16位颜色模式
            (0x36, pack(">B",0x08)), # 显示相对位置(0xc0)
            (0x20, None), #关闭反转
            (0x29, None),#开启显示
            (0x2d, buf),# RGB
            ):
            self._write(command, data)
        self.clear()
        
    def clear(self):
        self.framebuf.fill(0)
        self.show()
    
    def reset(self):
        self._write(0x01)

    def _write(self, command, data=None):
        self.cs.off() # 开启片选信号
        self.dc.off() # 低电平写命令
        self.spi.write(bytearray([command]))
        if data is not None:
            self.cs.on() # 释放片选信号
            self.cs.off() # 开启片选信号
            self.dc.on() # 高电平写参数
            self.spi.write(data)
            self.cs.on() # 释放片选信号

    def show(self):
        self._write(0x2a,pack(">HH", 0,127))
        self._write(0x2b,pack(">HH", 0,127))
        self._write(0x2c,self.framebuf)

    def sleep(self):
        self._write(0x28)
        self._write(0x10)
        if self.bl is not None:
            self.bl.off()
    
    def split_RGB(self,number:int):
        n = f'{number:016b}'
        return int(n[:8],2), int(n[8:],2)

    def encode_RGB(self,number:int):
        n = f'{number:016b}'
        return int(n[8:]+n[:8],2)

    def cn_to_byte(self,s:str):
        d={
            '蓝':bytearray(b'\x04\x04\xe4\x04\x0f\xf4\x04\x04\xf4\x44\xcf\x44\x44\x44\x04\x00\x40\x40\x7d\x44\x44\x7d\x44\x45\x44\x7c\x44\x45\x7c\x40\x40\x00'),
            '牙':bytearray(b'\x00\x00\xc2\xb2\x82\x82\x82\x82\x82\xfe\x82\x82\x82\x82\x80\x00\x00\x20\x20\x10\x08\x04\x02\x41\x80\x7f\x00\x00\x00\x00\x00\x00'),
            '南':bytearray(b'\x04\xe4\x24\x24\x64\xa4\x24\x3f\x24\xa4\x64\x24\x24\xe4\x04\x00\x00\xff\x00\x08\x09\x09\x09\x7f\x09\x09\x09\x48\x80\x7f\x00\x00'),
            '宁':bytearray(b'\x20\x18\x88\x88\x88\x88\x89\x8e\x88\x88\x88\x88\x88\x28\x18\x00\x00\x00\x00\x00\x00\x40\x80\x7f\x00\x00\x00\x00\x00\x00\x00\x00'),
            '广':bytearray(b'\x00\x00\xf8\x08\x08\x08\x08\x09\x0e\x08\x08\x08\x08\x08\x00\x00\x80\x60\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'),
            '州':bytearray(b'\x00\xe0\x00\xff\x00\x20\xc0\x00\xfe\x00\x20\xc0\x00\xff\x00\x00\x81\x40\x30\x0f\x00\x00\x00\x00\x3f\x00\x00\x00\x00\xff\x00\x00'),
            '市':bytearray(b'\x00\x08\x88\x88\x88\x88\x89\xfa\x88\x88\x88\x88\x88\x08\x00\x00\x00\x00\x3f\x00\x00\x00\x00\xff\x00\x00\x10\x20\x1f\x00\x00\x00'),
            '西':bytearray(b'\x02\x02\xe2\x22\x22\xfe\x22\x22\x22\xfe\x22\x22\xe2\x02\x02\x00\x00\x00\xff\x48\x44\x43\x40\x40\x40\x43\x44\x44\xff\x00\x00\x00'),
            '上':bytearray(b'\x00\x00\x00\x00\x00\x00\xff\x40\x40\x40\x40\x40\x40\x00\x00\x00\x40\x40\x40\x40\x40\x40\x7f\x40\x40\x40\x40\x40\x40\x40\x40\x00'),
            '下':bytearray(b'\x02\x02\x02\x02\x02\x02\xfe\x02\x02\x42\x82\x02\x02\x02\x02\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x01\x06\x00\x00\x00'),
            '海':bytearray(b'\x10\x60\x02\x0c\xc0\x10\x08\xf7\x14\x54\x94\x14\xf4\x04\x00\x00\x04\x04\x7c\x03\x00\x01\x1d\x13\x11\x55\x99\x51\x3f\x11\x01\x00'),
            '北':bytearray(b'\x00\x20\x20\x20\x20\xff\x00\x00\x00\xff\x40\x20\x10\x08\x00\x00\x20\x60\x20\x10\x10\xff\x00\x00\x00\x3f\x40\x40\x40\x40\x78\x00'),
            '京':bytearray(b'\x04\x04\x04\xe4\x24\x24\x25\x26\x24\x24\x24\xe4\x04\x04\x04\x00\x00\x40\x20\x1b\x02\x42\x82\x7e\x02\x02\x02\x0b\x10\x60\x00\x00'),
            '湖':bytearray(b'\x10\x60\x02\x8c\x00\x88\x88\xff\x88\x88\x00\xfe\x22\x22\xfe\x00\x04\x04\x7e\x01\x00\x1f\x08\x08\x08\x9f\x60\x1f\x42\x82\x7f\x00'),
            '东':bytearray(b'\x00\x08\x88\x48\x28\x18\x0f\xe8\x08\x08\x08\x08\x08\x08\x00\x00\x00\x20\x11\x09\x05\x41\x81\x7f\x01\x01\x05\x09\x11\x20\x00\x00'),
            '中':bytearray(b'\x00\x00\xf0\x10\x10\x10\x10\xff\x10\x10\x10\x10\xf0\x00\x00\x00\x00\x00\x0f\x04\x04\x04\x04\xff\x04\x04\x04\x04\x0f\x00\x00\x00'),
            '国':bytearray(b'\x00\x00\xf0\x10\x10\x10\x10\xff\x10\x10\x10\x10\xf0\x00\x00\x00\x00\x00\x0f\x04\x04\x04\x04\xff\x04\x04\x04\x04\x0f\x00\x00\x00'),
            '区':bytearray(b'\x00\xfe\x02\x02\x02\x12\x22\x42\x82\x42\x22\x1a\x02\x02\x00\x00\x00\x7f\x40\x40\x48\x44\x42\x41\x40\x41\x42\x4c\x40\x40\x40\x00'),
            '安':bytearray(b'\x80\x90\x8c\x84\x84\x84\xf5\x86\x84\x84\x84\x84\x94\x8c\x80\x00\x00\x80\x80\x84\x46\x49\x28\x10\x10\x2c\x23\x40\x80\x00\x00\x00'),
            '全':bytearray(b'\x80\x80\x40\x20\x50\x48\x44\xc3\x44\x48\x50\x20\x40\x80\x80\x00\x00\x40\x40\x44\x44\x44\x44\x7f\x44\x44\x44\x44\x40\x40\x00\x00'),
            '温':bytearray(b'\x10\x60\x02\x8c\x00\x00\xfe\x92\x92\x92\x92\x92\xfe\x00\x00\x00\x04\x04\x7e\x01\x40\x7e\x42\x42\x7e\x42\x7e\x42\x42\x7e\x40\x00'),
            '度':bytearray(b'\x00\x00\xfc\x24\x24\x24\xfc\x25\x26\x24\xfc\x24\x24\x24\x04\x00\x40\x30\x8f\x80\x84\x4c\x55\x25\x25\x25\x55\x4c\x80\x80\x80\x00'),
            '湿':bytearray(b'\x10\x60\x02\x8c\x00\xfe\x92\x92\x92\x92\x92\x92\xfe\x00\x00\x00\x04\x04\x7e\x01\x44\x48\x50\x7f\x40\x40\x7f\x50\x48\x44\x40\x00'),
            '高':bytearray(b'\x04\x04\x04\x04\xf4\x94\x95\x96\x94\x94\xf4\x04\x04\x04\x04\x00\x00\xfe\x02\x02\x7a\x4a\x4a\x4a\x4a\x4a\x7a\x02\x82\xfe\x00\x00'),
            '低':bytearray(b'\x00\x80\x60\xf8\x07\x00\xfc\x84\x84\x84\xfe\x82\x83\x82\x80\x00\x01\x00\x00\xff\x00\x00\xff\x40\x20\x00\x41\x8e\x30\x40\xf8\x00'),
            '摄':bytearray(b'\x10\x10\x10\xff\x10\x90\x82\xfe\xaa\xaa\xaa\xaa\xfe\x42\x40\x00\x04\x44\x82\x7f\x81\x42\x2a\x12\x6e\x80\x5e\x22\x53\x8e\x80\x00'),
            '氏':bytearray(b'\x00\x00\xfc\x44\x44\x44\x44\x44\xfe\x42\x42\x43\x42\x40\x40\x00\x00\x00\xff\x40\x20\x00\x00\x00\x01\x06\x08\x10\x20\x40\xf8\x00'),
            '山':bytearray(b'\x00\x00\xf0\x00\x00\x00\x00\xff\x00\x00\x00\x00\xf0\x00\x00\x00\x00\x00\x3f\x20\x20\x20\x20\x3f\x20\x20\x20\x20\x7f\x00\x00\x00')
        }
        return d[s]

    def fill(self,c:int):
        '''
        使整个画面变成一种颜色
        :c:RGB565格式的int
        '''
        self.framebuf.fill(self.encode_RGB(c))

    def pixel(self,x:int,y:int,c:int):
        '''
        画点
        x: 横坐标
        y: 纵坐标
        c: BGR565格式的int
        '''
        self.framebuf.pixel(x,y,self.encode_RGB(c))
    
    def hline(self,x:int,y:int,w:int,c:int):
        '''
        画横线
        x: 起始横坐标
        y: 起始纵坐标
        w: 线长
        c: BGR565格式的int
        '''
        self.framebuf.hline(x,y,w,self.encode_RGB(c))

    def vline(self,x:int,y:int,w:int,c:int):
        '''
        画竖线
        x: 起始横坐标
        y: 起始纵坐标
        w: 线长
        c: BGR565格式的int
        '''
        self.framebuf.vline(x,y,w,self.encode_RGB(c))

    def line(self,x1:int,y1:int,x2:int,y2:int,c:int):
        '''
        画直线
        x1: 起始横坐标
        y1: 起始纵坐标
        x2: 终点横坐标
        y2: 终点纵坐标
        c: BGR565格式的int
        '''
        self.framebuf.line(x1,y1,x2,y2,self.encode_RGB(c))
    
    def rect(self,x:int,y:int,w:int,h:int,c:int,f:int=0):
        '''
        画矩形
        x: 矩形左上角横坐标
        y: 矩形左上角纵坐标
        w: 宽
        h: 高
        c: BGR565格式的int
        f: 布尔类型,表示是否填充
        '''
        self.framebuf.rect(x,y,w,h,self.encode_RGB(c),f)

    def ellipse(self,x:int,y:int,xr:int,yr:int,c:int,f:int=0):
        '''
        画椭圆
        x: 椭圆中心横坐标
        y: 椭圆中心纵坐标
        xr: 椭圆横轴半径
        yr: 椭圆纵轴半径
        c: BGR565格式的int
        f: 布尔类型,表示是否填充
    '''
        self.framebuf.ellipse(x,y,xr,yr,self.encode_RGB(c),f)

    def poly(self,x:int,y:int,coords:array,c:int,f=0):
        '''
        画多边形
        x: 基准点横坐标
        y: 基准点纵坐标
        coords: 多边形坐标点,例如array('h',[x0,y0,x1,y1,x2,y2])
        c: BGR565格式的int
        f: 布尔类型,表示是否填充
        '''
        self.framebuf.poly(x,y,coords,self.encode_RGB(c),f)
    
    def scroll(self,x:int,y:int):
        '''
        将画布往某位置移动,但会在源位置留下残影
        x: 目标横坐标
        y: 目标纵坐标
        '''
        self.framebuf.scroll(x,y)

    def p8(self,buf:bytearray,x:int,y:int):
        fbuf=framebuf.FrameBuffer(buf,8,8,framebuf.RGB565)
        self.framebuf.blit(fbuf,x,y)
    def p16(self,buf:bytearray,x:int,y:int):
        fbuf=framebuf.FrameBuffer(buf,16,16,framebuf.RGB565)
        self.framebuf.blit(fbuf,x,y)
    def p32(self,buf:bytearray,x:int,y:int):
        fbuf=framebuf.FrameBuffer(buf,32,32,framebuf.RGB565)
        self.framebuf.blit(fbuf,x,y)
    def p32(self,buf:bytearray,x:int,y:int):
        fbuf=framebuf.FrameBuffer(buf,64,64,framebuf.RGB565)
        self.framebuf.blit(fbuf,x,y)
    def pic(self,buf:bytearray,x:int,y:int,w:int,h:int):
        fbuf=framebuf.FrameBuffer(buf,w,h,framebuf.RGB565)
        self.framebuf.blit(fbuf,x,y)

    def cn_char(self,s:str,x:int,y:int,c:int):
        '''
        绘制中文字符串
        s: 中文字符串
        x: 起始横坐标
        y: 起始纵坐标
        c: RGB565格式的int
        '''
        # 颜色解码
        c1,c2=self.split_RGB(c)
        # 构建调色板
        palette_fb = FrameBuffer(bytearray([0,0,c1,c2]), 2, 1, framebuf.RGB565)
        for i,char in enumerate(s):
            # 构建字符缓冲区
            buf=FrameBuffer(self.cn_to_byte(char),16,16,framebuf.MONO_VLSB)
            # 绘制
            self.framebuf.blit(buf,x+i*16,y,0,palette_fb)

    def en_char(self,s:str,x:int,y:int,c:int):
        '''
        绘制英文字符串
        s: 英文字符串
        x: 起始横坐标
        y: 起始纵坐标
        c: RGB565格式的int
        '''
        self.framebuf.text(s,x,y,self.encode_RGB(c))

    def char(self,s:str,x:int,y:int,c:int):
        '''
        绘制中英文字符串
        s: 字符串
        x: 起始横坐标
        y: 起始纵坐标
        c: RGB565格式的int
        ''' 
        start_position=x
        # 颜色解码
        c1,c2=self.split_RGB(c)
        # 构建调色板
        palette_fb = FrameBuffer(bytearray([0,0,c1,c2]), 2, 1, framebuf.RGB565)
        for char in s:
            if ord(char)<128:
                self.framebuf.text(char,start_position,y+4,self.encode_RGB(c))
                start_position+=8
            else:
                self.framebuf.blit(FrameBuffer(self.cn_to_byte(char),16,16,framebuf.MONO_VLSB),start_position,y,0,palette_fb)
                start_position+=16
                
                


if __name__=='__main__':
    '''
    mpremote run st7735s.py
    '''
    lcd=ST7735(SPI(2, sck=37,mosi=38,baudrate=60000000),41,40,42)
    lcd.poly(10,10,array('h',[0,0,50,20,20,40]),1000)
    lcd.show()

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐