micropython驱动ST7789v 2.4寸液晶显示中文

2023-10-17 17:50

本文主要是介绍micropython驱动ST7789v 2.4寸液晶显示中文,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、ST7789v介绍

 ST7789v是小尺寸液晶中常用的驱动芯片,作者手里的是网上买的一块2.4寸液晶模组,接口

 为SPI接口。

网上能找到这个芯片的micropython驱动,这不是本文的重点。

本文的重点是如何利用这个驱动,并使用字库的方法来显示汉字。

我曾经有一篇文章,介绍如何使用unicode字模库在屏幕上显示汉字,如果你对这个方法还不是很了解,可以看一下我之前这篇文章。使用micropython(ESP8266、ESP32)驱动SES 2.66寸墨水屏显示中文_esp8266驱动墨水屏_f4t0x的博客-CSDN博客

二、st7789v原驱动

这个驱动可以在网上找到,我把源码贴下来。

"""
Copyright (c) 2020, 2021 Russ HughesThis file incorporates work covered by the following copyright and
permission notice and is licensed under the same terms:The MIT License (MIT)Copyright (c) 2019 Ivan BelokobylskiyPermission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.The driver is based on devbis' st7789py_mpy module from
https://github.com/devbis/st7789py_mpy.This driver adds support for:- 320x240, 240x240 and 135x240 pixel displays
- Display rotation
- Hardware based scrolling
- Drawing text using 8 and 16 bit wide bitmap fonts with heights that aremultiples of 8.  Included are 12 bitmap fonts derived from classic pcBIOS text mode fonts.
- Drawing text using converted TrueType fonts.
- Drawing converted bitmaps"""import time
from micropython import const
import ustruct as struct# commands
ST7789_NOP = const(0x00)
ST7789_SWRESET = const(0x01)
ST7789_RDDID = const(0x04)
ST7789_RDDST = const(0x09)ST7789_SLPIN = const(0x10)
ST7789_SLPOUT = const(0x11)
ST7789_PTLON = const(0x12)
ST7789_NORON = const(0x13)ST7789_INVOFF = const(0x20)
ST7789_INVON = const(0x21)
ST7789_DISPOFF = const(0x28)
ST7789_DISPON = const(0x29)
ST7789_CASET = const(0x2A)
ST7789_RASET = const(0x2B)
ST7789_RAMWR = const(0x2C)
ST7789_RAMRD = const(0x2E)ST7789_PTLAR = const(0x30)
ST7789_VSCRDEF = const(0x33)
ST7789_COLMOD = const(0x3A)
ST7789_MADCTL = const(0x36)
ST7789_VSCSAD = const(0x37)ST7789_MADCTL_MY = const(0x80)
ST7789_MADCTL_MX = const(0x40)
ST7789_MADCTL_MV = const(0x20)
ST7789_MADCTL_ML = const(0x10)
ST7789_MADCTL_BGR = const(0x08)
ST7789_MADCTL_MH = const(0x04)
ST7789_MADCTL_RGB = const(0x00)ST7789_RDID1 = const(0xDA)
ST7789_RDID2 = const(0xDB)
ST7789_RDID3 = const(0xDC)
ST7789_RDID4 = const(0xDD)COLOR_MODE_65K = const(0x50)
COLOR_MODE_262K = const(0x60)
COLOR_MODE_12BIT = const(0x03)
COLOR_MODE_16BIT = const(0x05)
COLOR_MODE_18BIT = const(0x06)
COLOR_MODE_16M = const(0x07)# Color definitions
BLACK = const(0x0000)
BLUE = const(0x001F)
RED = const(0xF800)
GREEN = const(0x07E0)
CYAN = const(0x07FF)
MAGENTA = const(0xF81F)
YELLOW = const(0xFFE0)
WHITE = const(0xFFFF)_ENCODE_PIXEL = ">H"
_ENCODE_POS = ">HH"
_DECODE_PIXEL = ">BBB"_BUFFER_SIZE = const(256)_BIT7 = const(0x80)
_BIT6 = const(0x40)
_BIT5 = const(0x20)
_BIT4 = const(0x10)
_BIT3 = const(0x08)
_BIT2 = const(0x04)
_BIT1 = const(0x02)
_BIT0 = const(0x01)# Rotation tables (width, height, xstart, ystart)[rotation % 4]WIDTH_320 = [(240, 320,  0,  0),(320, 240,  0,  0),(240, 320,  0,  0),(320, 240,  0,  0)]WIDTH_240 = [(240, 240,  0,  0),(240, 240,  0,  0),(240, 240,  0, 80),(240, 240, 80,  0)]WIDTH_135 = [(135, 240, 52, 40),(240, 135, 40, 53),(135, 240, 53, 40),(240, 135, 40, 52)]# MADCTL ROTATIONS[rotation % 4]
ROTATIONS = [0x00, 0x60, 0xc0, 0xa0]def color565(red, green=0, blue=0):"""Convert red, green and blue values (0-255) into a 16-bit 565 encoding."""try:red, green, blue = red  # see if the first var is a tuple/listexcept TypeError:passreturn (red & 0xf8) << 8 | (green & 0xfc) << 3 | blue >> 3def _encode_pos(x, y):"""Encode a postion into bytes."""return struct.pack(_ENCODE_POS, x, y)def _encode_pixel(color):"""Encode a pixel color into bytes."""return struct.pack(_ENCODE_PIXEL, color)class ST7789():"""ST7789 driver classArgs:spi (spi): spi object **Required**width (int): display width **Required**height (int): display height **Required**reset (pin): reset pindc (pin): dc pin **Required**cs (pin): cs pinbacklight(pin): backlight pinrotation (int): display rotation- 0-Portrait- 1-Landscape- 2-Inverted Portrait- 3-Inverted Landscape"""def __init__(self, spi, width, height, reset=None, dc=None,cs=None, backlight=None, rotation=0):"""Initialize display."""if height != 240 or width not in [320, 240, 135]:raise ValueError("Unsupported display. 320x240, 240x240 and 135x240 are supported.")if dc is None:raise ValueError("dc pin is required.")self._display_width = self.width = widthself._display_height = self.height = heightself.xstart = 0self.ystart = 0self.spi = spiself.reset = resetself.dc = dcself.cs = csself.backlight = backlightself._rotation = rotation % 4#self.hard_reset()#self.soft_reset()self.sleep_mode(False)self._set_color_mode(COLOR_MODE_65K | COLOR_MODE_16BIT)time.sleep_ms(50)self.rotation(self._rotation)self.inversion_mode(True)time.sleep_ms(10)self._write(ST7789_NORON)time.sleep_ms(10)if backlight is not None:backlight.value(1)self.fill(0)self._write(ST7789_DISPON)time.sleep_ms(500)def _write(self, command=None, data=None):"""SPI write to the device: commands and data."""if self.cs:self.cs.off()if command is not None:self.dc.off()self.spi.write(bytes([command]))if data is not None:self.dc.on()self.spi.write(data)if self.cs:self.cs.on()def hard_reset(self):"""Hard reset display."""if self.cs:self.cs.off()if self.reset:self.reset.on()time.sleep_ms(50)if self.reset:self.reset.off()time.sleep_ms(50)if self.reset:self.reset.on()time.sleep_ms(150)if self.cs:self.cs.on()def soft_reset(self):"""Soft reset display."""self._write(ST7789_SWRESET)time.sleep_ms(150)def sleep_mode(self, value):"""Enable or disable display sleep mode.Args:value (bool): if True enable sleep mode. if False disable sleepmode"""if value:self._write(ST7789_SLPIN)else:self._write(ST7789_SLPOUT)def inversion_mode(self, value):"""Enable or disable display inversion mode.Args:value (bool): if True enable inversion mode. if False disableinversion mode"""if value:self._write(ST7789_INVON)else:self._write(ST7789_INVOFF)def _set_color_mode(self, mode):"""Set display color mode.Args:mode (int): color modeCOLOR_MODE_65K, COLOR_MODE_262K, COLOR_MODE_12BIT,COLOR_MODE_16BIT, COLOR_MODE_18BIT, COLOR_MODE_16M"""self._write(ST7789_COLMOD, bytes([mode & 0x77]))def rotation(self, rotation):"""Set display rotation.Args:rotation (int):- 0-Portrait- 1-Landscape- 2-Inverted Portrait- 3-Inverted Landscape"""rotation %= 4self._rotation = rotationmadctl = ROTATIONS[rotation]if self._display_width == 320:table = WIDTH_320elif self._display_width == 240:table = WIDTH_240elif self._display_width == 135:table = WIDTH_135else:raise ValueError("Unsupported display. 320x240, 240x240 and 135x240 are supported.")self.width, self.height, self.xstart, self.ystart = table[rotation]self._write(ST7789_MADCTL, bytes([madctl]))def _set_columns(self, start, end):"""Send CASET (column address set) command to display.Args:start (int): column start addressend (int): column end address"""if start <= end <= self.width:self._write(ST7789_CASET, _encode_pos(start+self.xstart, end + self.xstart))def _set_rows(self, start, end):"""Send RASET (row address set) command to display.Args:start (int): row start addressend (int): row end address"""if start <= end <= self.height:self._write(ST7789_RASET, _encode_pos(start+self.ystart, end+self.ystart))def _set_window(self, x0, y0, x1, y1):"""Set window to column and row address.Args:x0 (int): column start addressy0 (int): row start addressx1 (int): column end addressy1 (int): row end address"""self._set_columns(x0, x1)self._set_rows(y0, y1)self._write(ST7789_RAMWR)def vline(self, x, y, length, color):"""Draw vertical line at the given location and color.Args:x (int): x coordinateY (int): y coordinatelength (int): length of linecolor (int): 565 encoded color"""self.fill_rect(x, y, 1, length, color)def hline(self, x, y, length, color):"""Draw horizontal line at the given location and color.Args:x (int): x coordinateY (int): y coordinatelength (int): length of linecolor (int): 565 encoded color"""self.fill_rect(x, y, length, 1, color)def pixel(self, x, y, color):"""Draw a pixel at the given location and color.Args:x (int): x coordinateY (int): y coordinatecolor (int): 565 encoded color"""self._set_window(x, y, x, y)self._write(None, _encode_pixel(color))def blit_buffer(self, buffer, x, y, width, height):"""Copy buffer to display at the given location.Args:buffer (bytes): Data to copy to displayx (int): Top left corner x coordinateY (int): Top left corner y coordinatewidth (int): Widthheight (int): Height"""self._set_window(x, y, x + width - 1, y + height - 1)self._write(None, buffer)def rect(self, x, y, w, h, color):"""Draw a rectangle at the given location, size and color.Args:x (int): Top left corner x coordinatey (int): Top left corner y coordinatewidth (int): Width in pixelsheight (int): Height in pixelscolor (int): 565 encoded color"""self.hline(x, y, w, color)self.vline(x, y, h, color)self.vline(x + w - 1, y, h, color)self.hline(x, y + h - 1, w, color)def fill_rect(self, x, y, width, height, color):"""Draw a rectangle at the given location, size and filled with color.Args:x (int): Top left corner x coordinatey (int): Top left corner y coordinatewidth (int): Width in pixelsheight (int): Height in pixelscolor (int): 565 encoded color"""self._set_window(x, y, x + width - 1, y + height - 1)chunks, rest = divmod(width * height, _BUFFER_SIZE)pixel = _encode_pixel(color)self.dc.on()if chunks:data = pixel * _BUFFER_SIZEfor _ in range(chunks):self._write(None, data)if rest:self._write(None, pixel * rest)def fill(self, color):"""Fill the entire FrameBuffer with the specified color.Args:color (int): 565 encoded color"""self.fill_rect(0, 0, self.width, self.height, color)def line(self, x0, y0, x1, y1, color):"""Draw a single pixel wide line starting at x0, y0 and ending at x1, y1.Args:x0 (int): Start point x coordinatey0 (int): Start point y coordinatex1 (int): End point x coordinatey1 (int): End point y coordinatecolor (int): 565 encoded color"""steep = abs(y1 - y0) > abs(x1 - x0)if steep:x0, y0 = y0, x0x1, y1 = y1, x1if x0 > x1:x0, x1 = x1, x0y0, y1 = y1, y0dx = x1 - x0dy = abs(y1 - y0)err = dx // 2ystep = 1 if y0 < y1 else -1while x0 <= x1:if steep:self.pixel(y0, x0, color)else:self.pixel(x0, y0, color)err -= dyif err < 0:y0 += ysteperr += dxx0 += 1def vscrdef(self, tfa, vsa, bfa):"""Set Vertical Scrolling Definition.To scroll a 135x240 display these values should be 40, 240, 40.There are 40 lines above the display that are not shown followed by240 lines that are shown followed by 40 more lines that are not shown.You could write to these areas off display and scroll them into view bychanging the TFA, VSA and BFA values.Args:tfa (int): Top Fixed Areavsa (int): Vertical Scrolling Areabfa (int): Bottom Fixed Area"""struct.pack(">HHH", tfa, vsa, bfa)self._write(ST7789_VSCRDEF, struct.pack(">HHH", tfa, vsa, bfa))def vscsad(self, vssa):"""Set Vertical Scroll Start Address of RAM.Defines which line in the Frame Memory will be written as the firstline after the last line of the Top Fixed Area on the displayExample:for line in range(40, 280, 1):tft.vscsad(line)utime.sleep(0.01)Args:vssa (int): Vertical Scrolling Start Address"""self._write(ST7789_VSCSAD, struct.pack(">H", vssa))def _text8(self, font, text, x0, y0, color=WHITE, background=BLACK):"""Internal method to write characters with width of 8 andheights of 8 or 16.Args:font (module): font module to usetext (str): text to writex0 (int): column to start drawing aty0 (int): row to start drawing atcolor (int): 565 encoded color to use for charactersbackground (int): 565 encoded color to use for background"""for char in text:ch = ord(char)if (font.FIRST <= ch < font.LASTand x0+font.WIDTH <= self.widthand y0+font.HEIGHT <= self.height):if font.HEIGHT == 8:passes = 1size = 8each = 0else:passes = 2size = 16each = 8for line in range(passes):idx = (ch-font.FIRST)*size+(each*line)buffer = struct.pack('>64H',color if font.FONT[idx] & _BIT7 else background,color if font.FONT[idx] & _BIT6 else background,color if font.FONT[idx] & _BIT5 else background,color if font.FONT[idx] & _BIT4 else background,color if font.FONT[idx] & _BIT3 else background,color if font.FONT[idx] & _BIT2 else background,color if font.FONT[idx] & _BIT1 else background,color if font.FONT[idx] & _BIT0 else background,color if font.FONT[idx+1] & _BIT7 else background,color if font.FONT[idx+1] & _BIT6 else background,color if font.FONT[idx+1] & _BIT5 else background,color if font.FONT[idx+1] & _BIT4 else background,color if font.FONT[idx+1] & _BIT3 else background,color if font.FONT[idx+1] & _BIT2 else background,color if font.FONT[idx+1] & _BIT1 else background,color if font.FONT[idx+1] & _BIT0 else background,color if font.FONT[idx+2] & _BIT7 else background,color if font.FONT[idx+2] & _BIT6 else background,color if font.FONT[idx+2] & _BIT5 else background,color if font.FONT[idx+2] & _BIT4 else background,color if font.FONT[idx+2] & _BIT3 else background,color if font.FONT[idx+2] & _BIT2 else background,color if font.FONT[idx+2] & _BIT1 else background,color if font.FONT[idx+2] & _BIT0 else background,color if font.FONT[idx+3] & _BIT7 else background,color if font.FONT[idx+3] & _BIT6 else background,color if font.FONT[idx+3] & _BIT5 else background,color if font.FONT[idx+3] & _BIT4 else background,color if font.FONT[idx+3] & _BIT3 else background,color if font.FONT[idx+3] & _BIT2 else background,color if font.FONT[idx+3] & _BIT1 else background,color if font.FONT[idx+3] & _BIT0 else background,color if font.FONT[idx+4] & _BIT7 else background,color if font.FONT[idx+4] & _BIT6 else background,color if font.FONT[idx+4] & _BIT5 else background,color if font.FONT[idx+4] & _BIT4 else background,color if font.FONT[idx+4] & _BIT3 else background,color if font.FONT[idx+4] & _BIT2 else background,color if font.FONT[idx+4] & _BIT1 else background,color if font.FONT[idx+4] & _BIT0 else background,color if font.FONT[idx+5] & _BIT7 else background,color if font.FONT[idx+5] & _BIT6 else background,color if font.FONT[idx+5] & _BIT5 else background,color if font.FONT[idx+5] & _BIT4 else background,color if font.FONT[idx+5] & _BIT3 else background,color if font.FONT[idx+5] & _BIT2 else background,color if font.FONT[idx+5] & _BIT1 else background,color if font.FONT[idx+5] & _BIT0 else background,color if font.FONT[idx+6] & _BIT7 else background,color if font.FONT[idx+6] & _BIT6 else background,color if font.FONT[idx+6] & _BIT5 else background,color if font.FONT[idx+6] & _BIT4 else background,color if font.FONT[idx+6] & _BIT3 else background,color if font.FONT[idx+6] & _BIT2 else background,color if font.FONT[idx+6] & _BIT1 else background,color if font.FONT[idx+6] & _BIT0 else background,color if font.FONT[idx+7] & _BIT7 else background,color if font.FONT[idx+7] & _BIT6 else background,color if font.FONT[idx+7] & _BIT5 else background,color if font.FONT[idx+7] & _BIT4 else background,color if font.FONT[idx+7] & _BIT3 else background,color if font.FONT[idx+7] & _BIT2 else background,color if font.FONT[idx+7] & _BIT1 else background,color if font.FONT[idx+7] & _BIT0 else background)self.blit_buffer(buffer, x0, y0+8*line, 8, 8)x0 += 8def _text16(self, font, text, x0, y0, color=WHITE, background=BLACK):"""Internal method to draw characters with width of 16 and heights of 16or 32.Args:font (module): font module to usetext (str): text to writex0 (int): column to start drawing aty0 (int): row to start drawing atcolor (int): 565 encoded color to use for charactersbackground (int): 565 encoded color to use for background"""for char in text:ch = ord(char)if (font.FIRST <= ch < font.LASTand x0+font.WIDTH <= self.widthand y0+font.HEIGHT <= self.height):each = 16if font.HEIGHT == 16:passes = 2size = 32else:passes = 4size = 64for line in range(passes):idx = (ch-font.FIRST)*size+(each*line)buffer = struct.pack('>128H',color if font.FONT[idx] & _BIT7 else background,color if font.FONT[idx] & _BIT6 else background,color if font.FONT[idx] & _BIT5 else background,color if font.FONT[idx] & _BIT4 else background,color if font.FONT[idx] & _BIT3 else background,color if font.FONT[idx] & _BIT2 else background,color if font.FONT[idx] & _BIT1 else background,color if font.FONT[idx] & _BIT0 else background,color if font.FONT[idx+1] & _BIT7 else background,color if font.FONT[idx+1] & _BIT6 else background,color if font.FONT[idx+1] & _BIT5 else background,color if font.FONT[idx+1] & _BIT4 else background,color if font.FONT[idx+1] & _BIT3 else background,color if font.FONT[idx+1] & _BIT2 else background,color if font.FONT[idx+1] & _BIT1 else background,color if font.FONT[idx+1] & _BIT0 else background,color if font.FONT[idx+2] & _BIT7 else background,color if font.FONT[idx+2] & _BIT6 else background,color if font.FONT[idx+2] & _BIT5 else background,color if font.FONT[idx+2] & _BIT4 else background,color if font.FONT[idx+2] & _BIT3 else background,color if font.FONT[idx+2] & _BIT2 else background,color if font.FONT[idx+2] & _BIT1 else background,color if font.FONT[idx+2] & _BIT0 else background,color if font.FONT[idx+3] & _BIT7 else background,color if font.FONT[idx+3] & _BIT6 else background,color if font.FONT[idx+3] & _BIT5 else background,color if font.FONT[idx+3] & _BIT4 else background,color if font.FONT[idx+3] & _BIT3 else background,color if font.FONT[idx+3] & _BIT2 else background,color if font.FONT[idx+3] & _BIT1 else background,color if font.FONT[idx+3] & _BIT0 else background,color if font.FONT[idx+4] & _BIT7 else background,color if font.FONT[idx+4] & _BIT6 else background,color if font.FONT[idx+4] & _BIT5 else background,color if font.FONT[idx+4] & _BIT4 else background,color if font.FONT[idx+4] & _BIT3 else background,color if font.FONT[idx+4] & _BIT2 else background,color if font.FONT[idx+4] & _BIT1 else background,color if font.FONT[idx+4] & _BIT0 else background,color if font.FONT[idx+5] & _BIT7 else background,color if font.FONT[idx+5] & _BIT6 else background,color if font.FONT[idx+5] & _BIT5 else background,color if font.FONT[idx+5] & _BIT4 else background,color if font.FONT[idx+5] & _BIT3 else background,color if font.FONT[idx+5] & _BIT2 else background,color if font.FONT[idx+5] & _BIT1 else background,color if font.FONT[idx+5] & _BIT0 else background,color if font.FONT[idx+6] & _BIT7 else background,color if font.FONT[idx+6] & _BIT6 else background,color if font.FONT[idx+6] & _BIT5 else background,color if font.FONT[idx+6] & _BIT4 else background,color if font.FONT[idx+6] & _BIT3 else background,color if font.FONT[idx+6] & _BIT2 else background,color if font.FONT[idx+6] & _BIT1 else background,color if font.FONT[idx+6] & _BIT0 else background,color if font.FONT[idx+7] & _BIT7 else background,color if font.FONT[idx+7] & _BIT6 else background,color if font.FONT[idx+7] & _BIT5 else background,color if font.FONT[idx+7] & _BIT4 else background,color if font.FONT[idx+7] & _BIT3 else background,color if font.FONT[idx+7] & _BIT2 else background,color if font.FONT[idx+7] & _BIT1 else background,color if font.FONT[idx+7] & _BIT0 else background,color if font.FONT[idx+8] & _BIT7 else background,color if font.FONT[idx+8] & _BIT6 else background,color if font.FONT[idx+8] & _BIT5 else background,color if font.FONT[idx+8] & _BIT4 else background,color if font.FONT[idx+8] & _BIT3 else background,color if font.FONT[idx+8] & _BIT2 else background,color if font.FONT[idx+8] & _BIT1 else background,color if font.FONT[idx+8] & _BIT0 else background,color if font.FONT[idx+9] & _BIT7 else background,color if font.FONT[idx+9] & _BIT6 else background,color if font.FONT[idx+9] & _BIT5 else background,color if font.FONT[idx+9] & _BIT4 else background,color if font.FONT[idx+9] & _BIT3 else background,color if font.FONT[idx+9] & _BIT2 else background,color if font.FONT[idx+9] & _BIT1 else background,color if font.FONT[idx+9] & _BIT0 else background,color if font.FONT[idx+10] & _BIT7 else background,color if font.FONT[idx+10] & _BIT6 else background,color if font.FONT[idx+10] & _BIT5 else background,color if font.FONT[idx+10] & _BIT4 else background,color if font.FONT[idx+10] & _BIT3 else background,color if font.FONT[idx+10] & _BIT2 else background,color if font.FONT[idx+10] & _BIT1 else background,color if font.FONT[idx+10] & _BIT0 else background,color if font.FONT[idx+11] & _BIT7 else background,color if font.FONT[idx+11] & _BIT6 else background,color if font.FONT[idx+11] & _BIT5 else background,color if font.FONT[idx+11] & _BIT4 else background,color if font.FONT[idx+11] & _BIT3 else background,color if font.FONT[idx+11] & _BIT2 else background,color if font.FONT[idx+11] & _BIT1 else background,color if font.FONT[idx+11] & _BIT0 else background,color if font.FONT[idx+12] & _BIT7 else background,color if font.FONT[idx+12] & _BIT6 else background,color if font.FONT[idx+12] & _BIT5 else background,color if font.FONT[idx+12] & _BIT4 else background,color if font.FONT[idx+12] & _BIT3 else background,color if font.FONT[idx+12] & _BIT2 else background,color if font.FONT[idx+12] & _BIT1 else background,color if font.FONT[idx+12] & _BIT0 else background,color if font.FONT[idx+13] & _BIT7 else background,color if font.FONT[idx+13] & _BIT6 else background,color if font.FONT[idx+13] & _BIT5 else background,color if font.FONT[idx+13] & _BIT4 else background,color if font.FONT[idx+13] & _BIT3 else background,color if font.FONT[idx+13] & _BIT2 else background,color if font.FONT[idx+13] & _BIT1 else background,color if font.FONT[idx+13] & _BIT0 else background,color if font.FONT[idx+14] & _BIT7 else background,color if font.FONT[idx+14] & _BIT6 else background,color if font.FONT[idx+14] & _BIT5 else background,color if font.FONT[idx+14] & _BIT4 else background,color if font.FONT[idx+14] & _BIT3 else background,color if font.FONT[idx+14] & _BIT2 else background,color if font.FONT[idx+14] & _BIT1 else background,color if font.FONT[idx+14] & _BIT0 else background,color if font.FONT[idx+15] & _BIT7 else background,color if font.FONT[idx+15] & _BIT6 else background,color if font.FONT[idx+15] & _BIT5 else background,color if font.FONT[idx+15] & _BIT4 else background,color if font.FONT[idx+15] & _BIT3 else background,color if font.FONT[idx+15] & _BIT2 else background,color if font.FONT[idx+15] & _BIT1 else background,color if font.FONT[idx+15] & _BIT0 else background)self.blit_buffer(buffer, x0, y0+8*line, 16, 8)x0 += font.WIDTHdef text(self, font, text, x0, y0, color=WHITE, background=BLACK):"""Draw text on display in specified font and colors. 8 and 16 bit widefonts are supported.Args:font (module): font module to use.text (str): text to writex0 (int): column to start drawing aty0 (int): row to start drawing atcolor (int): 565 encoded color to use for charactersbackground (int): 565 encoded color to use for background"""if font.WIDTH == 8:self._text8(font, text, x0, y0, color, background)else:self._text16(font, text, x0, y0, color, background)def bitmap(self, bitmap, x, y, index=0):"""Draw a bitmap on display at the specified column and rowArgs:bitmap (bitmap_module): The module containing the bitmap to drawx (int): column to start drawing aty (int): row to start drawing atindex (int): Optional index of bitmap to draw from multiple bitmapmodule"""bitmap_size = bitmap.HEIGHT * bitmap.WIDTHbuffer_len = bitmap_size * 2buffer = bytearray(buffer_len)bs_bit = bitmap.BPP * bitmap_size * index if index > 0 else 0for i in range(0, buffer_len, 2):color_index = 0for _ in range(bitmap.BPP):color_index <<= 1color_index |= (bitmap.BITMAP[bs_bit // 8]& 1 << (7 - (bs_bit % 8))) > 0bs_bit += 1color = bitmap.PALETTE[color_index]buffer[i] = color & 0xff00 >> 8buffer[i + 1] = color_index & 0xffto_col = x + bitmap.WIDTH - 1to_row = y + bitmap.HEIGHT - 1if self.width > to_col and self.height > to_row:self._set_window(x, y, to_col, to_row)self._write(None, buffer)# @micropython.nativedef write(self, font, string, x, y, fg=WHITE, bg=BLACK):"""Write a string using a converted true-type font on the display startingat the specified column and rowArgs:font (font): The module containing the converted true-type fonts (string): The string to writex (int): column to start writingy (int): row to start writingfg (int): foreground color, optional, defaults to WHITEbg (int): background color, optional, defaults to BLACK"""buffer_len = font.HEIGHT * font.MAX_WIDTH * 2buffer = bytearray(buffer_len)fg_hi = (fg & 0xff00) >> 8fg_lo = fg & 0xffbg_hi = (bg & 0xff00) >> 8bg_lo = bg & 0xfffor character in string:try:char_index = font.MAP.index(character)offset = char_index * font.OFFSET_WIDTHbs_bit = font.OFFSETS[offset]if font.OFFSET_WIDTH > 1:bs_bit = (bs_bit << 8) + font.OFFSETS[offset + 1]if font.OFFSET_WIDTH > 2:bs_bit = (bs_bit << 8) + font.OFFSETS[offset + 2]char_width = font.WIDTHS[char_index]buffer_needed = char_width * font.HEIGHT * 2for i in range(0, buffer_needed, 2):if font.BITMAPS[bs_bit // 8] & 1 << (7 - (bs_bit % 8)) > 0:buffer[i] = fg_hibuffer[i + 1] = fg_loelse:buffer[i] = bg_hibuffer[i + 1] = bg_lobs_bit += 1to_col = x + char_width - 1to_row = y + font.HEIGHT - 1if self.width > to_col and self.height > to_row:self._set_window(x, y, to_col, to_row)self._write(None, buffer[:buffer_needed])x += char_widthexcept ValueError:passdef write_width(self, font, string):"""Returns the width in pixels of the string if it was written with thespecified fontArgs:font (font): The module containing the converted true-type fontstring (string): The string to measure"""width = 0for character in string:try:char_index = font.MAP.index(character)width += font.WIDTHS[char_index]except ValueError:passreturn width

