Als Test-Programm diente der folgende Code. Dabei wurden die Parameter für die Pins entsprechend den Angaben der Abbildung 1 vorgenommen; für die übrigen Parameter habe ich diejenigen Werte benutzt, welche auch beim TTGO eingesetzt werden:
Code: Alles auswählen
# Display_Test_1
from machine import Pin, SPI, SoftSPI
import st7789
from time import sleep
spi = SPI(1, baudrate=20000000, polarity=1, sck=Pin(3), mosi=Pin(2))
display = st7789.ST7789(spi, 128, 128, reset=Pin(1, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(6, Pin.OUT), backlight=Pin(10, Pin.OUT), rotation=1)
display.init()
display.off() # Hintergrundbeleuchtung einschalten (vgl. http://www.forum.g-heinrichs.de/viewtopic.php?f=18&t=174)
display.fill(0) # löschen
sleep(2)
display.fill(7789.MAGENTA) # Display mit Magenta-Farbe füllen
sleep(2)
print('ENDE')
Nun habe ich das Hardware-SPI durch ein Software-SPI ersetzt; die Instanziierung lautet in diesem Fall:
spi = SoftSPI(baudrate=800000, polarity=1, sck=Pin(3), mosi=Pin(2), miso=Pin(6)) # miso = dc
Und tatsächlich können wir mit diesem Programm eine Einfärbung des Displays feststellen; allerdings ist die angezeigte Farbe nicht MAGENTA!
Ein weiteres (kleineres) Problem zeigt sich, wenn wir den rotation-Parameter bei der Instanziierung von display verändern. Mit diesem Parameter können wir die Darstellung auf dem Display einstellen: Die Standard-Einstellung ist rotation=1; diese ist für den Fall geeignet, dass für den Betrachter der USB-Anschluss des T-QT-Moduls auf der linken Seite liegt. Für andere Blickrichtungen kann die Anzeige um 90° (rotation=2), 180° (rotation=3) oder 270° (rotation=4) rotiert werden. Bei den rotation-Werten 2 und 3 ist die Darstellung um 1 Pixel verschoben.
Zwei Dinge sind jetzt zu klären:
1. Warum wird hier eine falsche Farbe angezeigt?
2. Warum funktioniert das Hardware-SPI nicht?
3. Wie können wir das Problem mit den rotation-Werten lösen?
1. Das Farbenproblem
Kümmern wir uns zunächst um die Farben! Tests mit anderen Farben zeigen, dass auch andere Farben nicht korrekt angezeigt werden. Die Farbe Grün (st7789.GREEN) wird hingegen richtig dargestellt. Außerdem stellen wir fest, dass Rot und Blau vertauscht angezeigt werden. Offensichtlich arbeitet der Display-Treiber GC9107 nicht mit einem RGB565-Format, sondern mit einem BGR565-Format (vgl. auch https://www.forum.g-heinrichs.de/viewto ... f=18&t=141). Eine solche Vertauschung von Rot- und Blauanteil können wir mit unserem st7789-Treiber bewirken, indem wir bei der Instanziierung von display den zusätzlichen Parameter
color_order=st7789.BGR
einfügen. Die Instanziierung von display sieht dann so aus:
display = st7789.ST7789(spi, 128, 128, reset=Pin(1, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(6, Pin.OUT), backlight=Pin(10, Pin.OUT), rotation=1, color_order=st7789.BGR)
Nun werden die Farben korrekt dargestellt. Das folgende Test-Programm Display_Test_2.py zeigt nun diese korrekte Darstellung der Farben. In diesem Programm wird auch beispielhaft die Anzeige von geometrischen Formen und Texten gezeigt.
Code: Alles auswählen
# Display_Test_2
# Durch Auskommentieren können Sie zwischen dem Hardware- und dem Software-SPI auswählen
from machine import Pin, SPI, SoftSPI
import st7789
import vga1_16x16 as font
from time import sleep
# spi = SPI(1, baudrate=20000000, sck=Pin(3), mosi=Pin(2), miso=Pin(6))
spi = SoftSPI(baudrate=800_000, polarity=1, sck=Pin(3), mosi=Pin(2), miso=Pin(6)) # miso = dc
display = st7789.ST7789(spi, 128, 128, reset=Pin(1, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(6, Pin.OUT), backlight=Pin(10, Pin.OUT), rotation=1, color_order=st7789.BGR)
display.init()
display.off() # Hintergrundbeleuchtung einschalten (vgl. http://www.forum.g-heinrichs.de/viewtopic.php?f=18&t=174)
display.fill(0) # löschen
# einige Farben anzeigen lassen
farben = [['weiß', st7789.WHITE],
['blau', st7789.BLUE],
['schwarz', st7789.BLACK],
['gelb', st7789.YELLOW],
['magenta', st7789.MAGENTA],
['rot', st7789.RED]]
for f in farben:
print('Farbwert für ', f[0], ' ist ', f[1])
display.fill(f[1])
sleep(1)
sleep(2)
# Kreise
for i in range(100):
f = st7789.BLUE * i // 100
display.fill_circle(64, 64, i, f)
# Text
display.text(font, 'ENDE', 35, 55)
print('ENDE')
Leider ist das Software-SPI recht langsam. Deswegen kümmern wir uns nun noch einmal um das Hardware-SPI.
2. Das Problem mit dem Hardware-SPI
Zunächst habe ich überprüft, ob durch das Hardware-SPI überhaupt Signale an das Display gesendet werden. Dazu habe ich die Signale sck und mosi auf Pins umgeleitet, die für Anschlusskabel zugängig sind. Die Signale habe ich dann mit einem Logik-Analysator angeschaut. Abb. 2 zeigt einen Screenshot; die Signale sehen auf den ersten Blick ganz ordentlich aus, insbesondere waren die Bits in der erwarteten Reihenfolge (MSB zuerst) gesendet worden. Die Ergebnisse waren für Id=1 und Id=2 gleich.
SPI-Protokolle können sich noch in den Parametern "Clock Polarity" (CPOL) und "Clock Phase" (CPHA) unterscheiden (vgl. Abb. 3 links); Details dazu finden Sie hier. Diese können bei der Instanziierung angegeben werden (vgl. https://docs.micropython.org/en/latest/ ... e.SPI.html). Ein Blick in das Datenblatt des GC9107 zeigt, dass das Clock-Signal im Ruhezustand 0 sein soll und die Datenbits bei einer aufsteigenden Flanke von sck/SCL gelesen werden (vgl. Abb. 3 rechts).
Das entspricht den Parameterwerten CPOL = 0 und CPHA = 0; da dies die Standardwerte sind, lassen wir jetzt den beim TTGO bislang benutzten Eintrag "polarity=1" bei der Instanziierung von spi einfach weg:
spi = SPI(1, baudrate=20000000, sck=Pin(3), mosi=Pin(2), miso=Pin(6))
Bei dieser Einstellung werden die einzelnen mosi-Bits bei einer steigenden Flanke des Takt-Signals sck übernommen. Damit funktioniert nun auch das Display des T-QT mit dem Hardware-SPI!
Prüfen Sie es selbst nach: Ändern Sie die Auskommentierung bei dem Programm Display_Test_2.py, und das Display wird jetzt korrekt mit den verschiedenen Farben ausgefüllt - und das wesentlich schneller als bei dem Software-SPI.
Merkwürdig ist nur, dass das Software-SPI trotz des falschen polarity-Parameters funktioniert hat.
3. Das Problem mit dem rotation-Parameter
Wie bereits erwähnt, müssen wir nur für die Fälle rotation=2 und rotation=3 aktiv werden. Dazu benutzen wir die Methode offset von unserem display-Objekt. Diese Methode dient dazu, die x- und y-Koordinaten an die interne Verarbeitung bei den verschiedenen Displays anzupassen. In unserem Fall führt der Befehl
display.offset(258, 258)
zum Ziel. Dies können Sie mit dem folgenden Programm austesten. Wer mag, kann zum Vergleich einmal die beiden Korrekturzeilen auskommentieren.
Code: Alles auswählen
# display_rotation_test.py
from machine import Pin, SPI
import st7789
import vga1_16x16 as font
from time import sleep
spi = SPI(1, baudrate=20_000_000, sck=Pin(3), mosi=Pin(2))
display = st7789.ST7789(spi, 128, 128, reset=Pin(1, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(6, Pin.OUT), backlight=Pin(10, Pin.OUT), rotation=1, color_order=st7789.BGR)
# rotation-Werte 1 und 4 arbeiten korrekt.
# Bei den rotation-Werten 2 und 3 ist die Anzeige um 1 Pixel verschoben, in diesem Fall Korrektur mit display.offset(258, 258), s. u.
display.init()
display.fill(0)
display.off() # umgekehrte Logik gegenüber TTGO!
# jetzt in einer Schleife alle rotation-Modi durchlaufen:
while True:
for i in range(4):
r = i + 1
display.rotation(r)
# die folgenden beiden Zeilen auskommentieren -> keine Korrektur!
if (r == 2) or (r == 3):
display.offset(258, 258)
display.fill(0)
display.rect(0, 0, 127, 127, st7789.RED)
display.text(font, 'Test ' + str(r), 10, 20)
sleep(2)
.