物联网开发115 - Micropython ESP32 C3连接GM12864屏幕ST7576驱动IC芯片_esp32 驱动lcd 12864

50 阅读3分钟

from micropython import const import framebuf import time

SET_BIAS =const(0xA2) POWER_CTRL=const(0x28) SET_BOOST =const(0xF8) SOFT_RST =const(0xE2) SEG_DIR =const(0xA0) COM_DIR =const(0xC0) REGU_RATIO=const(0x20) EVSET_MODE=const(0x81) DISP_ONOFF=const(0xAE) INV_DISP =const(0xA6)#0:normal display 1:inverse ALL_PIX_ON=const(0xA4) SRTLIN_SET=const(0x40)#407F PAGEAD_SET=const(0xB0)#b0b8 COLHAD_SET=const(0x10)#0x100x1F COLLAD_SET=const(0x00)#0x000x0F

class ST7567(framebuf.FrameBuffer): def init(self,spi,dc,cs,rst,elecvolt=0x1F,regratio=0x03,invX=0x00,invY=0x00,invdisp=0x00): dc.init(dc.OUT,value=0) cs.init(cs.OUT,value=1)#disable device port rst.init(rst.OUT,value=0)#reset device self.dc=dc self.cs=cs self.rst=rst self.spi=spi

    self.EV=elecvolt
    self.RR=regratio
    self.invX=0x00 if(invX==0) else 0x01#0x00:MX=0 normal dir, 0x01:MX=1 reverse dir
    self.invY=0x00 if(invY==0) else 0x08#0x00:MY=0 0x08:MY=1
    self.invdisp=0x00 if(invdisp==0) else 0x01
    self.buffer=bytearray(128*64//8)
    super().__init__(self.buffer,128,64,framebuf.MONO_VLSB)

    time.sleep_ms(1)
    self.rst.value(1)
    time.sleep_ms(1)#reset done
    self.initscreen()
    time.sleep_ms(50)
    self.fill(0)
    self.show()
    self.write_cmd(DISP_ONOFF|0x01)#1:display on normal display mode
    
def initscreen(self):
    self.write_cmd(SOFT_RST)#optional, I think it's useless
    self.write_cmd(SET_BOOST)#set booster mode
    self.write_cmd(0x00)#boost: 0x00:x4 0x01:x5
    self.write_cmd(SET_BIAS|0x01)# 0:1/9 1:1/7
    self.write_cmd(EVSET_MODE)#put device into EV setting mode
    self.write_cmd(self.EV)#0x00~0x3F set contrast to 0x1f with last command
    self.write_cmd(REGU_RATIO|self.RR)#0x00~0x07 3.0~6.5
    self.write_cmd(POWER_CTRL|0x07)#7:{booster on,regulator on,follower on}
    self.write_cmd(INV_DISP|self.invdisp)#normal display
    self.write_cmd(ALL_PIX_ON|0x00)#0x00:normal display 0x01:all pixel on
    self.write_cmd(SEG_DIR|self.invX)#0:MX=0 normal dir, 1:MX=1 reverse dir
    self.write_cmd(COM_DIR|self.invY)#0x00:MY=0 0x08:MY=1 (may change to reverse y)
    
def write_cmd(self,cmd):
    self.cs.value(0)#enable device port
    self.dc.value(0)#cmd mode
    self.spi.write(bytearray([cmd]))
    #time.sleep_ms(1)
    self.cs.value(1)#disable device port 

def write_data(self,data):
    self.cs.value(0)#enable device port
    self.dc.value(1)#display data mode
    self.spi.write(data)
    #time.sleep_ms(1)
    self.cs.value(1)#disable device port

def show(self):
    self.write_cmd(DISP_ONOFF|0x00)
    self.write_cmd(SRTLIN_SET|0x00)
    colcnt=0
    pagcnt=0
    while (pagcnt<9):
        self.write_cmd(PAGEAD_SET|pagcnt)
        self.write_cmd(COLHAD_SET|0x00)
        self.write_cmd(COLLAD_SET|0x00)
        if(pagcnt<8):
            self.write_data(self.buffer[(128*pagcnt):(128*pagcnt+128)])
        else:
            while (colcnt<128):
                colcnt+=1
                self.write_data(b"\x00")
        pagcnt+=1
        self.write_cmd(DISP_ONOFF|0x01)
        
def clear(self):
    self.fill(0)
    self.show()
    

**六、字库程序**


ufont.py



version = 3

import time import struct

import framebuf

DEBUG = False

def timeit(f, *args, **kwargs): try: myname = str(f).split(' ')[1] except: myname = "UNKONW"

def new_func(*args, **kwargs):
    if DEBUG:
        try:
            t = time.ticks_us()
            result = f(*args, **kwargs)
            delta = time.ticks_diff(time.ticks_us(), t)
            print('Function {} Time = {:6.3f}ms'.format(myname, delta / 1000))
        except AttributeError:
            t = time.perf_counter_ns()
            result = f(*args, **kwargs)
            delta = time.perf_counter_ns() - t
            print('Function {} Time = {:6.3f}ms'.format(myname, delta / 1000000))
        return result
    else:
        return f(*args, **kwargs)

return new_func

class BMFont: @staticmethod def _list_to_byte(arr): b = 0 for a in arr: b = (b << 1) + a return bytes([b])

@timeit
def _bit_list_to_byte_data(self, bit_list):
    """将点阵转换为字节数据

    Args:
        bit_list:

    Returns:

    """
    byte_data = b''
    for _col in bit_list:
        for i in range(0, len(_col), 8):
            byte_data += self._list_to_byte(_col[i:i + 8])
    return byte_data

@timeit
def __init__(self, font_file):
    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]  # 点阵所占字节

