73浏览
查看: 73|回复: 0

[讨论] 【Beetle 树莓派RP2350】屏幕显示

[复制链接]
本帖最后由 FuShenxiao 于 2025-5-10 21:21 编辑

本文将介绍基于IIC驱动0.91寸OLED屏幕和基于SPI驱动1.8寸TFT屏幕
OLED屏幕
根据绘制的扩展板原理图,可以看到GP26和GP27分别对应IIC的SDA和SCL引脚
【Beetle 树莓派RP2350】屏幕显示图1

查看0.91寸OLED屏幕发现其驱动芯片为SSD1306,因此编写驱动程序ssd1306.py如下
  1. # MicroPython SSD1306 OLED driver, I2C and SPI interfaces
  2. from micropython import const
  3. import framebuf
  4. # register definitions
  5. SET_CONTRAST = const(0x81)
  6. SET_ENTIRE_ON = const(0xA4)
  7. SET_NORM_INV = const(0xA6)
  8. SET_DISP = const(0xAE)
  9. SET_MEM_ADDR = const(0x20)
  10. SET_COL_ADDR = const(0x21)
  11. SET_PAGE_ADDR = const(0x22)
  12. SET_DISP_START_LINE = const(0x40)
  13. SET_SEG_REMAP = const(0xA0)
  14. SET_MUX_RATIO = const(0xA8)
  15. SET_COM_OUT_DIR = const(0xC0)
  16. SET_DISP_OFFSET = const(0xD3)
  17. SET_COM_PIN_CFG = const(0xDA)
  18. SET_DISP_CLK_DIV = const(0xD5)
  19. SET_PRECHARGE = const(0xD9)
  20. SET_VCOM_DESEL = const(0xDB)
  21. SET_CHARGE_PUMP = const(0x8D)
  22. # Subclassing FrameBuffer provides support for graphics primitives
  23. # http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
  24. class SSD1306(framebuf.FrameBuffer):
  25.     def __init__(self, width, height, external_vcc):
  26.         self.width = width
  27.         self.height = height
  28.         self.external_vcc = external_vcc
  29.         self.pages = self.height // 8
  30.         self.buffer = bytearray(self.pages * self.width)
  31.         super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
  32.         self.init_display()
  33.     def init_display(self):
  34.         for cmd in (
  35.             SET_DISP | 0x00,  # off
  36.             # address setting
  37.             SET_MEM_ADDR,
  38.             0x00,  # horizontal
  39.             # resolution and layout
  40.             SET_DISP_START_LINE | 0x00,
  41.             SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0
  42.             SET_MUX_RATIO,
  43.             self.height - 1,
  44.             SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0
  45.             SET_DISP_OFFSET,
  46.             0x00,
  47.             SET_COM_PIN_CFG,
  48.             0x02 if self.width > 2 * self.height else 0x12,
  49.             # timing and driving scheme
  50.             SET_DISP_CLK_DIV,
  51.             0x80,
  52.             SET_PRECHARGE,
  53.             0x22 if self.external_vcc else 0xF1,
  54.             SET_VCOM_DESEL,
  55.             0x30,  # 0.83*Vcc
  56.             # display
  57.             SET_CONTRAST,
  58.             0xFF,  # maximum
  59.             SET_ENTIRE_ON,  # output follows RAM contents
  60.             SET_NORM_INV,  # not inverted
  61.             # charge pump
  62.             SET_CHARGE_PUMP,
  63.             0x10 if self.external_vcc else 0x14,
  64.             SET_DISP | 0x01,
  65.         ):  # on
  66.             self.write_cmd(cmd)
  67.         self.fill(0)
  68.         self.show()
  69.     def poweroff(self):
  70.         self.write_cmd(SET_DISP | 0x00)
  71.     def poweron(self):
  72.         self.write_cmd(SET_DISP | 0x01)
  73.     def contrast(self, contrast):
  74.         self.write_cmd(SET_CONTRAST)
  75.         self.write_cmd(contrast)
  76.     def invert(self, invert):
  77.         self.write_cmd(SET_NORM_INV | (invert & 1))
  78.     def show(self):
  79.         x0 = 0
  80.         x1 = self.width - 1
  81.         if self.width == 64:
  82.             # displays with width of 64 pixels are shifted by 32
  83.             x0 += 32
  84.             x1 += 32
  85.         self.write_cmd(SET_COL_ADDR)
  86.         self.write_cmd(x0)
  87.         self.write_cmd(x1)
  88.         self.write_cmd(SET_PAGE_ADDR)
  89.         self.write_cmd(0)
  90.         self.write_cmd(self.pages - 1)
  91.         self.write_data(self.buffer)
  92. class SSD1306_I2C(SSD1306):
  93.     def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
  94.         self.i2c = i2c
  95.         self.addr = addr
  96.         self.temp = bytearray(2)
  97.         self.write_list = [b"\x40", None]  # Co=0, D/C#=1
  98.         super().__init__(width, height, external_vcc)
  99.     def write_cmd(self, cmd):
  100.         self.temp[0] = 0x80  # Co=1, D/C#=0
  101.         self.temp[1] = cmd
  102.         self.i2c.writeto(self.addr, self.temp)
  103.     def write_data(self, buf):
  104.         self.write_list[1] = buf
  105.         self.i2c.writevto(self.addr, self.write_list)
  106. class SSD1306_SPI(SSD1306):
  107.     def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
  108.         self.rate = 10 * 1024 * 1024
  109.         dc.init(dc.OUT, value=0)
  110.         res.init(res.OUT, value=0)
  111.         cs.init(cs.OUT, value=1)
  112.         self.spi = spi
  113.         self.dc = dc
  114.         self.res = res
  115.         self.cs = cs
  116.         import time
  117.         self.res(1)
  118.         time.sleep_ms(1)
  119.         self.res(0)
  120.         time.sleep_ms(10)
  121.         self.res(1)
  122.         super().__init__(width, height, external_vcc)
  123.     def write_cmd(self, cmd):
  124.         self.spi.init(baudrate=self.rate, polarity=0, phase=0)
  125.         self.cs(1)
  126.         self.dc(0)
  127.         self.cs(0)
  128.         self.spi.write(bytearray([cmd]))
  129.         self.cs(1)
  130.     def write_data(self, buf):
  131.         self.spi.init(baudrate=self.rate, polarity=0, phase=0)
  132.         self.cs(1)
  133.         self.dc(1)
  134.         self.cs(0)
  135.         self.spi.write(buf)
  136.         self.cs(1)
复制代码

查看数据手册发现SDA和SCL两个引脚属于I2C1
【Beetle 树莓派RP2350】屏幕显示图3