其中,st7789.text()方法就是显示ASCII字符了,你可能也发现了,遗憾的是,这个驱动只支持8*8和16*16的字符,并且不支持中文。

下面我们在这个驱动下面增加中文字符显示功能。

三、中文显示

如我之前那篇文章所述,显示中文得有字模库,取到字模库中要显示得汉字字模后,采用blit的方法显示出来。

我们注意到,前面那个驱动里,也正好有blit这个方法。

1.取字模库

依然采用前述那篇文章中的软件,提取unicode字模库。

要注意的是,为了编程方便,我们把unicode从0x0000-0xFFFF全部取出来,我用的SD卡存储字模库,所以没那么在乎存储空间的问题,如果你在意的话,只取中文部分0x4E00开始也没问题,只需在取到中文unicode码之后减掉0x4E00再去fileseek()即可。

这个是取模软件截图。

 取好字模库后,保存到flash或SD卡备用。

2.处理字模库

关于这一步,其实开始我也是不知道的,因为取模直接显示出来的中文字符出现了问题:

字符左右半边各自镜像于正常字符。比如下边这个“辉”字,中间为界,左半边和右半边各自左右翻转了。

 显示成了:

 不难看出,是取模方式的问题。横向取模是对的,但是每个字节高低位是反的。图中的字节H和L是反的,但是取模软件横向取模只有这一种方式,没有其他方式可选,那就只能自己处理下字模文件了。

 

 所以就有了下面这个小程序(随手写的,有些逻辑问题,不影响结果):

