GLCD, farbiges XV-Display und BASCOM (Beispiele) FAQ

Cassio

Aktives Mitglied
29. Okt. 2008
4.027
17
38
Region Hannover
Sprachen
  1. BascomAVR
Hallo zusammen!

Ich trage hier einfach mal ein paar Programmbeispiele rund um das kleine (128x160 Pixel) farbige OLED XV-Display ein.

Da dies Display einen eigenen Controller besitzt, der sich nicht nur um das Darstellen von Pixeln kümmert sondern weit aus flexibler ist, folgen hier einfach mal ein paar "Ansteuerungen".

Wie es sich für ein FAQ gehört, geht es hier nicht um ein Projekt und wenn jemand Fragen oder andere Erfahrungen hat, dann kann er gern dafür diesen Thread benutzen.


Ich fange aber nun erst mal vorne an....

Das Display:


Wie auf dem Bild schon zu erkennen ist, kann das Display hier im Shop käuflich erworben werden. ;)
Und hier ist der LINK dazu.

Display-Controller:
Der Controller wird über die SPI-Schnittstelle angesprochen und ist daher für nahezu alle Mikrocontroller und Programmiersprachen geeignet.
Hier mal ein Anschlussbeispiel mit einem ATMega16:
XV-Display+Mega16.gif

Hinweis:
Wenn ein AVR benutzt wird, der via ISP über die SPI-Schnittstelle programmiert wird (wie im Beispiel gezeigt), dann sollte beim Flashen des AVRs das Display von der Schnittstelle getrennt werden!


Ansteuerung / Programmierung unter BASCOM:
Die Ansteuerung des Dispalys ist trotz der vielen Optionen recht einfach und fast immer wieder gleich.
Hier mal ein Beispiel, wie man die Stiftfarbe (Vordergrundfarbe) ändert:
Code:
  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &H14                                                  ' SetPenColor
  Spiout I , 1

  Bitwait Display_busy , Reset
  Spiout Red , 1                                            ' Send Parameter
  Spiout Green , 1
  Spiout Blue , 1

  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1


Zur Erklärung:
Als Erstes wird durch den BUSY-Pin geprüft, ob das Display bereit ist:
Code:
  Bitwait Display_busy , Set
Dann wird der CS-Pin auf Low gesetzt:
Code:
  Reset Display_cs
Nach einer kurzen Pause wird dann das Kommando gesendet, dass die Stiftfarbe geändert werden soll:
Code:
  Waitus 2
  [B]I = &H14                                                  ' SetPenColor[/B]
  Spiout I , 1
Nach erneuter Prüfung des BUSY-Pins werden dann die einzelnen Werte für die Farben übermittelt:
Code:
  Bitwait Display_busy , Reset
  Spiout Red , 1                                         
  Spiout Green , 1
  Spiout Blue , 1
Dann wird wieder der BUYS-Pin abgefragt und anschließend der CS-Pin wieder High geschaltet:
Code:
  Bitwait Display_busy , Set
  Set Display_cs                                     
  Waitus 1
Fertig!
Nun wurden alle benötigten Daten an das Display erfolgreich übermittelt und die neue Stiftfarbe ist sofort verfügbar. :)


Mit den verschiedenen Kommandos kann man dann recht schnell ähnlich nette Displaylayouts entwickeln wie z.B. dieses hier:
XV-Prog_Beispiel.jpg


Damit ich aber die Ansteuerung des Displays nicht immer wieder neu eingeben muss, habe ich mir dafür entsprechende Subroutinen geschrieben.
Diese werden dann einfach mitten im Programm aufgerufen und ausgeführt.

Wie ich das im einzelnen realisiert habe, folgt dann in Kürze...

Gruß,
Cassio
 
Hi Cassio,

Hinweis:
Wenn ein AVR benutzt wird, der via ISP über die SPI-Schnittstelle programmiert wird (wie im Beispiel gezeigt), dann sollte beim Flashen des AVRs das Display lieber solange von der Schnittstelle getrennt werden!
es wird ja PB4/SS für SlaveSelect/CS des Displays benutzt. Das Signal is beim
Display Low-Active (/CS). Da beim Programmiervorgang durch den Reset
eigentlich alle anderen Pins auf TriState gehen sollten (hochohmig) würde ich
den /CS des Displays einfach mit einem PullUp-Widerstand (10k ?) auf Vcc
ziehen. Damit sollte es während des Prog-Vorgangs inaktiv sein. Würde mich
interessieren ob der Gedankengang stimmt :D

Gruß
Dino
 
Hi Dino,

CS\ dient hier zur Synchronisation eines Datenpaketes, SPI-Out des Displays schaltet hier nicht hochohmig, wenn CS\ high ist. Grund dafür ist der Output-Leveltransceiver, dieser hat keine Tristate-Funktion.

