当前位置:   article > 正文

总线学习3--SPI

总线学习3--SPI

一 环境搭建

老规矩,先上图吧。。

上面电源线接到VBUS了,给的一个5V,应该3.3V。不过这个屏还能正常跑也是不错。

折腾了一个晚上,主要还是找驱动,然后熟悉SPI接口的接法。

遇到了两个坑:

1 接口名称不统一,相对于I2C的两根线,这个SPI显示接口名称真的很多,SCL/SCK,SDA/MOSI,A0/DC,最后才知道这几个是一个东西。网上也找到几个参考,但是和板子上的标号对不起来。后来才慢慢搞明白。

2 没有miso。驱动代码库里面有个,example也有这个,但是死活板子上没这个口。最后看了一些参考代码,这个可以直接给None。

这两个坑踩过去,就没啥问题了,一次点亮出图。

这个应该会写两篇,一篇重点写SPI,一篇重点写显示。

驱动来自:GitHub - boochow/MicroPython-ST7735: ST7735 TFT LCD driver for MicroPython

接线:

ST7735 PinPico Pin
VCC3.3V
GNDGND
SCL (SCK)GP10
SDA (MOSI)GP11
RES (RST)GP17
DC(A0)GP16
CSGP18

二 代码

应用(显示图)

  1. from ST7735 import TFT,TFTColor
  2. from machine import SPI,Pin
  3. spi = SPI(1, baudrate=20000000, polarity=0, phase=0, sck=Pin(10), mosi=Pin(11), miso=None)
  4. tft=TFT(spi,16,17,18)
  5. tft.initr()
  6. tft.rgb(True)
  7. tft.fill(TFT.BLACK)
  8. f=open('test128x160.bmp', 'rb')
  9. if f.read(2) == b'BM': #header
  10. dummy = f.read(8) #file size(4), creator bytes(4)
  11. offset = int.from_bytes(f.read(4), 'little')
  12. hdrsize = int.from_bytes(f.read(4), 'little')
  13. width = int.from_bytes(f.read(4), 'little')
  14. height = int.from_bytes(f.read(4), 'little')
  15. if int.from_bytes(f.read(2), 'little') == 1: #planes must be 1
  16. depth = int.from_bytes(f.read(2), 'little')
  17. if depth == 24 and int.from_bytes(f.read(4), 'little') == 0:#compress method == uncompressed
  18. print("Image size:", width, "x", height)
  19. rowsize = (width * 3 + 3) & ~3
  20. if height < 0:
  21. height = -height
  22. flip = False
  23. else:
  24. flip = True
  25. w, h = width, height
  26. if w > 128: w = 128
  27. if h > 160: h = 160
  28. tft._setwindowloc((0,0),(w - 1,h - 1))
  29. for row in range(h):
  30. if flip:
  31. pos = offset + (height - 1 - row) * rowsize
  32. else:
  33. pos = offset + row * rowsize
  34. if f.tell() != pos:
  35. dummy = f.seek(pos)
  36. for col in range(w):
  37. bgr = f.read(3)
  38. tft._pushcolor(TFTColor(bgr[2],bgr[1],bgr[0]))
  39. spi.deinit()

驱动

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

三 SPI协议

插上祖传逻辑分析仪,五根线一起上,抓信号。

信号通道
SDA0
SCK1
DC2
CS3
RESET4

接口说明:

整个信号大概是这样的,可以看到reset就是开始拉低再拉高,相当于重启了屏幕,之后就没事了。DC干的事情也很少。这部分就不多看了。重点还是看前面三个SPI的吧。

SPI一般是4根线,SCLK是时钟,MOSI是主设备输出,MISO是主设备输入(LCD没有输入,所以这次少了一根线),SS是片选。

1 片选

​​​​​​​不同于I2C,SPI是通过片选信号来提供多设备支持。如下:

只有片选信号拉低时,信号才有效。这样也造成了SPI需要多个片选线,如果挂10个设备,就要10个片选线,这点确实就不如I2C先进了。。。

SPI(0, baudrate=40000000, polarity=1, phase=1, sck=Pin(18), mosi=Pin(19))

SPI库背身只管理时钟和数据,片选是自己管理。

  1. def _writecommand( self, aCommand ) :
  2. '''Write given command to the device.'''
  3. self.dc(0)
  4. self.cs(0)
  5. self.spi.write(bytearray([aCommand]))
  6. self.cs(1)

从代码也可以看出,写命令时候会手动将cs拉低。之后恢复。

2 时钟

然后是时钟线,这个和I2C差不多,倒是没啥好说的。就是上沿时候的MOSI或者MISO才算有效。(但是时钟线的间隔也有点怪。。。也不是固定的。。。)

3 MOSI/MISO

最后就是MOSI,这里也叫SDA。

根据时钟线上沿的MOSI信号,所以数据是1000 0000,最后换算出来就是0x80。(其实最后还有1个1,但是我不知道为什么没有解析,是不是一次只处理8位?)

好吧,虽然还有一些疑问,后面澄清了我会再更新。但是SPI的重点内容我想都提到了,就到这里了。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号