取模完成后,用程序把字模文件的每个字节高低顺序对调。
f=open('e:/fonts-unicode(0000-00FF)-w16-h32-b24.dzk','rb')
f1=open('e:/fonts-unicode(0000-00FF)-w16-h32-b24-inv8.dzk','wb')
buff=f.read(1)
a=buff[0]
cnt=0
writeBuff=bytearray(1)while buff is not None:b=0x00#print("a=",a)for i in range(8):  b=(b&0xfe) | (0x01 & a)if i<7:b=b<<1a=a>>1#print("b=",b)writeBuff[0]=bf1.write(writeBuff)cnt+=1#print("cnt=",cnt)try:buff=f.read(1)a=buff[0]except:break
print("cnt=",cnt)
f1.flush()
f.close()
f1.close()print("done")

 处理完成后的字模库文件终于可以用了。

3.显示中文

经过一番准备,终于可以干正事了。

ST7789v液晶屏幕上,一个像素点需要使用2个字节来表示该点的颜色,即RGB565,毕竟是彩色屏幕嘛。

 我们在字模库中取出的字模,实际是黑白像素字模,一个位对应一个像素点。这就需要我们做一个转换。字模库中取出一个位,我们判断是1的话,就用文字颜色(RGB565的2个字节)填充;如果是0的话,就用背景色填充。