Gruß,
Dirk
 
Hallo zusammen!

Hier nun mal eine kleine Übersicht der verfügbaren Kommandos:

  • Stiftfarbe (RGB) einstellen = &H14
  • Hintergrundfarbe (RGB) einstellen = &H15
  • Rechteck (RGB) erstellen = &H21
  • Linie (RGB) zeichnen = &H3A
  • 1-Pixel-Punkt (RGB) = &H2A
  • Kreis (RGB) zeichnen = &H32
  • internes Image auswählen und anzeigen = &HA4
  • Schriftgröße ändern (interne Fonts) = &H11
  • Text ausgeben = &H48

Wie oben schon erwähnt, ist dies nur eine kleine Auswahl von Kommandoes, die man zum Ansteuern des Displays verwenden kann.

Für alle diese Kommandos habe ich mir erst mal spezielle Subroutinen erstellt.

Der Vollständigkeit halber noch einmal die Sub für die Stiftfarbe....
Code:
Fg:
'Set Pen Color

  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &H14                                                  ' SetPenColor
  Spiout I , 1

  Bitwait Display_busy , Reset
  Spiout Red , 1                                            ' Send Parameter
  Spiout Green , 1
  Spiout Blue , 1

  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1

Return

...die Hintergrundfarbe...
Code:
Bg:
'Set Background Color

  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &H15                                                  ' SetBackgroundColor
  Spiout I , 1

  Bitwait Display_busy , Reset
  Spiout Red , 1                                            ' Send Parameter
  Spiout Green , 1
  Spiout Blue , 1

  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1

Return

...ein Rechteck zeichnen...
Code:
Rahmen:
'Box oder Rahmen in RGB

  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &H21                                                  ' DrawRectRGB
  Spiout I , 1

  Bitwait Display_busy , Reset
  Spiout X1 , 1                                             ' Send Parameter
  Spiout Y1 , 1
  Spiout X2 , 1
  Spiout Y2 , 1
  Spiout Red , 1
  Spiout Green , 1
  Spiout Blue , 1
  Spiout Fillmode , 1

  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1

Return
Hinweis:
Bei der Anweisung ein Rechteck zu zeichnen kann man mit der Variable "Fillmode" entscheiden,
ob es nur ein Rahmen (Fillmode = 0) oder eine Fläche (Fillmode = 1) sein soll.


...eine Linie zeichnen...
Code:
Linie:
'Linie in RGB

  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &H3A                                                  ' DrawLineRGB
  Spiout I , 1

  Bitwait Display_busy , Reset
  Spiout X1 , 1                                             ' Send Parameter
  Spiout Y1 , 1
  Spiout X2 , 1
  Spiout Y2 , 1
  Spiout Red , 1
  Spiout Green , 1
  Spiout Blue , 1

  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1

Return

...einen einzelnen Pixel-Punkt anzeigen...
Code:
Punkt:
'Ein Pixel-Punkt in RGB

  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &H2A                                                  ' DrawPixelRGB
  Spiout I , 1

  Bitwait Display_busy , Reset
  Spiout X1 , 1                                             ' Send Parameter
  Spiout Y1 , 1
  Spiout Red , 1
  Spiout Green , 1
  Spiout Blue , 1

  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1

Return

...einen Kreis zeichnen...
Code:
Kreis:
'Kreis in RGB

  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &H32                                                  ' DrawCircleRGB
  Spiout I , 1

  Bitwait Display_busy , Reset
  Spiout X1 , 1                                             ' Send Parameter
  Spiout Y1 , 1
  Spiout Rd , 1
  Spiout Red , 1
  Spiout Green , 1
  Spiout Blue , 1

  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1

Return


Da das Displaymodul einen eigenen Speicher besitzt, in dem Fontdateien oder Bilder bzw. Icons abgelegt werden können, muss man weder eine Fontdatei im BASCOM-Code vorhalten noch alle Bilder ins BGF`s konvertieren und einzeln übermitteln. :)
Dies macht nicht nur den BASCOM-Code kleiner und übersichtlicher, es beschleunigt natürlich auch die Darstellung. Schließlich muss nicht jedes Zeichen oder Bild bitweise zum Displaymodul übertragen werden.
Voraussetzung ist natürlich, dass man vorher die Bilder mit dem optionalen USB-Stick (nebst Packagemanager) schon in den Speicher übertragen hat. ;)
Hier nun meine Sub zur Darstellung eines Bildes, dass sich bereits im internen Speicher befindet...
Code:
Image:
' interne Bilder und Icons anzeigen

  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &HA4                                                  ' Dspcmd_displayimageitem
  Spiout I , 1

  Bitwait Display_busy , Reset
  I = High(x)                                               ' Locate x
  Spiout I , 1
  I = Low(x)
  Spiout I , 1

  I = High(y)                                               ' Locate y
  Spiout I , 1
  I = Low(y)
  Spiout I , 1

  Spiout Packageindex , 1

  I = High(itemindex)                                       ' Item Index
  Spiout I , 1
  I = Low(itemindex)
  Spiout I , 1

  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1

Return

...mit dieser Sub kann die Schrift geändert werden, die sich auch bereits im internen Speicher befindet...
Code:
Schrift:
'Set Font

  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &H11                                                  ' SetFont
  Spiout I , 1

  Bitwait Display_busy , Reset
  Spiout Fontindex , 1                                      ' Fontindex(0, 1, 2, 3, 4, 5, 6)


  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1

Return


Um einen fertigen String als Text auszugeben, nutze ich diese Sub...
Code:
Text:
'Text-String ausgeben

Bitwait Display_busy , Set
Reset Display_cs                                            ' Chipselect Display Module
Waitus 2

I = &H48                                                    ' Display Text
Spiout I , 1

Bitwait Display_busy , Reset
Spiout X1 , 1                                               ' Send Parameter
Spiout Y1 , 1
Spiout Xmax , 1

' Eingabestring in einzelne Zeichen zerlegen
   For Zz = 1 To Len(eingabe)                               'Pro Zeichen im String aufwärtszählen
      Zeichen = Mid(eingabe , Zz , 1)                       'Einzelne Ziffer, oder Buchstabe aus String
      Char = Asc(zeichen)

     Spiout Char , 1
   Next Zz

Char = 0                                                    'Binäre Null zum Abschluss für den Textstring !
Spiout Char , 1

Bitwait Display_busy , Set
Set Display_cs                                              ' Chipselect Display Module
Waitus 1

Return

Damit ein fertiger String verarbeitet werden kann, wird der String in einzelne Zeichen zerlegt.
Dies geschieht hiermit:
Code:
' Eingabestring in einzelne Zeichen zerlegen
   For Zz = 1 To Len(eingabe)                               'Pro Zeichen im String aufwärtszählen
      Zeichen = Mid(eingabe , Zz , 1)                       'Einzelne Ziffer, oder Buchstabe aus String
      Char = Asc(zeichen)
Die einzelnen Zeichen werden so der Reihe nach zum Displaymodul übertragen.
Zum Abschluss der Zeichenfolge MUSS dann noch eine binäre NULL gesendet werden.
Dies geschieht hier:
Code:
Char = 0                                                    'Binäre Null zum Abschluss für den Textstring !
Spiout Char , 1


So, dass war es erst mal wieder.... :)
Ich habe mir aber (aus Bequemlichkeit) noch ein paar "Extras" einfallen lassen, was die Übergabe der Farbwerte und Positionskoordinaten betrifft..... aber dass stelle ich hier beim nächsten Mal mit vor. ;)


Grüße,
Cassio
 
Hi Dirk,

CS\ dient hier zur Synchronisation eines Datenpaketes, SPI-Out des Displays schaltet hier nicht hochohmig, wenn CS\ high ist. Grund dafür ist der Output-Leveltransceiver, dieser hat keine Tristate-Funktion.
eine wichtige Info ... Aber für die einfache Idee => Kuh Ka Ke :eek: :p
Also müßte man sicherheitshalber die üblichen Leitungen des Displays wie
bei Atmel beschrieben über 1k-Widerstände von der ISP-Schnittstelle trennen.

Weil das Display immer abziehen wenn man programmiert ist zwar für Versuche
OK aber für ein fertiges Gerät ein unhaltbarer Zustand.

Ergebnis ... /CS über 10k PullUp auf sauberen Pegel bringen und in die
Leitungen MISO/MOSI/SCK des Displays jeweils nen 1k in Reihe. Dann sollte
es keine Probleme geben.

Gruß
Dino
 
Hi Dino,

das Displaymodul muss nicht unbedingt an die Pins für Hardware-SPI angeschlossen werden, Software-SPI mit beliebigen IO-Pins geht natürlich auch. Vorsichtig muss man sein, wenn man serielle Widerstände nutzt, sind diese zu hoch oder dann noch die Leitungslänge zu groß, kann es passieren, dass eine Übertragung mit 500bps nicht mehr funktioniert.

Gruß,
Dirk
 
Hi Dirk,

Vorsichtig muss man sein, wenn man serielle Widerstände nutzt, sind diese zu hoch oder dann noch die Leitungslänge zu groß, kann es passieren, dass eine Übertragung mit 500bps nicht mehr funktioniert.
ich schätze mal, du meinst 500kbps oder ? :D

Mit den Widerständden hast du natürlich recht. Die bilden dann mit den
Kapazitäten der Chipeingänge einen Tiefpaß und verschleifen die Kanten der
Signale. Dadurch kann dann auch teilweise das Timing durcheinanderkommen ;)
Stimmt das so ? :rolleyes:

Man kann ja ein wenig rumprobieren wann es noch sauber funktioniert.

Gruß
Dino
 
Hi Dino,
ich schätze mal, du meinst 500kbps oder ? :D

Mit den Widerständden hast du natürlich recht. Die bilden dann mit den
Kapazitäten der Chipeingänge einen Tiefpaß und verschleifen die Kanten der
Signale. Dadurch kann dann auch teilweise das Timing durcheinanderkommen ;)
Stimmt das so ? :rolleyes:

Man kann ja ein wenig rumprobieren wann es noch sauber funktioniert.

ja natürlich 500kbps und ja das stimmt so. Man muss natürlich mit der Übertragungsrate nicht bis an die Grenzen gehen. Eine langsame Übertragungsrate macht sich hauptsächlich auch nur dann bemerkbar, wenn man Grafikdaten überträgt.

Gruß,
Dirk
 
Hallo, ihr Zwei!

Da ihr hier so munter über die SPI-Schnittstelle diskutiert....

Ich habe für die ersten Tests mit dem ATMega16 nur die Hardware-Schnittstelle benutzt, so wie es von Dirk einmal vorgeschlagen wurde:
Code:
'------------------------------------------------------------------------------
' SPI Definition für das Display
'------------------------------------------------------------------------------
Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = High , Phase = 1 , Clockrate = 128 , Noss = 1

Spiinit

Damit funktioniert es sofort und problemlos!

OK, der Nachteil war, dass ich bei jedem Flashen des AVR`s den Display-Stecker ziehen musste. Dank meines kleinen Adapters, den ich mir schnell auf einer Lochrasterplatine gebaut hatte, war das aber kein Problem.
Adapter.jpg
Ich kann ja auch noch mal ein reales Bild davon einstellen.


Inzwischen entfällt diese Vorsichtsmaßnahme, weil ich auf den ATMega128 umgestiegen bin. ;)
Da dieser Controller andere Pins für das ISP hat, gibt es nun auch keine "Doppelbelegung" der SPI-Schnittstelle mehr. :)

Software-SPI habe ich ehrlich gesagt noch nicht ausprobiert.... wäre aber wohl eine Alternative, wenn man mit kleineren AVR`s weiterarbeiten möchte.

Gruß,
Cassio
 
Hallo an alle!

Wie ihr in den vorherigen Beispielen gesehen habt, benötigt man einige "feste" Variablen (z.B.: X1, Y1, X2, Y2, RD usw.) die in den Subroutinen dafür sorgen, dass auch zur richtigen Zeit die richtigen Daten übermittelt werden.

Hier mal die Config der Variablen dazu:


CodeBox Bascom

'------------------------------------------------------------------------------
' Definition von Variablen für das Display
'------------------------------------------------------------------------------
' Steuerungsvariablen
Dim Cmd As Byte , I As Byte , D As Word

Dim Dspa(5) As String * 3 , Dspwc As Byte

' Positionsvariablen
Dim Position As String * 17
Dim X1 As Byte , Y1 As Byte , X2 As Byte , Y2 As Byte , Fillmode As Byte
Dim X As Word , Y As Word

' Kreisvariablen
Dim Rd As Byte

' Farbvariablen
Dim Farbe As String * 11
Dim Red As Byte , Green As Byte , Blue As Byte

' Imagevariablen
Dim Packageindex As Byte , Itemindex As Word

' Schriftvariablen
Dim Xmax As Byte , Char As Byte , Fontindex As Byte
' Fontvariablen
Dim Eingabe As String * 23 , Zz As Byte , Zeichen As String * 1


Dort ist auch meine Variable für den Text-String zu sehen:
Dim Eingabe As String * 23

Die Variable kann also maximal 23 Zeichen enthalten!
Warum gerade 23?
Durch ein paar Tests habe ich heraus gefunden, dass man mit der kleinen (proportionalen) Schrift maximal 22 (ggf. 23) Zeichen in eine Zeile bekommt.
XV-Lieferung_Test2.jpg
Daher habe ich die Stringvariable "Eingabe" auf 23 Zeichen eingestellt.

In der Subroutine für den Text, wird ja dann der String "Eingabe" in einzelne Zeichen zerlegt und zum Display übertragen.
Dafür sind diese beiden Variablen notwendig:
Dim Zz As Byte
Dim Zeichen As String * 1

Die Variable "Zz" (Zeichenzähler) enthält die Anzahl der Zeichen im aktuell übergeben String.
Die wird mit "Len()" ermittelt:
Code:
Zz = 1 To Len(eingabe)

Die Variable "Zeichen" enthält dann immer nur das jeweils aktuelle Zeichen des Strings.
Dies geschieht durch "Mid()":
Code:
Zeichen = Mid(eingabe , Zz , 1)

Da ja im Displaymodul bereits fertige Fontdateien hinterlegt sind, muss man jetzt nur noch die zugehörige ASCII-Nummer des Zeichens ermitteln, die dann an das Display gesendet wird.
Dies wird mittels "Asc()" realisiert:
Code:
Char = Asc(zeichen)




In meinem Beispiel gibt es ein paar Variablen, die ich jetzt noch nicht weiter erklären möchte.....
Diese sind:
Dim Dspa(5) As String * 3 , Dspwc As Byte
und
Dim Position As String * 17
und
Dim Farbe As String * 11

Wofür ich die benutze, erkläre ich demnächst bald mal.....


Alle anderen Variablen sollten wohl soweit verständlich sein. ;)


Grüße,
Cassio
 
Hallo zusammen!

Wie ich im vorherigen Beitrag schon geschrieben hatte, habe ich mir mehr aus "Bequemlichkeit" einige zusätzliche Subroutinen geschrieben, die mir das Programme schreiben ein wenig erleichtern. ;)

Bestimmte Variablen müssen ja ständig immer wieder mit den aktuellen Daten gefüllt werden, um eine entsprechende Ausgabe am Display zu erhalten.
Wenn ich nun z.B. zwei farbige Rechtecke darstellen möchte, müsste ich bei mir folgenden Programmcode schreiben:
Code:
X1 = 0
Y1 = 0
X2 = 127
Y2 = 79
Fillmode = 1
Red = 15
Green = 0
Blue = 0
Gosub Rahmen


X1 = 0 : Y1 = 80
X2 = 127 : Y2 = 159
Fillmode = 1
Red = 0 : Green = 15 : Blue = 0
Gosub Rahmen


Dieses war mir einfach zu "lang" und ich habe nach einer Möglichkeit gesucht, die Schreibweise zu verkürzen und obendrein noch fertig definierte Farben angeben zu können.
Ich habe mir das also so vorgestellt (nach dem Beispiel von eben):
Position = "0,0,127,79,1"
Farbe = Rot
Gosub Rahmen

Position = "0,80,127,159,1"
Farbe = Gruen
Gosub Rahmen


Damit dies funktioniert, muss ich also erst einmal meine "festen" Farben definieren.
Dies erledige ich über Konstanten:
Code:
'------------------------------------------------------------------------------
' Konstante Farben definieren
'------------------------------------------------------------------------------
'Farbreihenfolge ist immer = "Rot,Grün,Blau"
'Alle Farben können einen Wert von 0-63(bit) besitzen (je höher, je intensiver)

Const Drot = "3,0,0"
Const Rot = "15,0,0"
Const Hrot = "31,0,0"

Const Dgruen = "0,3,0"
Const Gruen = "0,15,0"
Const Hgruen = "0,31,0"

Const Dblau = "0,0,3"
Const Blau = "0,0,15"
Const Hblau = "0,0,31"

Const Dgelb = "7,7,0"
Const Gelb = "15,15,0"

Const Cyan = "0,15,15"
Const Magenta = "15,0,15"

Const Weiss = "15,15,15"
Const Schwarz = "0,0,0"

Soweit..... so gut, dachte ich mir.
Allerdings sind nun die Farbwerte nicht in Bytes angegeben sondern in Form eines Strings. :cool:

Ich muss also in einer Subroutine die Stringvariable wieder in einzelne Bytewerte zerlegen und zuordnen.
Das Konvertieren eines Strings in ein Byte kann mit dem Befehl "val()" realisiert werden.
Allerdings habe ich so gesehen drei Variablen hinter einander, nämlich: "15,0,0" !
Daraus muss dann anschließend wieder: Red = 15 , Green = 0 , Blue = 0 gemacht werden und die dezimalen Zahen sind dann Bytewerte und keine Strings mehr.

Damit dieses "Aufteilen" auch funktioniert, gibt es den Befehl "split()" !
"Split()" kann eine Stringvariable nach vordefinierten Trennzeichen zerlegen und die Teile dann in ein Array speichern.

Aus der Kombination von "val()" und "split()" kann ich nun meine Farbvorgabe "automatisch" in die benöigten Bytes zerlegen und konvertieren.
Code:
   Dspwc = Split(farbe , Dspa(1) , ",")
   Red = Val(dspa(1))
   Green = Val(dspa(2))
   Blue = Val(dspa(3))

Hier kommen nun auch meine beiden Variablen "Dspwc" und "Dspa()" zum Einsatz.
"Dspwc" bedeutet DisplayWordCount
"Dspa()" bedeutet DisplayArray
Die beiden Variablen sind wie folgt dimensioniert:
Code:
Dim Dspa(5) As String * 3 , Dspwc As Byte


Mit dieser Methode kann ich also nun etwas bequemer eine Farbvorgabe im Programm schreiben..... entweder mit festen Farbkonstanten (Farbe = Rot), oder mit selbst definierten Werten (Farbe = "15,0,0"). :)


Ähnlich funktioniert dies bei den Koordinaten zur Positionierung von Grafiken und Text.
Hierüber berichte ich beim nächsten Mal etwas... und wie ich das Ganze noch "verfeinert" habe. ;)

Grüße,
Cassio
 
Hallo Cassio,

das mit den Koordinaten und Farbkonstanten ist eine klasse Idee, das habe ich in meinem Testprogramm gleich mal mit eingebaut. Bin mal gespannt, was du noch für Feinheiten ausgetüftelt hast!
 
Hallo Stefan!

Danke, für die Blumen! ;)
Manchmal hat "Bequemlichkeit" ja auch eine nützliche Seite. :D


In der gleichen Weise, wie ich die Farbwerte mit Strings verarbeite, habe ich es dann auch mit den Koordinaten (und Zusätze) gemacht.
Hierfür werden dann ebenfalls die beiden Variablen verwendet:
Dim Dspa(5) As String * 3 , Dspwc As Byte
und zusätzlich noch die Variable für die Koordinaten (kurz Positionen genannt):
Dim Position As String * 17


Nun aber erst mal ein paar Worte zu den Variablen selbst und der Dimensionierung.
Dspa(5) As String * 3
Bei den Positionen werden maximal fünf Bytes benötigt, um z.B. ein Rechteck zu zeichnen: X1, Y1, X2, Y2, Fillmode !
Das ist auch der Grund, warum das Array Dspa() 5 Bytes aufnehmen kann.
Da jedes Byte im Array einen String von maximal 3 Zeichen aufnehmen muss (X1=100, Y1=120 usw.) wird dies natürlich auch so dimensioniert.


Dspwc As Byte
Ich denke mal, dass ich zur Variable Dspwc nichts weiter schreiben muss.
Hier werden lediglich die Anzahl der Teile in einem String gezählt:
Dspwc = Split(position , Dspa(1) , ",")
....und darum reicht auch ein ganz normales Byte aus. ;)


Dim Position As String * 17
Die Variable "Position" ist natürlich ebenfall ein String, aber warum nun 17 Zeichen lang?
Nehmen wir als Beispiel mal wieder das Rechteck:
X1=100, Y1=100 , X2=127, Y2=159, Fillmode=1
dies würde dann bei mir folgendermaßen aussehen:
Position="100,100,127,159,1"
Wenn man nun mal alle einzelnen Zeichen zusammen zählt, kommt man (incl. der Kommas) auf 17 Zeichen.
Dies ist dann aber auch schon die maximal Angabe an Koordinaten (plus Zusatz) die von der Variable "Position" aufgenommen werden muss.


Aus den oben gewonnenen Infos habe ich mir dann wieder eine Subroutine geschrieben, die den String "Position" in einzelne Bytes zerlegt:
Code:
   Dspwc = Split(position , Dspa(1) , ",")
   X1 = Val(dspa(1))
   Y1 = Val(dspa(2))
   X2 = Val(dspa(3))
   Y2 = Val(dspa(4))
   Fillmode = Val(dspa(5))

Eine Angabe im Programm wie zum Beispiel: Position = "0,0,127,159,1"
wird durch die Subroutine in folgende Bytes zerlegt:
X1 = 0 , Y1 = 0 , X2 = 127 , Y2 = 159 , Fillmode = 1
Wie zu erkennen ist, wird hier eine Fläche über das ganze Display erstellt und durch die Angabe "Fillmode=1" auch gefüllt.


Diese Funktion hatte ich zum Beispiel zu Beginn genutzt um das Display zu "löschen"..... also komplett in schwarz zu füllen.
Dies geht aber dank des Kommandos "&H1B" (ScreenFillRGB) viel einfacher. ;)


Ach so.....
was die Feinheiten betrifft, da komme ich auch noch zu. ;)
Nur mal als Hinweis:
Man kann mit den Stringvariablen "Farbe" oder "Position" nämlich keine automatischen Änderungen übergeben. ;)
Wenn man zum Beispiel einen Punkt über das Display "wandern" lassen möchte, dann kann man dies zwar über eine For-Next-Scheife machen, bekommt aber den (Byte)Wert nicht an die passende Stelle in den String "Position".

Daher folgt dann im nächsten Beitrag die verbesserte Version meiner Subroutinen. ;)

Grüße,
Cassio
 
Hallo !

Bevor ich nun meine Änderung zur Übergabe der String- oder Bytevariablen an die Subroutinen hier einstelle, folgt noch kurz eine Ergänzung zum Thema "Position".


Wenn man mal so durch die Kommandoliste vom Display schaut, dann benötigt man nur eine beschränkte Anzahl von Variablen, um die zugehörigen Daten zu übermitteln.

Diese sind z.B.:
X1
Y1
X2
Y2
Fillmode
Xmax
Rd
X
Y
Packageindex
Itemindex

Aus diesem Grunde nutze ich meine String-Variable "Position" nicht nur zum Darstellen von Rechtecken, Linien, oder ähnliches.

Wenn in der Subroutine "Position" der String in das Array zerlegt wird:
Dspwc = Split(position , Dspa(1) , ",")
...dann ist es egal ob ich fünf Werte durch Komma getrennt übergebe, oder einfach nur drei Werte.
Die letzen beiden fehlenden Werte werden im Array dann nicht befüllt.... und erhalten eine Null.

Diesen Effekt kann man sich natürlich zu nutze machen und den String "Position" für alle Bereiche verwenden. :)

Es müssen in der Subroutine später nur die richtigen Variablen befüllt werden. ;)
Dies habe ich einfach so gelöst:
Code:
   Dspwc = Split(position , Dspa(1) , ",")
   X1 = Val(dspa(1))
   Y1 = Val(dspa(2))
   X2 = Val(dspa(3))
   Y2 = Val(dspa(4))
   Fillmode = Val(dspa(5))
      Xmax = X2
      Rd = X2
      X = X1
      Y = Y1
      Packageindex = X2
      Itemindex = Y2

Dadurch funktionieren zum Beispiel folgende Angaben:

Rahmen und Boxen:
Position = "0,0,127,159,0"
ergibt:
X1=0, Y1=0, X2=127, Y2=159, Fillmode=0

Texte:
Position = "10,20,0"
ergibt:
X=10, Y=20, Xmax=0

Image:
Position = "0,0,0,57"
ergibt:
X=0, Y=0, Packageindex=0, Itemindex=57


Ich hoffe, es ist alles soweit verständlich. :hmmmm:

Gruß,
Cassio
 
Hallo !

Wie nun schon ein paar mal erwähnt sind meine "Bequemlichkeits-Subroutinen" zwar ganz praktisch... haben aber einen gravierenden Nachteil.
Sie funktionieren nur bei "statischen" Werten.

Zur Zeit müsste man also folgendermaßen vorgehen:
Code:
Position = "0,0,127,159,1"
Farbe = Rot
Gosub Farben        'Sub zum Auflösen der Farbvariablen
Gosub Positionen    'Sub zum Auflösen der Koordinaten
Gosub Rahmen       'Sub um einen Rahmen oder Fläche zu zeichnen

Dies ist nicht nur nervig sondern auch etwas uneffektiv.
Außerdem....
Eine kleine For-Next-Schleife, zum akiven Verändern einer Koordinaten-, oder Farbvariable, funktioniert nicht. :eek:

Es wäre also wünschenswert, wenn man einfach nur folgendes schreiben müsste:
Position = "0,0,127,159,1"
Farbe = Rot
Gosub Rahmen 'Sub um einen Rahmen oder Fläche zu zeichnen

Die Subroutine muss dann folgendes prüfen:
-Ob und was für eine Farbvorgabe gemacht wurde (Kostante, String, Byte)?
-Wie wurden die Koordinaten übergeben (String, oder Byte)?


Hierfür habe ich mir dann einen einfachen Trick einfallen lassen.... ;)
Die Stringvariablen "Farbe" und "Position" werden immer mit dem "-" Zeichen vorbelegt.
Die Subroutinen "Farben" und "Positionen" prüfen dann als erstes ob der Trennstrich vorhanden ist.
Sollte dies so sein, dann wird die Subroutine abgebrochen.
Wurden neue "Stringvorgaben" übermittelt, werden diese in einzeln Bytes zerlegt.
Das Ganze sieht dann so aus:
Code:
Farben:

If Farbe = "-" Then
   Return
Else
   Dspwc = Split(farbe , Dspa(1) , ",")
   Red = Val(dspa(1))
   Green = Val(dspa(2))
   Blue = Val(dspa(3))
   Farbe = "-"
End If

Return

und

Code:
Positionen:

If Position = "-" Then
   Return
Else
   Dspwc = Split(position , Dspa(1) , ",")
   X1 = Val(dspa(1))
   Y1 = Val(dspa(2))
   X2 = Val(dspa(3))
   Y2 = Val(dspa(4))
   Fillmode = Val(dspa(5))
      Xmax = X2
      Rd = X2
      X = X1
      Y = Y1
      Packageindex = X2
      Itemindex = Y2
   Position = "-"
End If

Return


In den Subroutinen zur Ansteuerung des Displays werden dann als erstes die beiden o.g. Subs aufgerufen.
Hier mal ein Beispiel:
Code:
Rahmen:
'Box oder Rahmen in RGB

Gosub Farben
Gosub Positionen

  Bitwait Display_busy , Set
  Reset Display_cs                                          ' Chipselect Display Module
  Waitus 2

  I = &H21                                                  ' DrawRectRGB
  Spiout I , 1

  Bitwait Display_busy , Reset
  Spiout X1 , 1                                             ' Send Parameter
  Spiout Y1 , 1
  Spiout X2 , 1
  Spiout Y2 , 1
  Spiout Red , 1
  Spiout Green , 1
  Spiout Blue , 1
  Spiout Fillmode , 1

  Bitwait Display_busy , Set
  Set Display_cs                                            ' Chipselect Display Module
  Waitus 1

Return


Mit dieser einfachen Methode ist es nun auch möglich, problemlos mitten im Programm folgende Anweisungen zu übergeben:
Code:
Position = "50,50,100,100,1"
[B]Farbe = Rot[/B]
Gosub Rahmen

oder

Code:
Position = "50,50,100,100,1"
[B]Farbe = "15,0,0"[/B]
Gosub Rahmen

aber auch:

Code:
Position = "50,50,100,100,1"
[B]Red = Z : Green = 0 : Blue = 0[/B]
Gosub Rahmen


So, dass sollte wohl nun erst mal reichen....
Ich habe zwar inzwischen das Meiste schon wieder erweitert und verbessert (modular aufgebaut), aber das ist ein anderes Thema! ;)

Grüße,
Cassio
 
Hallo,

gut gelöst, Respekt! Ich habe die einzelnen Routinen noch etwas verkleinert, da ja bestimmte Befehle immer wieder vorkommen.
Code:
Bg:                           'Hintergundfarbe
   I = &H15
   Gosub Sendcommand      'Ausgelagerter Code
   Gosub Splitcolor             'Version Cassio: Gosub Farben
   Spiout Red , 1
   Spiout Green , 1
   Spiout Blue , 1
   Gosub Warte_auf_display 'Ausgelagerter Code
Return
Die immer gleichen Teile habe ich in diese Unterprogramme ausgelagert. Das spart etwas Platz im Flash:
Code:
Sendcommand:
   Bitwait Display_busy , Set
   Reset Display_cs
   Waitus 2
   Spiout I , 1
   Bitwait Display_busy , Reset
Return

Warte_auf_display:
   Bitwait Display_busy , Set
   Set Display_cs
   Waitus 1
Return
 
Hallo Stefan!

Ja, das ist natürlich auch eine Möglichkeit. ;)

Ich hatte dies auch schon mal in Betracht gezogen, war mir aber wegen des Timings (zwischendurch zur Sub springen und wieder zurück) nicht ganz sicher.

Obendrein verfolge ich zwischenzeitlich eine andere Vorgehensweise und darum habe ich die Subs erst mal "komplett" gelassen. ;)

Wenn du mit der Variante aber keine Probleme hast, dann arbeite damit doch erst mal weiter.


Gruß,
Cassio
 
Hi Cassio,

super Sache, doch leider muss dieses Display erst mal gaaaanz hinten anstehen, andere "Basteleien" haben Vorrang.


Grüsse und schöne Woche,

Michael
 
Hallo,

btw wärs nicht besser anstatt subroutinen functionen zu nehmen ?
Lies dir mal in der BASCOM-Referenz die Infos beim Befehl STCHECK durch.
Ich werde in meinen Programmen nur noch Subroutinen und globale Variablen
verwenden. Außerdem werde ich den Befehl $NORAMCLEAR einsetzen da man
ja sowieso die Variablen mit Initialwerten besetzen soll kann man sich also die
RAM-Säuberung von BASCOM sparen.

Functions sind in Hochsprachen auf nem PC sicher sehr gut einsetzbar. Aber
nach der Info bei STCHECK werde ich mir den verbratenen RAM-Platz nicht
gönnen der für Functions benötigt wird.

Gruß
Dino
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)