@timeit
def _to_bit_list(self, byte_data, font_size, *, _height=None, _width=None):
    """将字节数据转换为点阵数据

    Args:
        byte_data: 字节数据
        font_size: 字号大小
        _height: 字体原高度
        _width: 字体原宽度

    Returns:

    """
    _height = _height or self.font_size
    _width = _width or self.bitmap_size // self.font_size * 8
    new_bitarray = [[0 for j in range(font_size)] for i in range(font_size)]
    for _col in range(len(new_bitarray)):
        for _row in range(len(new_bitarray[_col])):
            _index = int(_col / (font_size / _height)) * _width + int(_row / (font_size / _width))
            new_bitarray[_col][_row] = byte_data[_index // 8] >> (7 - _index % 8) & 1
    return new_bitarray

@timeit
def _color_render(self, bit_list, color):
    """将二值点阵图像转换为 RGB565 彩色字节图像

    Args:
        bit_list:
        color:
    Returns:

    """
    color_array = b""
    for _col in range(len(bit_list)):
        for _row in range(len(bit_list)):
            color_array += struct.pack("<H", color) if bit_list[_col][_row] else b'\x00\x00'
    return color_array

@timeit
def _get_index(self, word):
    """获取索引

    Args:
        word: 字符

    Returns:

    """
    word_code = ord(word)
    start = 0x10
    end = self.start_bitmap

    while start <= end:
        mid = ((start + end) // 4) * 2
        self.font.seek(mid, 0)
        target_code = struct.unpack(">H", self.font.read(2))[0]
        if word_code == target_code:
            return (mid - 16) >> 1
        elif word_code < target_code:
            end = mid - 2
        else:
            start = mid + 2
    return -1

@timeit
def get_bitmap(self, word):
    """获取点阵图

    Args:
        word: 字符

    Returns:
        bytes 字符点阵
    """
    index = self._get_index(word)
    if index == -1:
        return b'\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x0f\xcf\xf3\xcf\xf3\xff\xf3\xff\xcf\xff?\xff?\xff\xff\xff' \
               b'?\xff?\xff\xff\xff\xff'

    self.font.seek(self.start_bitmap + index * self.bitmap_size, 0)
    return self.font.read(self.bitmap_size)

@timeit
def text(self, display, string, x, y, color=1, *, font_size=None, reverse=False, clear=False, show=False,
         half_char=True, auto_wrap=False, **kwargs):
    """通过显示屏显示文字

    使用此函数显示文字,必须先确认显示对象是否继承与 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 >= 128 and ord(string[char]) < 128 and half_char) or
                              (x + font_size >= 128 and (not half_char or ord(string[char]) > 128))):
                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 > 128 or y > 64:
            continue
        
        byte_data = list(self.get_bitmap(string[char]))

        # 反转
        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)
            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]) < 128 and half_char:
            x += font_size // 2
        else:
            x += font_size

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。 img img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!