编写显示主程序如下
在主程序中,我完成的显示内容包括:I2C初始化 -> OLED屏幕初始化 -> 显示文本 -> 显示图形 -> 滚动显示文本
  1. from machine import Pin, I2C
  2. import ssd1306
  3. import time
  4. # I2C初始化
  5. i2c = I2C(1, scl=Pin(27), sda=Pin(26), freq=400000)
  6. # OLED初始化 (根据你的屏幕尺寸调整)
  7. # 对于128x32屏幕:
  8. oled = ssd1306.SSD1306_I2C(128, 32, i2c)
  9. # 对于128x64屏幕:
  10. # oled = ssd1306.SSD1306_I2C(128, 64, i2c)
  11. # 清除屏幕
  12. oled.fill(0)
  13. oled.show()
  14. # 显示文本
  15. oled.text("Hello RP2350!", 0, 0)
  16. oled.text("MicroPython", 0, 10)
  17. oled.text("OLED Test", 0, 20)
  18. oled.show()
  19. # 显示图形
  20. def draw_square():
  21.     for y in range(20, 30):
  22.         for x in range(80, 100):
  23.             oled.pixel(x, y, 1)
  24.     oled.show()
  25. draw_square()
  26. time.sleep(5)
  27. # 滚动文本示例
  28. for i in range(0, 128):
  29.     oled.fill(0)
  30.     oled.text("Scrolling text", 128-i, 10)
  31.     oled.show()
  32.     time.sleep(0.02)
复制代码

显示效果如下
【Beetle 树莓派RP2350】屏幕显示图4

【Beetle 树莓派RP2350】屏幕显示图5

工程文件如下
TFT屏幕
根据绘制的扩展板原理图,可以看到GP19和GP18分别对应SPI的SDA和SCL引脚,GP16为CS引脚,GP26为DC引脚,GP27为RES引脚,BL引脚默认接高电平,即背光打开
【Beetle 树莓派RP2350】屏幕显示图6