原理清楚了,就可以直接上代码了。

注意程序中对中文字符和ASCII字符做了区别处理。这是因为在同等高度,比如都是high=32的情况下,ASCII字符不需要占用到32,只需要16就可以了,否则ASCII字符就周围空白很多就不好看了。所以中文字符和ASCII字符用了不同的字模库。

这段程序支持16和32两种字符。

encode_get_utf8_size和encode_utf8_to_unicode是用来把中文转为unicode编码的,之前那篇文章提到过。

    def stringCN(self,string, x0, y0, high=32,color=WHITE, background=BLACK):import gcgc.collect()high=highif high==16:fontFileCN=open('/sd/fonts-unicode(0000-FFFF)-w16-h16-b12-inv8.dzk','rb')fontFileEN=open('/sd/fonts-unicode(0000-00FF)-w8-h16-b12-inv8.dzk','rb')widthCN=16widthEN=8elif high==32:fontFileCN=open('/sd/fonts-unicode(0000-FFFF)-w32-h32-b24.dzk','rb')fontFileEN=open('/sd/fonts-unicode(0000-00FF)-w16-h32-b24-inv8.dzk','rb')widthCN=32widthEN=16else:print("unsupported font!")return#输入字符串长度,即字符数,一个中文/英文字符均算作1个i=0#i是string通过string=bytes(string,'utf-8')转换成字节串之后在每个循环中处理的位置scrPos=0#要显示的某个字符在屏幕X轴方向的位置string=bytes(string,'utf-8')#此时string的len已经和输入参数中的len不一样了,因为中文在输入时len为1,转换后len为3while i<len(string):utfbytes=self.encode_get_utf8_size(string[i])#单个字符的所占字节数,一般英文为1,中文为3#print(i,string[i],utfbytes,string[i:i+utfbytes])tmp=self.encode_utf8_to_unicode(string[i:i+utfbytes])#字符转码为unicode编码,0x0000~0xffff,常用中文在0x4e00~0x9fff,英文在0x0000~0x00ff#print(type(tmp),tmp)i+=utfbytesif utfbytes==1:width=widthENfontFile=fontFileENelif utfbytes==3:width=widthCNfontFile=fontFileCNelse:print("utfbytes error,utfbytes=",utfbytes)returnfontFile.seek(tmp*int(high*width/8))zimo=fontFile.read(int(high*width/8))buffer=bytearray(0)for pixByteIndex in range(int(high*width/8)):#print(pixByteIndex)for bitCounter in range(8):#print(bitCounter)#RGB565,一个像素点2字节,如果字模中像素点为0,就填充背景色,为1就填充color色if (zimo[pixByteIndex] & 0x01<<bitCounter):buffer.append(~((color&0xff00)>>8))buffer.append(~(color&0x00ff))else:buffer.append(~((background & 0xff00)>>8))buffer.append(~(background & 0x00ff))self.blit_buffer(buffer, x0+scrPos, y0, width=width, height=high)scrPos+=widthdef encode_get_utf8_size(self,utf):if utf < 0x80:return 1if utf >= 0x80 and utf < 0xC0:return -1if utf >= 0xC0 and utf < 0xE0:return 2if utf >= 0xE0 and utf < 0xF0:return 3if utf >= 0xF0 and utf < 0xF8:return 4if utf >= 0xF8 and utf < 0xFC:return 5if utf >= 0xFC:return 6def encode_utf8_to_unicode(self,utf8):utfbytes = self.encode_get_utf8_size(utf8[0])if utfbytes == 1:unic = utf8[0]if utfbytes == 2:b1 = utf8[0]b2 = utf8[1]if ((b2 & 0xE0) != 0x80):return -1unic = ((((b1 << 6) + (b2 & 0x3F)) & 0xFF) << 8) | (((b1 >> 2) & 0x07) & 0xFF)if utfbytes == 3:b1 = utf8[0]b2 = utf8[1]b3 = utf8[2]if (((b2 & 0xC0) != 0x80) or ((b3 & 0xC0) != 0x80)):return -1unic = ((((b1 << 4) + ((b2 >> 2) & 0x0F)) & 0xFF) << 8) | (((b2 << 6) + (b3 & 0x3F)) & 0xFF)if utfbytes == 4:b1 = utf8[0]b2 = utf8[1]b3 = utf8[2]b4 = utf8[3]if (((b2 & 0xC0) != 0x80) or ((b3 & 0xC0) != 0x80) or ((b4 & 0xC0) != 0x80)):return -1unic = ((((b3 << 6) + (b4 & 0x3F)) & 0xFF) << 16) | ((((b2 << 4) + ((b3 >> 2)& 0x0F)) & 0xFF) << 8) | ((((b1 << 2) & 0x1C) + ((b2 >> 4) & 0x03)) & 0xFF)if utfbytes == 5:b1 = utf8[0]b2 = utf8[1]b3 = utf8[2]b4 = utf8[3]b5 = utf8[4]if (((b2 & 0xC0) != 0x80) or ((b3 & 0xC0) != 0x80) or ((b4 & 0xC0) != 0x80) or ((b5 & 0xC0) != 0x80)):return -1unic = ((((b4 << 6) + (b5 & 0x3F)) & 0xFF) << 24) | (((b3 << 4) + ((b4 >> 2) & 0x0F) & 0xFF) << 16) | ((((b2 << 2) + ((b3 >> 4) & 0x03)) & 0xFF) << 8) | (((b1 << 6)) & 0xFF)if utfbytes == 6:b1 = utf8[0]b2 = utf8[1]b3 = utf8[2]b4 = utf8[3]b5 = utf8[4]b6 = utf8[5]if (((b2 & 0xC0) != 0x80) or ((b3 & 0xC0) != 0x80) or ((b4 & 0xC0) != 0x80) or ((b5 & 0xC0) != 0x80) or ((b6 & 0xC0) != 0x80)):return -1unic = ((((b5 << 6) + (b6 & 0x3F)) << 24) & 0xFF) | (((b5 << 4) + ((b6 >> 2) & 0x0F) << 16) & 0xFF) | ((((b3 << 2) + ((b4 >> 4) & 0x03)) << 8) & 0xFF) | ((((b1 << 6) & 0x40) + (b2 & 0x3F)) & 0xFF)return unic

OK,最终显示效果:

最后说一句,原驱动程序中使用了大量color if font.FONT[idx] & _BITx else background这种语句,个人感觉太笨重了,可以优化成循环语句,不过我也懒得去修改了。

这篇关于micropython驱动ST7789v 2.4寸液晶显示中文的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/227002

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

vscode中文乱码问题,注释,终端,调试乱码一劳永逸版

忘记咋回事突然出现了乱码问题,很多方法都试了,注释乱码解决了,终端又乱码,调试窗口也乱码,最后经过本人不懈努力,终于全部解决了,现在分享给大家我的方法。 乱码的原因是各个地方用的编码格式不统一,所以把他们设成统一的utf8. 1.电脑的编码格式 开始-设置-时间和语言-语言和区域 管理语言设置-更改系统区域设置-勾选Bata版:使用utf8-确定-然后按指示重启 2.vscode

解决Office Word不能切换中文输入

我们在使用WORD的时可能会经常碰到WORD中无法输入中文的情况。因为,虽然我们安装了搜狗输入法,但是到我们在WORD中使用搜狗的输入法的切换中英文的按键的时候会发现根本没有效果,无法将输入法切换成中文的。下面我就介绍一下如何在WORD中把搜狗输入法切换到中文。

sqlite不支持中文排序,采用java排序

方式一 不支持含有重复字段进行排序 /*** sqlite不支持中文排序,改用java排序* 根据指定的对象属性字段,排序对象集合,顺序* @param list* @param field* @return*/public static List sortListByField(List<?> list,String field){List temp = new ArrayList(

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

UMDF驱动安装

VS2013 + WDF8.1,UMDF驱动选择User Mode Driver,不要选User Mode Driver 2.0,否则Win7安装有问题,如图 另外,在驱动安装时不要忘记WUDFUpdate_<主版本号><次版本号>.dll文件,具体文件名在INF中查找。此文件可在WDF的安装目录中找到。注意:在WDF的安装目录中会有3个WUDFUpdate_xxx.dll文件,x86,x6

彻底解决win10系统Tomcat10控制台输出中文乱码

彻底解决Tomcat10控制台输出中文乱码 首先乱码问题的原因通俗的讲就是读的编码格式和写的解码格式不一致,比如最常见的两种中文编码UTF-8和GBK,UTF-8一个汉字占三个字节,GBK一个汉字占两个字节,所以当编码与解码格式不一致时,输出端当然无法识别这是啥,所以只能以乱码代替。 值得一提的是GBK不是国家标准编码,常用的国标有两,一个是GB2312,一个是GB18030 GB1

matplotlib中文乱码问题

在使用Matplotlib进行数据可视化的过程中,经常会遇到中文乱码的问题。显示乱码是由于编码问题导致的,而matplotlib 默认使用ASCII 编码,但是当使用pyplot时,是支持unicode编码的,只是默认字体是英文字体,导致中文无法正常显示,所以显示中文乱码。 文本使用系统默认字体、手动指定字体、使用字体管理器来解决。 一、系统默认字体(全局设置字体) 在Matplotlib中