屏幕的驱动芯片为ST7735,编写驱动程序ST7735.py如下
  1. #driver for Sainsmart 1.8" TFT display ST7735
  2. #Translated by Guy Carver from the ST7735 sample code.
  3. #Modirfied for micropython-esp32 by boochow
  4. import machine
  5. import time
  6. from math import sqrt
  7. #TFTRotations and TFTRGB are bits to set
  8. # on MADCTL to control display rotation/color layout
  9. #Looking at display with pins on top.
  10. #00 = upper left printing right
  11. #10 = does nothing (MADCTL_ML)
  12. #20 = upper left printing down (backwards) (Vertical flip)
  13. #40 = upper right printing left (backwards) (X Flip)
  14. #80 = lower left printing right (backwards) (Y Flip)
  15. #04 = (MADCTL_MH)
  16. #60 = 90 right rotation
  17. #C0 = 180 right rotation
  18. #A0 = 270 right rotation
  19. TFTRotations = [0x00, 0x60, 0xC0, 0xA0]
  20. TFTBGR = 0x08 #When set color is bgr else rgb.
  21. TFTRGB = 0x00
  22. #@micropython.native
  23. def clamp( aValue, aMin, aMax ) :
  24.   return max(aMin, min(aMax, aValue))
  25. #@micropython.native
  26. def TFTColor( aR, aG, aB ) :
  27.   '''Create a 16 bit rgb value from the given R,G,B from 0-255.
  28.      This assumes rgb 565 layout and will be incorrect for bgr.'''
  29.   return ((aR & 0xF8) << 8) | ((aG & 0xFC) << 3) | (aB >> 3)
  30. ScreenSize = (128, 160)
  31. class TFT(object) :
  32.   """Sainsmart TFT 7735 display driver."""
  33.   NOP = 0x0
  34.   SWRESET = 0x01
  35.   RDDID = 0x04
  36.   RDDST = 0x09
  37.   SLPIN  = 0x10
  38.   SLPOUT  = 0x11
  39.   PTLON  = 0x12
  40.   NORON  = 0x13
  41.   INVOFF = 0x20
  42.   INVON = 0x21
  43.   DISPOFF = 0x28
  44.   DISPON = 0x29
  45.   CASET = 0x2A
  46.   RASET = 0x2B
  47.   RAMWR = 0x2C
  48.   RAMRD = 0x2E
  49.   VSCRDEF = 0x33
  50.   VSCSAD = 0x37
  51.   COLMOD = 0x3A
  52.   MADCTL = 0x36
  53.   FRMCTR1 = 0xB1
  54.   FRMCTR2 = 0xB2
  55.   FRMCTR3 = 0xB3
  56.   INVCTR = 0xB4
  57.   DISSET5 = 0xB6
  58.   PWCTR1 = 0xC0
  59.   PWCTR2 = 0xC1
  60.   PWCTR3 = 0xC2
  61.   PWCTR4 = 0xC3
  62.   PWCTR5 = 0xC4
  63.   VMCTR1 = 0xC5
  64.   RDID1 = 0xDA
  65.   RDID2 = 0xDB
  66.   RDID3 = 0xDC
  67.   RDID4 = 0xDD
  68.   PWCTR6 = 0xFC
  69.   GMCTRP1 = 0xE0
  70.   GMCTRN1 = 0xE1
  71.   BLACK = 0
  72.   RED = TFTColor(0xFF, 0x00, 0x00)
  73.   MAROON = TFTColor(0x80, 0x00, 0x00)
  74.   GREEN = TFTColor(0x00, 0xFF, 0x00)
  75.   FOREST = TFTColor(0x00, 0x80, 0x80)
  76.   BLUE = TFTColor(0x00, 0x00, 0xFF)
  77.   NAVY = TFTColor(0x00, 0x00, 0x80)
  78.   CYAN = TFTColor(0x00, 0xFF, 0xFF)
  79.   YELLOW = TFTColor(0xFF, 0xFF, 0x00)
  80.   PURPLE = TFTColor(0xFF, 0x00, 0xFF)
  81.   WHITE = TFTColor(0xFF, 0xFF, 0xFF)
  82.   GRAY = TFTColor(0x80, 0x80, 0x80)
  83.   @staticmethod
  84.   def color( aR, aG, aB ) :
  85.     '''Create a 565 rgb TFTColor value'''
  86.     return TFTColor(aR, aG, aB)
  87.   def __init__( self, spi, aDC, aReset, aCS ) :
  88.     """aLoc SPI pin location is either 1 for 'X' or 2 for 'Y'.
  89.        aDC is the DC pin and aReset is the reset pin."""
  90.     self._size = ScreenSize
  91.     self._offset = bytearray([0,0])
  92.     self.rotate = 0                    #Vertical with top toward pins.
  93.     self._rgb = True                   #color order of rgb.
  94.     self.tfa = 0                       #top fixed area
  95.     self.bfa = 0                       #bottom fixed area
  96.     self.dc  = machine.Pin(aDC, machine.Pin.OUT, machine.Pin.PULL_DOWN)
  97.     self.reset = machine.Pin(aReset, machine.Pin.OUT, machine.Pin.PULL_DOWN)
  98.     self.cs = machine.Pin(aCS, machine.Pin.OUT, machine.Pin.PULL_DOWN)
  99.     self.cs(1)
  100.     self.spi = spi
  101.     self.colorData = bytearray(2)
  102.     self.windowLocData = bytearray(4)
  103.   def size( self, newSize = ScreenSize ) :
  104.     if (newSize != ScreenSize):
  105.         self._size = newSize
  106.     return self._size
  107. #   @micropython.native
  108.   def on( self, aTF = True ) :
  109.     '''Turn display on or off.'''
  110.     self._writecommand(TFT.DISPON if aTF else TFT.DISPOFF)
  111. #   @micropython.native
  112.   def invertcolor( self, aBool ) :
  113.     '''Invert the color data IE: Black = White.'''
  114.     self._writecommand(TFT.INVON if aBool else TFT.INVOFF)
  115. #   @micropython.native
  116.   def rgb( self, aTF = True ) :
  117.     '''True = rgb else bgr'''
  118.     self._rgb = aTF
  119.     self._setMADCTL()
  120. #   @micropython.native
  121.   def rotation( self, aRot ) :
  122.     '''0 - 3. Starts vertical with top toward pins and rotates 90 deg
  123.        clockwise each step.'''
  124.     if (0 <= aRot < 4):
  125.       rotchange = self.rotate ^ aRot
  126.       self.rotate = aRot
  127.       #If switching from vertical to horizontal swap x,y
  128.       # (indicated by bit 0 changing).
  129.       if (rotchange & 1):
  130.         self._size =(self._size[1], self._size[0])
  131.       self._setMADCTL()
  132. #  @micropython.native
  133.   def pixel( self, aPos, aColor ) :
  134.     '''Draw a pixel at the given position'''
  135.     if 0 <= aPos[0] < self._size[0] and 0 <= aPos[1] < self._size[1]:
  136.       self._setwindowpoint(aPos)
  137.       self._pushcolor(aColor)
  138. #   @micropython.native
  139.   def text( self, aPos, aString, aColor, aFont, aSize = 1, nowrap = False ) :
  140.     '''Draw a text at the given position.  If the string reaches the end of the
  141.        display it is wrapped to aPos[0] on the next line.  aSize may be an integer
  142.        which will size the font uniformly on w,h or a or any type that may be
  143.        indexed with [0] or [1].'''
  144.     if aFont == None:
  145.       return
  146.     #Make a size either from single value or 2 elements.
  147.     if (type(aSize) == int) or (type(aSize) == float):
  148.       wh = (aSize, aSize)
  149.     else:
  150.       wh = aSize
  151.     px, py = aPos
  152.     width = wh[0] * aFont["Width"] + 1
  153.     for c in aString:
  154.       self.char((px, py), c, aColor, aFont, wh)
  155.       px += width
  156.       #We check > rather than >= to let the right (blank) edge of the
  157.       # character print off the right of the screen.
  158.       if px + width > self._size[0]:
  159.         if nowrap:
  160.           break
  161.         else:
  162.           py += aFont["Height"] * wh[1] + 1
  163.           px = aPos[0]
  164. #   @micropython.native
  165.   def char( self, aPos, aChar, aColor, aFont, aSizes ) :
  166.     '''Draw a character at the given position using the given font and color.
  167.        aSizes is a tuple with x, y as integer scales indicating the
  168.        # of pixels to draw for each pixel in the character.'''
  169.     if aFont == None:
  170.       return
  171.     startchar = aFont['Start']
  172.     endchar = aFont['End']
  173.     ci = ord(aChar)
  174.     if (startchar <= ci <= endchar):
  175.       fontw = aFont['Width']
  176.       fonth = aFont['Height']
  177.       ci = (ci - startchar) * fontw
  178.       charA = aFont["Data"][ci:ci + fontw]
  179.       px = aPos[0]
  180.       if aSizes[0] <= 1 and aSizes[1] <= 1 :
  181.         buf = bytearray(2 * fonth * fontw)
  182.         for q in range(fontw) :
  183.           c = charA[q]
  184.           for r in range(fonth) :
  185.             if c & 0x01 :
  186.               pos = 2 * (r * fontw + q)
  187.               buf[pos] = aColor >> 8
  188.               buf[pos + 1] = aColor & 0xff
  189.             c >>= 1
  190.         self.image(aPos[0], aPos[1], aPos[0] + fontw - 1, aPos[1] + fonth - 1, buf)
  191.       else:
  192.         for c in charA :
  193.           py = aPos[1]
  194.           for r in range(fonth) :
  195.             if c & 0x01 :
  196.               self.fillrect((px, py), aSizes, aColor)
  197.             py += aSizes[1]
  198.             c >>= 1
  199.           px += aSizes[0]
  200. #   @micropython.native
  201.   def line( self, aStart, aEnd, aColor ) :
  202.     '''Draws a line from aStart to aEnd in the given color.  Vertical or horizontal
  203.        lines are forwarded to vline and hline.'''
  204.     if aStart[0] == aEnd[0]:
  205.       #Make sure we use the smallest y.
  206.       pnt = aEnd if (aEnd[1] < aStart[1]) else aStart
  207.       self.vline(pnt, abs(aEnd[1] - aStart[1]) + 1, aColor)
  208.     elif aStart[1] == aEnd[1]:
  209.       #Make sure we use the smallest x.
  210.       pnt = aEnd if aEnd[0] < aStart[0] else aStart
  211.       self.hline(pnt, abs(aEnd[0] - aStart[0]) + 1, aColor)
  212.     else:
  213.       px, py = aStart
  214.       ex, ey = aEnd
  215.       dx = ex - px
  216.       dy = ey - py
  217.       inx = 1 if dx > 0 else -1
  218.       iny = 1 if dy > 0 else -1
  219.       dx = abs(dx)
  220.       dy = abs(dy)
  221.       if (dx >= dy):
  222.         dy <<= 1
  223.         e = dy - dx
  224.         dx <<= 1
  225.         while (px != ex):
  226.           self.pixel((px, py), aColor)
  227.           if (e >= 0):
  228.             py += iny
  229.             e -= dx
  230.           e += dy
  231.           px += inx
  232.       else:
  233.         dx <<= 1
  234.         e = dx - dy
  235.         dy <<= 1
  236.         while (py != ey):
  237.           self.pixel((px, py), aColor)
  238.           if (e >= 0):
  239.             px += inx
  240.             e -= dy
  241.           e += dx
  242.           py += iny
  243. #   @micropython.native
  244.   def vline( self, aStart, aLen, aColor ) :
  245.     '''Draw a vertical line from aStart for aLen. aLen may be negative.'''
  246.     start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1]))
  247.     stop = (start[0], clamp(start[1] + aLen, 0, self._size[1]))
  248.     #Make sure smallest y 1st.
  249.     if (stop[1] < start[1]):
  250.       start, stop = stop, start
  251.     self._setwindowloc(start, stop)
  252.     self._setColor(aColor)
  253.     self._draw(aLen)
  254. #   @micropython.native
  255.   def hline( self, aStart, aLen, aColor ) :
  256.     '''Draw a horizontal line from aStart for aLen. aLen may be negative.'''
  257.     start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1]))
  258.     stop = (clamp(start[0] + aLen, 0, self._size[0]), start[1])
  259.     #Make sure smallest x 1st.
  260.     if (stop[0] < start[0]):
  261.       start, stop = stop, start
  262.     self._setwindowloc(start, stop)
  263.     self._setColor(aColor)
  264.     self._draw(aLen)
  265. #   @micropython.native
  266.   def rect( self, aStart, aSize, aColor ) :
  267.     '''Draw a hollow rectangle.  aStart is the smallest coordinate corner
  268.        and aSize is a tuple indicating width, height.'''
  269.     self.hline(aStart, aSize[0], aColor)
  270.     self.hline((aStart[0], aStart[1] + aSize[1] - 1), aSize[0], aColor)
  271.     self.vline(aStart, aSize[1], aColor)
  272.     self.vline((aStart[0] + aSize[0] - 1, aStart[1]), aSize[1], aColor)
  273. #   @micropython.native
  274.   def fillrect( self, aStart, aSize, aColor ) :
  275.     '''Draw a filled rectangle.  aStart is the smallest coordinate corner
  276.        and aSize is a tuple indicating width, height.'''
  277.     start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1]))
  278.     end = (clamp(start[0] + aSize[0] - 1, 0, self._size[0]), clamp(start[1] + aSize[1] - 1, 0, self._size[1]))
  279.     if (end[0] < start[0]):
  280.       tmp = end[0]
  281.       end = (start[0], end[1])
  282.       start = (tmp, start[1])
  283.     if (end[1] < start[1]):
  284.       tmp = end[1]
  285.       end = (end[0], start[1])
  286.       start = (start[0], tmp)
  287.     self._setwindowloc(start, end)
  288.     numPixels = (end[0] - start[0] + 1) * (end[1] - start[1] + 1)
  289.     self._setColor(aColor)
  290.     self._draw(numPixels)
  291. #   @micropython.native
  292.   def circle( self, aPos, aRadius, aColor ) :
  293.     '''Draw a hollow circle with the given radius and color with aPos as center.'''
  294.     self.colorData[0] = aColor >> 8
  295.     self.colorData[1] = aColor
  296.     xend = int(0.7071 * aRadius) + 1
  297.     rsq = aRadius * aRadius
  298.     for x in range(xend) :
  299.       y = int(sqrt(rsq - x * x))
  300.       xp = aPos[0] + x
  301.       yp = aPos[1] + y
  302.       xn = aPos[0] - x
  303.       yn = aPos[1] - y
  304.       xyp = aPos[0] + y
  305.       yxp = aPos[1] + x
  306.       xyn = aPos[0] - y
  307.       yxn = aPos[1] - x
  308.       self._setwindowpoint((xp, yp))
  309.       self._writedata(self.colorData)
  310.       self._setwindowpoint((xp, yn))
  311.       self._writedata(self.colorData)
  312.       self._setwindowpoint((xn, yp))
  313.       self._writedata(self.colorData)
  314.       self._setwindowpoint((xn, yn))
  315.       self._writedata(self.colorData)
  316.       self._setwindowpoint((xyp, yxp))
  317.       self._writedata(self.colorData)
  318.       self._setwindowpoint((xyp, yxn))
  319.       self._writedata(self.colorData)
  320.       self._setwindowpoint((xyn, yxp))
  321.       self._writedata(self.colorData)
  322.       self._setwindowpoint((xyn, yxn))
  323.       self._writedata(self.colorData)
  324. #   @micropython.native
  325.   def fillcircle( self, aPos, aRadius, aColor ) :
  326.     '''Draw a filled circle with given radius and color with aPos as center'''
  327.     rsq = aRadius * aRadius
  328.     for x in range(aRadius) :
  329.       y = int(sqrt(rsq - x * x))
  330.       y0 = aPos[1] - y
  331.       ey = y0 + y * 2
  332.       y0 = clamp(y0, 0, self._size[1])
  333.       ln = abs(ey - y0) + 1;
  334.       self.vline((aPos[0] + x, y0), ln, aColor)
  335.       self.vline((aPos[0] - x, y0), ln, aColor)
  336.   def fill( self, aColor = BLACK ) :
  337.     '''Fill screen with the given color.'''
  338.     self.fillrect((0, 0), self._size, aColor)
  339.   def image( self, x0, y0, x1, y1, data ) :
  340.     self._setwindowloc((x0, y0), (x1, y1))
  341.     self._writedata(data)
  342.   def setvscroll(self, tfa, bfa) :
  343.     ''' set vertical scroll area '''
  344.     self._writecommand(TFT.VSCRDEF)
  345.     data2 = bytearray([0, tfa])
  346.     self._writedata(data2)
  347.     data2[1] = 162 - tfa - bfa
  348.     self._writedata(data2)
  349.     data2[1] = bfa
  350.     self._writedata(data2)
  351.     self.tfa = tfa
  352.     self.bfa = bfa
  353.   def vscroll(self, value) :
  354.     a = value + self.tfa
  355.     if (a + self.bfa > 162) :
  356.       a = 162 - self.bfa
  357.     self._vscrolladdr(a)
  358.   def _vscrolladdr(self, addr) :
  359.     self._writecommand(TFT.VSCSAD)
  360.     data2 = bytearray([addr >> 8, addr & 0xff])
  361.     self._writedata(data2)
  362. #   @micropython.native
  363.   def _setColor( self, aColor ) :
  364.     self.colorData[0] = aColor >> 8
  365.     self.colorData[1] = aColor
  366.     self.buf = bytes(self.colorData) * 32
  367. #   @micropython.native
  368.   def _draw( self, aPixels ) :
  369.     '''Send given color to the device aPixels times.'''
  370.     self.dc(1)
  371.     self.cs(0)
  372.     for i in range(aPixels//32):
  373.       self.spi.write(self.buf)
  374.     rest = (int(aPixels) % 32)
  375.     if rest > 0:
  376.         buf2 = bytes(self.colorData) * rest
  377.         self.spi.write(buf2)
  378.     self.cs(1)
  379. #   @micropython.native
  380.   def _setwindowpoint( self, aPos ) :
  381.     '''Set a single point for drawing a color to.'''
  382.     x = self._offset[0] + int(aPos[0])
  383.     y = self._offset[1] + int(aPos[1])
  384.     self._writecommand(TFT.CASET)            #Column address set.
  385.     self.windowLocData[0] = self._offset[0]
  386.     self.windowLocData[1] = x
  387.     self.windowLocData[2] = self._offset[0]
  388.     self.windowLocData[3] = x
  389.     self._writedata(self.windowLocData)
  390.     self._writecommand(TFT.RASET)            #Row address set.
  391.     self.windowLocData[0] = self._offset[1]
  392.     self.windowLocData[1] = y
  393.     self.windowLocData[2] = self._offset[1]
  394.     self.windowLocData[3] = y
  395.     self._writedata(self.windowLocData)
  396.     self._writecommand(TFT.RAMWR)            #Write to RAM.
  397. #   @micropython.native
  398.   def _setwindowloc( self, aPos0, aPos1 ) :
  399.     '''Set a rectangular area for drawing a color to.'''
  400.     self._writecommand(TFT.CASET)            #Column address set.
  401.     self.windowLocData[0] = self._offset[0]
  402.     self.windowLocData[1] = self._offset[0] + int(aPos0[0])
  403.     self.windowLocData[2] = self._offset[0]
  404.     self.windowLocData[3] = self._offset[0] + int(aPos1[0])
  405.     self._writedata(self.windowLocData)
  406.     self._writecommand(TFT.RASET)            #Row address set.
  407.     self.windowLocData[0] = self._offset[1]
  408.     self.windowLocData[1] = self._offset[1] + int(aPos0[1])
  409.     self.windowLocData[2] = self._offset[1]
  410.     self.windowLocData[3] = self._offset[1] + int(aPos1[1])
  411.     self._writedata(self.windowLocData)
  412.     self._writecommand(TFT.RAMWR)            #Write to RAM.
  413.   #@micropython.native
  414.   def _writecommand( self, aCommand ) :
  415.     '''Write given command to the device.'''
  416.     self.dc(0)
  417.     self.cs(0)
  418.     self.spi.write(bytearray([aCommand]))
  419.     self.cs(1)
  420.   #@micropython.native
  421.   def _writedata( self, aData ) :
  422.     '''Write given data to the device.  This may be
  423.        either a single int or a bytearray of values.'''
  424.     self.dc(1)
  425.     self.cs(0)
  426.     self.spi.write(aData)
  427.     self.cs(1)
  428.   #@micropython.native
  429.   def _pushcolor( self, aColor ) :
  430.     '''Push given color to the device.'''
  431.     self.colorData[0] = aColor >> 8
  432.     self.colorData[1] = aColor
  433.     self._writedata(self.colorData)
  434.   #@micropython.native
  435.   def _setMADCTL( self ) :
  436.     '''Set screen rotation and RGB/BGR format.'''
  437.     self._writecommand(TFT.MADCTL)
  438.     rgb = TFTRGB if self._rgb else TFTBGR
  439.     self._writedata(bytearray([TFTRotations[self.rotate] | rgb]))
  440.   #@micropython.native
  441.   def _reset( self ) :
  442.     '''Reset the device.'''
  443.     self.dc(0)
  444.     self.reset(1)
  445.     time.sleep_us(500)
  446.     self.reset(0)
  447.     time.sleep_us(500)
  448.     self.reset(1)
  449.     time.sleep_us(500)
  450.   def initb( self ) :
  451.     '''Initialize blue tab version.'''
  452.     self._size = (ScreenSize[0] + 2, ScreenSize[1] + 1)
  453.     self._reset()
  454.     self._writecommand(TFT.SWRESET)              #Software reset.
  455.     time.sleep_us(50)
  456.     self._writecommand(TFT.SLPOUT)               #out of sleep mode.
  457.     time.sleep_us(500)
  458.     data1 = bytearray(1)
  459.     self._writecommand(TFT.COLMOD)               #Set color mode.
  460.     data1[0] = 0x05                             #16 bit color.
  461.     self._writedata(data1)
  462.     time.sleep_us(10)
  463.     data3 = bytearray([0x00, 0x06, 0x03])       #fastest refresh, 6 lines front, 3 lines back.
  464.     self._writecommand(TFT.FRMCTR1)              #Frame rate control.
  465.     self._writedata(data3)
  466.     time.sleep_us(10)
  467.     self._writecommand(TFT.MADCTL)
  468.     data1[0] = 0x08                             #row address/col address, bottom to top refresh
  469.     self._writedata(data1)
  470.     data2 = bytearray(2)
  471.     self._writecommand(TFT.DISSET5)              #Display settings
  472.     data2[0] = 0x15                             #1 clock cycle nonoverlap, 2 cycle gate rise, 3 cycle oscil, equalize
  473.     data2[1] = 0x02                             #fix on VTL
  474.     self._writedata(data2)
  475.     self._writecommand(TFT.INVCTR)               #Display inversion control
  476.     data1[0] = 0x00                             #Line inversion.
  477.     self._writedata(data1)
  478.     self._writecommand(TFT.PWCTR1)               #Power control
  479.     data2[0] = 0x02   #GVDD = 4.7V
  480.     data2[1] = 0x70   #1.0uA
  481.     self._writedata(data2)
  482.     time.sleep_us(10)
  483.     self._writecommand(TFT.PWCTR2)               #Power control
  484.     data1[0] = 0x05                             #VGH = 14.7V, VGL = -7.35V
  485.     self._writedata(data1)
  486.     self._writecommand(TFT.PWCTR3)           #Power control
  487.     data2[0] = 0x01   #Opamp current small
  488.     data2[1] = 0x02   #Boost frequency
  489.     self._writedata(data2)
  490.     self._writecommand(TFT.VMCTR1)               #Power control
  491.     data2[0] = 0x3C   #VCOMH = 4V
  492.     data2[1] = 0x38   #VCOML = -1.1V
  493.     self._writedata(data2)
  494.     time.sleep_us(10)
  495.     self._writecommand(TFT.PWCTR6)               #Power control
  496.     data2[0] = 0x11
  497.     data2[1] = 0x15
  498.     self._writedata(data2)
  499.     #These different values don't seem to make a difference.
  500. #     dataGMCTRP = bytearray([0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f,
  501. #                             0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10])
  502.     dataGMCTRP = bytearray([0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29,
  503.                             0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10])
  504.     self._writecommand(TFT.GMCTRP1)
  505.     self._writedata(dataGMCTRP)
  506. #     dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30,
  507. #                             0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10])
  508.     dataGMCTRN = bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e,
  509.                             0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10])
  510.     self._writecommand(TFT.GMCTRN1)
  511.     self._writedata(dataGMCTRN)
  512.     time.sleep_us(10)
  513.     self._writecommand(TFT.CASET)                #Column address set.
  514.     self.windowLocData[0] = 0x00
  515.     self.windowLocData[1] = 2                   #Start at column 2
  516.     self.windowLocData[2] = 0x00
  517.     self.windowLocData[3] = self._size[0] - 1
  518.     self._writedata(self.windowLocData)
  519.     self._writecommand(TFT.RASET)                #Row address set.
  520.     self.windowLocData[1] = 1                   #Start at row 2.
  521.     self.windowLocData[3] = self._size[1] - 1
  522.     self._writedata(self.windowLocData)
  523.     self._writecommand(TFT.NORON)                #Normal display on.
  524.     time.sleep_us(10)
  525.     self._writecommand(TFT.RAMWR)
  526.     time.sleep_us(500)
  527.     self._writecommand(TFT.DISPON)
  528.     self.cs(1)
  529.     time.sleep_us(500)
  530.   def initr( self ) :
  531.     '''Initialize a red tab version.'''
  532.     self._reset()
  533.     self._writecommand(TFT.SWRESET)              #Software reset.
  534.     time.sleep_us(150)
  535.     self._writecommand(TFT.SLPOUT)               #out of sleep mode.
  536.     time.sleep_us(500)
  537.     data3 = bytearray([0x01, 0x2C, 0x2D])       #fastest refresh, 6 lines front, 3 lines back.
  538.     self._writecommand(TFT.FRMCTR1)              #Frame rate control.
  539.     self._writedata(data3)
  540.     self._writecommand(TFT.FRMCTR2)              #Frame rate control.
  541.     self._writedata(data3)
  542.     data6 = bytearray([0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d])
  543.     self._writecommand(TFT.FRMCTR3)              #Frame rate control.
  544.     self._writedata(data6)
  545.     time.sleep_us(10)
  546.     data1 = bytearray(1)
  547.     self._writecommand(TFT.INVCTR)               #Display inversion control
  548.     data1[0] = 0x07                             #Line inversion.
  549.     self._writedata(data1)
  550.     self._writecommand(TFT.PWCTR1)               #Power control
  551.     data3[0] = 0xA2
  552.     data3[1] = 0x02
  553.     data3[2] = 0x84
  554.     self._writedata(data3)
  555.     self._writecommand(TFT.PWCTR2)               #Power control
  556.     data1[0] = 0xC5   #VGH = 14.7V, VGL = -7.35V
  557.     self._writedata(data1)
  558.     data2 = bytearray(2)
  559.     self._writecommand(TFT.PWCTR3)               #Power control
  560.     data2[0] = 0x0A   #Opamp current small
  561.     data2[1] = 0x00   #Boost frequency
  562.     self._writedata(data2)
  563.     self._writecommand(TFT.PWCTR4)               #Power control
  564.     data2[0] = 0x8A   #Opamp current small
  565.     data2[1] = 0x2A   #Boost frequency
  566.     self._writedata(data2)
  567.     self._writecommand(TFT.PWCTR5)               #Power control
  568.     data2[0] = 0x8A   #Opamp current small
  569.     data2[1] = 0xEE   #Boost frequency
  570.     self._writedata(data2)
  571.     self._writecommand(TFT.VMCTR1)               #Power control
  572.     data1[0] = 0x0E
  573.     self._writedata(data1)
  574.     self._writecommand(TFT.INVOFF)
  575.     self._writecommand(TFT.MADCTL)               #Power control
  576.     data1[0] = 0xC8
  577.     self._writedata(data1)
  578.     self._writecommand(TFT.COLMOD)
  579.     data1[0] = 0x05
  580.     self._writedata(data1)
  581.     self._writecommand(TFT.CASET)                #Column address set.
  582.     self.windowLocData[0] = 0x00
  583.     self.windowLocData[1] = 0x00
  584.     self.windowLocData[2] = 0x00
  585.     self.windowLocData[3] = self._size[0] - 1
  586.     self._writedata(self.windowLocData)
  587.     self._writecommand(TFT.RASET)                #Row address set.
  588.     self.windowLocData[3] = self._size[1] - 1
  589.     self._writedata(self.windowLocData)
  590.     dataGMCTRP = bytearray([0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f,
  591.                             0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10])
  592.     self._writecommand(TFT.GMCTRP1)
  593.     self._writedata(dataGMCTRP)
  594.     dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30,
  595.                             0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10])
  596.     self._writecommand(TFT.GMCTRN1)
  597.     self._writedata(dataGMCTRN)
  598.     time.sleep_us(10)
  599.     self._writecommand(TFT.DISPON)
  600.     time.sleep_us(100)
  601.     self._writecommand(TFT.NORON)                #Normal display on.
  602.     time.sleep_us(10)
  603.     self.cs(1)
  604.   def initb2( self ) :
  605.     '''Initialize another blue tab version.'''
  606.     self._size = (ScreenSize[0] + 2, ScreenSize[1] + 1)
  607.     self._offset[0] = 2
  608.     self._offset[1] = 1
  609.     self._reset()
  610.     self._writecommand(TFT.SWRESET)              #Software reset.
  611.     time.sleep_us(50)
  612.     self._writecommand(TFT.SLPOUT)               #out of sleep mode.
  613.     time.sleep_us(500)
  614.     data3 = bytearray([0x01, 0x2C, 0x2D])        #
  615.     self._writecommand(TFT.FRMCTR1)              #Frame rate control.
  616.     self._writedata(data3)
  617.     time.sleep_us(10)
  618.     self._writecommand(TFT.FRMCTR2)              #Frame rate control.
  619.     self._writedata(data3)
  620.     time.sleep_us(10)
  621.     self._writecommand(TFT.FRMCTR3)              #Frame rate control.
  622.     self._writedata(data3)
  623.     time.sleep_us(10)
  624.     self._writecommand(TFT.INVCTR)               #Display inversion control
  625.     data1 = bytearray(1)                         #
  626.     data1[0] = 0x07
  627.     self._writedata(data1)
  628.     self._writecommand(TFT.PWCTR1)               #Power control
  629.     data3[0] = 0xA2   #
  630.     data3[1] = 0x02   #
  631.     data3[2] = 0x84   #
  632.     self._writedata(data3)
  633.     time.sleep_us(10)
  634.     self._writecommand(TFT.PWCTR2)               #Power control
  635.     data1[0] = 0xC5                              #
  636.     self._writedata(data1)
  637.     self._writecommand(TFT.PWCTR3)           #Power control
  638.     data2 = bytearray(2)
  639.     data2[0] = 0x0A   #
  640.     data2[1] = 0x00   #
  641.     self._writedata(data2)
  642.     self._writecommand(TFT.PWCTR4)           #Power control
  643.     data2[0] = 0x8A   #
  644.     data2[1] = 0x2A   #
  645.     self._writedata(data2)
  646.     self._writecommand(TFT.PWCTR5)           #Power control
  647.     data2[0] = 0x8A   #
  648.     data2[1] = 0xEE   #
  649.     self._writedata(data2)
  650.     self._writecommand(TFT.VMCTR1)               #Power control
  651.     data1[0] = 0x0E   #
  652.     self._writedata(data1)
  653.     time.sleep_us(10)
  654.     self._writecommand(TFT.MADCTL)
  655.     data1[0] = 0xC8                             #row address/col address, bottom to top refresh
  656.     self._writedata(data1)
  657. #These different values don't seem to make a difference.
  658. #     dataGMCTRP = bytearray([0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f,
  659. #                             0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10])
  660.     dataGMCTRP = bytearray([0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29,
  661.                             0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10])
  662.     self._writecommand(TFT.GMCTRP1)
  663.     self._writedata(dataGMCTRP)
  664. #     dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30,
  665. #                             0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10])
  666.     dataGMCTRN = bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e,
  667.                             0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10])
  668.     self._writecommand(TFT.GMCTRN1)
  669.     self._writedata(dataGMCTRN)
  670.     time.sleep_us(10)
  671.     self._writecommand(TFT.CASET)                #Column address set.
  672.     self.windowLocData[0] = 0x00
  673.     self.windowLocData[1] = 0x02                   #Start at column 2
  674.     self.windowLocData[2] = 0x00
  675.     self.windowLocData[3] = self._size[0] - 1
  676.     self._writedata(self.windowLocData)
  677.     self._writecommand(TFT.RASET)                #Row address set.
  678.     self.windowLocData[1] = 0x01                   #Start at row 2.
  679.     self.windowLocData[3] = self._size[1] - 1
  680.     self._writedata(self.windowLocData)
  681.     data1 = bytearray(1)
  682.     self._writecommand(TFT.COLMOD)               #Set color mode.
  683.     data1[0] = 0x05                             #16 bit color.
  684.     self._writedata(data1)
  685.     time.sleep_us(10)
  686.     self._writecommand(TFT.NORON)                #Normal display on.
  687.     time.sleep_us(10)
  688.     self._writecommand(TFT.RAMWR)
  689.     time.sleep_us(500)
  690.     self._writecommand(TFT.DISPON)
  691.     self.cs(1)
  692.     time.sleep_us(500)
  693.   #@micropython.native
  694.   def initg( self ) :
  695.     '''Initialize a green tab version.'''
  696.     self._reset()
  697.     self._writecommand(TFT.SWRESET)              #Software reset.
  698.     time.sleep_us(150)
  699.     self._writecommand(TFT.SLPOUT)               #out of sleep mode.
  700.     time.sleep_us(255)
  701.     data3 = bytearray([0x01, 0x2C, 0x2D])       #fastest refresh, 6 lines front, 3 lines back.
  702.     self._writecommand(TFT.FRMCTR1)              #Frame rate control.
  703.     self._writedata(data3)
  704.     self._writecommand(TFT.FRMCTR2)              #Frame rate control.
  705.     self._writedata(data3)
  706.     data6 = bytearray([0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d])
  707.     self._writecommand(TFT.FRMCTR3)              #Frame rate control.
  708.     self._writedata(data6)
  709.     time.sleep_us(10)
  710.     self._writecommand(TFT.INVCTR)               #Display inversion control
  711.     self._writedata(bytearray([0x07]))
  712.     self._writecommand(TFT.PWCTR1)               #Power control
  713.     data3[0] = 0xA2
  714.     data3[1] = 0x02
  715.     data3[2] = 0x84
  716.     self._writedata(data3)
  717.     self._writecommand(TFT.PWCTR2)               #Power control
  718.     self._writedata(bytearray([0xC5]))
  719.     data2 = bytearray(2)
  720.     self._writecommand(TFT.PWCTR3)               #Power control
  721.     data2[0] = 0x0A   #Opamp current small
  722.     data2[1] = 0x00   #Boost frequency
  723.     self._writedata(data2)
  724.     self._writecommand(TFT.PWCTR4)               #Power control
  725.     data2[0] = 0x8A   #Opamp current small
  726.     data2[1] = 0x2A   #Boost frequency
  727.     self._writedata(data2)
  728.     self._writecommand(TFT.PWCTR5)               #Power control
  729.     data2[0] = 0x8A   #Opamp current small
  730.     data2[1] = 0xEE   #Boost frequency
  731.     self._writedata(data2)
  732.     self._writecommand(TFT.VMCTR1)               #Power control
  733.     self._writedata(bytearray([0x0E]))
  734.     self._writecommand(TFT.INVOFF)
  735.     self._setMADCTL()
  736.     self._writecommand(TFT.COLMOD)
  737.     self._writedata(bytearray([0x05]))
  738.     self._writecommand(TFT.CASET)                #Column address set.
  739.     self.windowLocData[0] = 0x00
  740.     self.windowLocData[1] = 0x01                #Start at row/column 1.
  741.     self.windowLocData[2] = 0x00
  742.     self.windowLocData[3] = self._size[0] - 1
  743.     self._writedata(self.windowLocData)
  744.     self._writecommand(TFT.RASET)                #Row address set.
  745.     self.windowLocData[3] = self._size[1] - 1
  746.     self._writedata(self.windowLocData)
  747.     dataGMCTRP = bytearray([0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29,
  748.                             0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10])
  749.     self._writecommand(TFT.GMCTRP1)
  750.     self._writedata(dataGMCTRP)
  751.     dataGMCTRN = bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e,
  752.                             0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10])
  753.     self._writecommand(TFT.GMCTRN1)
  754.     self._writedata(dataGMCTRN)
  755.     self._writecommand(TFT.NORON)                #Normal display on.
  756.     time.sleep_us(10)
  757.     self._writecommand(TFT.DISPON)
  758.     time.sleep_us(100)
  759.     self.cs(1)
  760. #def maker(  ) :
  761. #  t = TFT(1, "X1", "X2")
  762. #  print("Initializing")
  763. #  t.initr()
  764. #  t.fill(0)
  765. #  return t
  766. #def makeb(  ) :
  767. #  t = TFT(1, "X1", "X2")
  768. #  print("Initializing")
  769. #  t.initb()
  770. #  t.fill(0)
  771. #  return t
  772. #def makeg(  ) :
  773. #  t = TFT(1, "X1", "X2")
  774. #  print("Initializing")
  775. #  t.initg()
  776. #  t.fill(0)
  777. #  return t
复制代码
接着编写相关字符文件,由于文件太长,这里不再赘述,详细可以参见工程文件
查看数据手册发现两个引脚属于SPI0
【Beetle 树莓派RP2350】屏幕显示图2

编写显示主程序如下
在主程序中,我完成的显示内容包括:SPI初始化 -> TFT屏幕初始化 -> 执行显示任务 -> 输出帧率

  1. from machine import UART,SPI,Pin
  2. from ST7735 import TFT
  3. from font import sysfont, seriffont, terminalfont
  4. import time
  5. import math
  6. # Fiz pra testar 2 displays com o mesmo script pq sim.
  7. display085 = False
  8. TFT_CLK =   const(18)
  9. TFT_MOSI =  const(19)
  10. TFT_DC =    const(26)
  11. TFT_RST =   const(27)
  12. TFT_CS =    const(16)
  13. # 20 Mhz = 20_000_000 (default), 51_200_000, 80_000_000
  14. spi = SPI(0, baudrate=80_000_000, polarity=0, phase=0, bits=8, sck=Pin(TFT_CLK), mosi=Pin(TFT_MOSI), miso=None)
  15. tft = TFT(spi, TFT_DC, TFT_RST, TFT_CS)
  16. # Na vdd, no Aliexpress dizia que o display 0.85' (ST7735) era 128x160, mas
  17. # depois desses testes confirmei ser na verdade 128x128.
  18. if (display085):
  19.     tft.initb2() # lcd 0.85'
  20.     tft.invertcolor(True)
  21.     tft.rgb(False)
  22. else:
  23.     tft.initg() # lcd 1.77' 128x160
  24. tft.rotation(2);
  25. print('Hello from Pi Pico using Python. Running: Display SPI ST7735.')
  26. def testlines(color):
  27.     tft.fill(TFT.BLACK)
  28.     for x in range(0, tft.size()[0], 6):
  29.         tft.line((0,0),(x, tft.size()[1] - 1), color)
  30.     for y in range(0, tft.size()[1], 6):
  31.         tft.line((0,0),(tft.size()[0] - 1, y), color)
  32.     tft.fill(TFT.BLACK)
  33.     for x in range(0, tft.size()[0], 6):
  34.         tft.line((tft.size()[0] - 1, 0), (x, tft.size()[1] - 1), color)
  35.     for y in range(0, tft.size()[1], 6):
  36.         tft.line((tft.size()[0] - 1, 0), (0, y), color)
  37.     tft.fill(TFT.BLACK)
  38.     for x in range(0, tft.size()[0], 6):
  39.         tft.line((0, tft.size()[1] - 1), (x, 0), color)
  40.     for y in range(0, tft.size()[1], 6):
  41.         tft.line((0, tft.size()[1] - 1), (tft.size()[0] - 1,y), color)
  42.     tft.fill(TFT.BLACK)
  43.     for x in range(0, tft.size()[0], 6):
  44.         tft.line((tft.size()[0] - 1, tft.size()[1] - 1), (x, 0), color)
  45.     for y in range(0, tft.size()[1], 6):
  46.         tft.line((tft.size()[0] - 1, tft.size()[1] - 1), (0, y), color)
  47. def testfastlines(color1, color2):
  48.     tft.fill(TFT.BLACK)
  49.     for y in range(0, tft.size()[1], 5):
  50.         tft.hline((0,y), tft.size()[0], color1)
  51.     for x in range(0, tft.size()[0], 5):
  52.         tft.vline((x,0), tft.size()[1], color2)
  53. def testdrawrects(color):
  54.     tft.fill(TFT.BLACK);
  55.     for x in range(0,tft.size()[0],6):
  56.         tft.rect((tft.size()[0]//2 - x//2, tft.size()[1]//2 - x/2), (x, x), color)
  57. def testfillrects(color1, color2):
  58.     tft.fill(TFT.BLACK);
  59.     for x in range(tft.size()[0],0,-6):
  60.         tft.fillrect((tft.size()[0]//2 - x//2, tft.size()[1]//2 - x/2), (x, x), color1)
  61.         tft.rect((tft.size()[0]//2 - x//2, tft.size()[1]//2 - x/2), (x, x), color2)
  62. def testfillcircles(radius, color):
  63.     for x in range(radius, tft.size()[0], radius * 2):
  64.         for y in range(radius, tft.size()[1], radius * 2):
  65.             tft.fillcircle((x, y), radius, color)
  66. def testdrawcircles(radius, color):
  67.     for x in range(0, tft.size()[0] + radius, radius * 2):
  68.         for y in range(0, tft.size()[1] + radius, radius * 2):
  69.             tft.circle((x, y), radius, color)
  70. def testtriangles():
  71.     tft.fill(TFT.BLACK);
  72.     color = 0xF800
  73.     w = tft.size()[0] // 2
  74.     x = tft.size()[1] - 1
  75.     y = 0
  76.     z = tft.size()[0]
  77.     for t in range(0, 15):
  78.         tft.line((w, y), (y, x), color)
  79.         tft.line((y, x), (z, x), color)
  80.         tft.line((z, x), (w, y), color)
  81.         x -= 4
  82.         y += 4
  83.         z -= 4
  84.         color += 100
  85. def testroundrects():
  86.     tft.fill(TFT.BLACK);
  87.     color = 100
  88.     for t in range(5):
  89.         x = 0
  90.         y = 0
  91.         w = tft.size()[0] - 2
  92.         h = tft.size()[1] - 2
  93.         for i in range(17):
  94.             tft.rect((x, y), (w, h), color)
  95.             x += 2
  96.             y += 3
  97.             w -= 4
  98.             h -= 6
  99.             color += 1100
  100.         color += 100
  101. def tftprinttest():
  102.     tft.fill(TFT.BLACK);
  103.     v = 30
  104.     tft.text((0, v), "Hello World!", TFT.RED, sysfont, 1, nowrap=True)
  105.     v += sysfont["Height"]
  106.     tft.text((0, v), "Hello World!", TFT.YELLOW, sysfont, 2, nowrap=True)
  107.     v += sysfont["Height"] * 2
  108.     tft.text((0, v), "Hello World!", TFT.GREEN, sysfont, 3, nowrap=True)
  109.     v += sysfont["Height"] * 3
  110.     tft.text((0, v), str(1234.567), TFT.BLUE, sysfont, 4, nowrap=True)
  111.     time.sleep_ms(2000)
  112.     tft.fill(TFT.BLACK);
  113.     v = 0
  114.     tft.text((0, v), "Hello World!", TFT.RED, sysfont)
  115.     v += sysfont["Height"]
  116.     tft.text((0, v), str(math.pi), TFT.GREEN, sysfont)
  117.     v += sysfont["Height"]
  118.     tft.text((0, v), " Want pi?", TFT.GREEN, sysfont)
  119.     v += sysfont["Height"] * 2
  120.     tft.text((0, v), hex(8675309), TFT.GREEN, sysfont)
  121.     v += sysfont["Height"]
  122.     tft.text((0, v), " Print HEX!", TFT.GREEN, sysfont)
  123.     v += sysfont["Height"] * 2
  124.     tft.text((0, v), "Sketch has been", TFT.WHITE, sysfont)
  125.     v += sysfont["Height"]
  126.     tft.text((0, v), "running for: ", TFT.WHITE, sysfont)
  127.     v += sysfont["Height"]
  128.     tft.text((0, v), str(time.ticks_ms() / 1000), TFT.PURPLE, sysfont)
  129.     v += sysfont["Height"]
  130.     tft.text((0, v), " seconds.", TFT.WHITE, sysfont)
  131. def printhello():
  132.     x = 0
  133.     y = 0
  134.     message = "Hello World"
  135.     fontSize = 2
  136.     fontType = sysfont # sysfont (the best), terminalfont, seriffont
  137.     tft.text((x, y), message, TFT.GRAY, fontType, fontSize) # 1
  138.     tft.text((x, y+15), message, TFT.MAROON, fontType, fontSize)
  139.     tft.text((x, y+30), message, TFT.GRAY, fontType, fontSize)
  140.     tft.text((x, y+45), message, TFT.MAROON, fontType, fontSize)
  141.     tft.text((x, y+60), message, TFT.GRAY, fontType, fontSize) # 5
  142.     tft.text((x, y+75), message, TFT.MAROON, fontType, fontSize)
  143.     tft.text((x, y+90), message, TFT.GRAY, fontType, fontSize) # 7 (retrato 128x128)
  144.     tft.text((x, y+105), message, TFT.MAROON, fontType, fontSize) # 8 (paisagem 128x160, retrato 128x128)
  145.     tft.text((x, y+120), message, TFT.GRAY, fontType, fontSize) # 9 (metade fora do frame 128x128)
  146.     tft.text((x, y+135), message, TFT.MAROON, fontType, fontSize) # 10 (retrato 128x160)
  147.     tft.text((x, y+150), message, TFT.NAVY, fontType, fontSize) # 11 (metade fora do frame 128x160)
  148. def test():
  149.     tft.fill(TFT.BLACK)
  150.     printhello()
  151.     tft.fill(TFT.RED)
  152.     printhello()
  153.     tft.fill(TFT.GREEN)
  154.     printhello()
  155.     tft.fill(TFT.BLUE)
  156.     printhello()
  157.     tft.fill(TFT.YELLOW)
  158.     printhello()
  159.     tft.fill(TFT.PURPLE)
  160.     printhello()
  161.     tft.fill(TFT.WHITE)
  162.     printhello()
  163. def test_fps():
  164.     frame_count = 0
  165.     start_time = time.ticks_ms()
  166.    
  167.     while True:
  168.       
  169.         test()
  170.         frame_count += 1
  171.         
  172.         # 每1秒计算一次帧率
  173.         if time.ticks_ms() - start_time >= 1000:
  174.             fps = frame_count / ((time.ticks_ms() - start_time) / 1000)
  175.             print("FPS: ", fps)
  176.             frame_count = 0
  177.             start_time = time.ticks_ms()
  178.             
  179.             
  180. def test_fps2():
  181.     tft.fill(TFT.BLACK)  # 清空屏幕
  182.     frame_count = 1  # 测试 50 帧
  183.     start_time = time.ticks_ms()  # 记录开始时间
  184.     for _ in range(frame_count):
  185.         testlines(TFT.RED)
  186.         test()
  187.         tftprinttest()
  188.     end_time = time.ticks_ms()  # 记录结束时间
  189.     elapsed_time = (end_time - start_time) / 1000  # 计算总时间 (秒)
  190.     fps = frame_count / elapsed_time  # 计算 FPS
  191.     print(f"FPS: {fps:.2f}")  # 输出帧率
  192. test_fps2()
  193. #test_main()
复制代码
最终显示帧率大约为20帧/秒
显示效果如下
【Beetle 树莓派RP2350】屏幕显示图9

【Beetle 树莓派RP2350】屏幕显示图10

【Beetle 树莓派RP2350】屏幕显示图11

工程文件如下
下载附件LCD_test.rar
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail