Grafikdisplay mit I2C-Ansteuerung

Simuliertes TRX-Display

Die Einbindung einer BASCOM-GLCD-Library und diverser Fonts zur Ansteuerung eines Grafikdisplays (GLCD) ist recht speicherhungrig, so dass ein für eine bestimmte Anwendung ausgelegter Prozessor schnell an seine Grenzen stößt. Darüber hinaus verlangt ein solches monochromes GLCD einen kompletten Daten-Port (8 bit) und weitere 6 bit eines zweiten AVR-Ports für die Steuersignale, insgesamt also 14 Pins an zwei Ports. Eine Möglichkeit, dieses Problem mit I2C-Portexpandern in BASCOM-AVR zu lösen, war erst einmal nicht zu finden.

Soll zudem, wie am bestehenden Si570-LO mit integriertem 2x16 LCD, die Anzeige weiterer TRX-Daten, z.B. SWR- und S-Meter-Balkenanzeigen, mit einem GLCD erweitert werden, gerät die ganze Angelegenheit voluminöser als erwünscht. Die Frage kam daher auf, ob und wie es möglich ist, das Prozessor-Board von der Anzeige räumlich zu trennen und - als Nebeneffekt - die Software für die TRX-Steuerung und für die Anzeige der TRX-Parameter zu teilen. Nicht mehr einer für alles, sondern alle für einen.

I2C (Inter-Integrated Circuit, gesprochen "I-Quadrat-C" oder englisch "I-Squared-C") ist ein von Philips zunächst zur Steuerung verschiedener Module in Fernsehgeräten entwickelter serieller Datenbus. Aus lizenzrechtlichen Gründen wird der technisch identische Bus bei ATMEL "TWI" (Two Wire Interface) genannt.

Vorgestellt wird ein "Werkzeugkasten" mit parametrierbaren Routinen zum Einbinden in die jeweiligen Anwendungen. Zum Testen sind im Download der Quellcode für ein Master- und ein Slave-Programm hinterlegt. Wer mag, fasst betreffende Routinen in Programmblöcke zusammen und fügt sie per Include in seine Anwendungen ein. Wer sich mit C auskennt, findet bei Nick Gammon in [5] vielleicht eine bessere Lösung (mit einem Portexpander MCP23017).

GLCD Textproben

Abb. 1: GLCD-Testbild

1       Ideensammlung

Im Si570-LO ist schon ein I2C-Bus zur Steuerung des Bandpass- und PA-Tiefpassfilter vorhanden. Es sollte daher keine große Sache sein, alle Anzeigefunktionen über eben diesen Bus auszugeben und einem GLCD zuzuführen. Dazu braucht das GLCD einen eigenen Prozessor (Slave), der die über I2C seriell übermittelten Daten in GLCD-Befehle umsetzt.

Aus der Betrachtung der GLCD-Funktionen wie

  • CLS, CLS Text, CLS Graph
  • LCDAT row, col, text, color
  • LINE (col1, row1) - (col2, row2), color
  • BOX (col1, row1) - (col2, row2), color

lassen sich leicht die Grundanforderungen an das erforderliche I2C-Protokoll ableiten. Erste Feststellung: Die für die einzelnen Befehle zu übermittelnden Datensätze sind unterschiedlich lang. Also muss die Datensatzlänge mit übertragen werden.

Das führte zu folgendem variablen Protokoll, wie die GLCD-Befehle auch englisch, Einzeldaten je 1 Byte:

  1. SlaveAddress
  2. Length
  3. Command 1
  4. Command 2
  5. Data...
  6. ...Data...
SlaveAddress I2C-Adresse des anzusprechenden GLCD-Prozessors
Length Länge des gesamten Protokolls in Bytes (ab Byte Nr. 2)
Command 1 bezeichnet die Befehlsgruppe, z.B. "D" für Displaysteuerung, "G" für Grafik
Command 2 nähere Identifikation eines Befehls innerhalb der Gruppe
Data mehr oder wenige Einzeldaten zu einem Befehl, ggf. auch keine weiteren

Das Protokoll und die gesamte Abwicklung könnten noch erweitert werden, z.B. um eine mit gesendete Checksumme über den gesamten Datensatz, die der Empfänger prüft und bestätigt oder auch nicht; bei Fehlern nachfolgend eine Wiederholung so wie im SNAP-Protokoll. Weiterhin könnte der Master ein Timeout aufsetzen, innerhalb dessen der Slave bestätigen muss, ansonsten auch hier eine Wiederholung durch den Master. Auf diese Finessen wurde zunächst verzichtet, da sich zumindest im Testaufbau der Datenverkehr als reibungslos erwies.

Nun aber: Wie kann das realisiert werden? Genial wären in die jeweiligen Anwendungen einzubindende Libraries mit entsprechenden Calls. Wenn man von AVR-Assembler keinen Schimmer hat, scheidet das schon einmal aus. Für einen Assembler-Dummie wie mich bleibt nur eine Zu-Fuß-Lösung mit BASCOM-AVR. Und siehe da - geht doch, wenn auch vielleicht nicht elegant. Es kommt schließlich darauf an, was dabei hinten herauskommt. Nach längeren Recherchen im Internet ist dann diese Lösung innerhalb von ein paar Tagen entstanden.

Die Testschaltung mit Master, Slave & I2C

Abb. 2: Schaltbild I2C-Kopplung von Master- und Slave-Prozessor

2       Realisierung im Master-Prozessor

Die einfachste I2C-Konfiguration ist die mit einem Master und meist mehreren Slaves. Der Master befiehlt und die Slaves führen aus, so wie sich das gehört. Der Master belegt mit" I2CStart" den Bus und sendet anschließend die Adresse des anzusprechenden Slaves. Der so angesprochene Slave nimmt die folgenden Bytes auf, bis die Befehlsausgabe mit "I2Cstop" beendet wird.

Im Master kann die BASCOM-Standardeinstellung - Software-I2C - verwendet werden. Die Pins für SDA und SCL sind also beliebig wählbar, müssen aber per Config festgelegt werden, z.B.

Config SCL = PortD.1                    'I2C, SCL
Config SDA = PortD.0                    'I2C, SDA

Beide I2C-Leitungen müssen mit je einem Widerstand (ca. 1,8 bis 4,7 kΩ) nach +5V hochgelegt werden (an beliebiger Stelle am Bus, z.B. am Master-Prozessor). Die I2C-Signale werden jeweils durch Tasten des logischen H-Pegels nach logisch L (+5V / 0V) erzeugt, wobei der Master über SCL das Clock-Signal zur Synchronisierung liefert. Neben den zwei Signalleitungen SCL und SDA ist eine dritte Leitung notwendig: die gemeinsame Masse zwischen Master und Slaves.

Die I2C-Kommunikation etwas genauer betrachtet:

  • Der Master prüft, ob SDA und SCL beide auf H-Pegel liegen. Dann ist der Bus frei.
  • Der Master zieht SDA auf L (SCL bleibt auf H). Das ist das I2C-Startsignal, womit sich der Master den Bus reserviert.
  • Der Master schickt ein Byte mit der Slave-Adresse auf den Bus.
  • Fühlt sich ein Slave mit der Adresse angesprochen (es können mehrere Slaves am Bus horchen), zieht dieser SDA auf L, was der Master als Bestätigung (ACK = Acknoledge) dafür auffasst, dass ein Slave unter dieser Adresse ansprechbar ist.
  • Nun kann der Master seine Datenfracht loswerden, die er Byte für Byte auf den Bus gibt.
  • Nach jedem Byte quittiert der Slave mit einem ACK (wie oben: SDA auf Low).
  • Unterbleibt das L-Signal nach einem gesendeten Byte auf der SDA-Leitung, hat es kein ACK gegeben. Der Master deutet dies als NAK (Not acknoledged).
  • Zum Ende der Übertragung schaltet der Master mit einem I2C-STOP-Signal den Bus wieder auf den Anfangszustand, SDA und SCL auf logisch H (Bus ist frei).

Im oben skizzierten Protokoll werden alle Daten eines Befehls in einem Block gesendet, eingerahmt durch " I2CStart" (Bus belegen) und "I2Cstop" (Bus wieder freigeben).

Beispiele für I2C-Protokolle:

CLS (Text- und Grafik-Display löschen):

bytGD_cmd1 = 68                         'ASCII "D", Display command
bytGD_cmd2 = 2                          'Cls command, clear all
bytGD_Len = 3                           'Total length in bytes
I2CStart
   I2CwByte bytGD_Addr                  'Write I2C address
   I2CwByte bytGD_Len                   '1: Message length to follow
   I2CwByte bytGD_cmd1                  '2: Display command
   I2CwByte bytGD_cmd2                  '3: Cls command
I2Cstop

Das längste Protokoll für LCDAT (Text 'strPrint' schreiben):

bytGD_cmd1 = 67                         'ASCII "C", Character command
bytGD_cmd2 = 2                          'Print string command
bytLen = Len(strPrint)                  'Length of string
bytGD_Len = bytLen + 6                  'Total length in bytes
I2CStart
   I2CwByte bytGD_Addr                  'Write I2C address
   I2CwByte bytGD_Len                   '1: Message length
   I2CwByte bytGD_cmd1                  '2: Character command
   I2CwByte bytGD_cmd2                  '3: Print command
   I2CwByte bytRow                      '4: Row to print
   I2CwByte bytCol                      '5: Column to print
   I2CwByte bytColor                    '6: Print color
   For i = 1 To bytLen                  '7... data
      strChar1 = Mid(strPrint , i , 1)  'single character
      j = Asc(strChar1)                 'ASCII code of character
      I2CwByte j                        'Write ASCII code
   Next i
I2Cstop

Eleganter ginge die String-Manipulation (Einzelzeichen mit "Mid" aus strPrint herausziehen) mit dem Overlay eines Byte-Arrays über strPrint.

Für's Erste wurden folgende Funktionen im Master realisiert, jeweils mit einer Routine "GLCD_XXX":

GLCD_INIT "INITLCD" Display initialisieren
GCLD_CLS "CLS"  Grafik- und Textdisplay löschen
GCLD_CLSText "CLS Text" Textdisplay löschen
GCLD_CLSGraph "CLS Graph" Grafikdisplay löschen
GLCD_SETFONT "Setfont" Text-Font setzen
GLCD_LCDAT "LCDAT" Text anzeigen
GLCD_PSET "PSET"  Pixel zeichnen/löschen
GLCD_LINE "LINE"  Linie zeichnen/löschen
GLCD_BOX "BOX" Box zeichnen/löschen
GLCD_BOXFILL "BOXFILL" Gefüllte Box zeichnen/löschen
GLCD_CIRCLE '"CIRCLE" Kreis zeichnen/löschen

Sie werden im Master mit einem Call mit zugehörigen Parametern aufgerufen, z.B.
Call GLCD_LINE(col1, row1, col2, row2, color)
für einen Grafikbefehl
LINE(col1, row1) - (col2, row2), color.

Reihenfolge und Bedeutung der Routinen-Call-Parameter und der entsprechenden Grafikbefehle stimmen grundsätzlich überein.

Bis hierher ist von einem speziellen GLCD noch nicht die Rede. Routinen und I2C-Protokoll sind also unabhängig von der Auswahl eines bestimmten Displays, dabei angenommen, dass die für die jeweiligen Grafikfunktionen zu übermittelnden Daten die richtigen sind. Die Festlegung auf ein bestimmtes Grafikdisplay erfolgt erst im Slave-Prozessor.

3       Realisierung im Slave-Prozessor

Der am I2C-Bus angeschlossene Slave-Prozessor ist mit einem Grafikdisplay ausgestattet. Hier muss daher die Software zum GLCD passen. Um mögliche Anpassungen möglichst einfach zu gestalten, sind drei Programmblöcke zu betrachten.

3.1   Vereinbarungen im Hauptprogramm

Die für das GLCD passende  BASCOM-Library ist per "$lib..." einzubinden,
hier für das TG12864B-03 von pollin.de (KS0108-kompatibel):

$lib "glcdKS108.lib"                    'GLCD KS0108 library

Die Lib ist in der BASCOM-Installation abgelegt, bei WinXP zumeist in
C:\Programme\MCS-Electronics\BASCOM-AVR\LIB.
Die Anschlussbelegung ist per "Config Graphlcd..." festzulegen, hier (siehe Schaltbild in Abb. 2):

Config Graphlcd = 128 * 64sed , Dataport = PortA , Controlport = PortC , Reset = 2 , Ce = 3 , Ce2 = 4 , Enable = 5 , Rd = 6 , Cd = 7

Der Dataport ist 8 bits breit, beansprucht also einen kompletten AVR-Port, hier PortA. Für den Controlport sind 6 Pins eines zweiten Ports erforderlich, hier PortC.2 bis PortC.7. Die beiden TWI- (I2C-)Pins SDA und SCL müssen für den Anschluss an den I2C-Bus vorgesehen werden (Hardware-TWI mit/ohne Interrupt-Steuerung). Am verwendeten ATmega16 sind dies PortC.0 und PortC.1. Ein "Config" auf diese 2 Pins ist nicht notwendig. Auch wird die "i2c_twi.lib" nicht benötigt. Die I2C-Adresse, über die der GLCD-Slave-Prozessor angesprochen wird, ist der Variablen bytGD_Addr zugewiesen, hier, passend zum Si570-LO, mit der Adresse 74 hex. Für den Fall, dass das Display keine Reaktion auf die Master-Befehle zeigt, kann für Debug-Zwecke die Anzeige der empfangenen Master-Befehle in Zeile 8 des Displays mit "TWI_Debug=1" eingeschaltet werden. Sonst "=0".

Schlamperei! Habe im Quellcode von GLCDSlave_101 vergessen, die Fuse-Bit-Einstellungen zu vermerken. Sind die gleichen wie in GLCDMaster_101, siehe dort.

3.2   Die I2C-/TWI-Protokollabwicklung

Es sind grundsätzlich zwei Möglichkeiten gegeben, wie der Slave den I2C-Bus abhört und auf Master-Befehle reagiert:
(1) Mit ständigem Polling der TWI-Register innerhalb der Do...Loop
(2) Mit Auslösen eines Interrupts durch ein I2CStart-Signal.

M. Ruhwald bietet in [1] beide Möglichkeiten, die ich zunächst für meine Zwecke angepasst habe. Da für mich die Interrupt-Steuerung die elegantere Lösung war, habe ich diese zunächst versucht und einige Stunden damit verbracht, sie zum Laufen zu bringen. CLS und die Textfunktion (LCDAT) waren kein Problem. Sobald aber eine Grafikfunktion, z.B. LINE, dazu kam, hat diese nur noch Pixelsalat erzeugt. Und das nachhaltig. Folgende Textanzeigen hatten Umbrüche zwischen den beiden Displayhälften. Es sah wüst aus.
Was auch immer der Grund war, das simple Polling brachte den Durchbruch. Dieses fragt das Interrupt-Bit TWINT im TWI-Kontrollregister TWCR ab und reagiert auf den Wert "1".

Zu Anfang muss der Slave mit Wertezuordnung der TWI-Register initialisiert werden, u.a. auch mit der zugewiesenen Slave-Adresse " bytGD_Addr" (hier 74 hex).

Call TWI_slave_init                     'Initialize TWI

Innerhalb der Do...Loop wird nun die Polling-Routine "TWI_GetData" aufgerufen, die das TWCR-Register auswertet. Ist das Interrupt-Bit TWINT = 1, ist ein auszuwertender Master-Befehl gekommen. Es wird geprüft, ob der GLCD-Prozessor (Adresse "bytGD_Addr") angesprochen ist. Wenn er feststellt, dass er gemeint ist, werden die nachfolgenden Bytes des I2C-Protokolls in den Empfangspuffer "bytTWI_Buf" gelesen, bis die mitgelieferte Protokolllänge erreicht ist. Dieser Programmteil ist unabhängig vom verwendeten GLCD, bedarf also keiner Anpassung aufgrund der jeweiligen Hardware-Konfiguration. Dank an Michael Ruhwald, mitchsoft.de [1], von dem ich die Idee übernommen und für meine Zwecke angepasst habe. Um überhaupt zu verstehen, wie mit den Bits in den TWI-Registern getrickst wurde, habe ich die in hex angegebenen Registerwerte in die Binärform umgeschrieben. Erklärungen dazu in [2]. Kann ja nicht schaden zu verstehen, was da passiert.

3.3   Umsetzung des I2C-/TWI-Protokolls in GLCD-Befehle

Nach Einlesen des I2C-Protokollsatzes wird die Auswerteroutine "TWI_ShowData" aufgerufen. Hier werden das Protokoll ausgewertet und entsprechend der " Command 1", " Command 2" und der zugehörigen Daten die GLCD-Befehle aufgesetzt.

Zunächst werden die allen Befehlen gemeinsamen ersten drei Bytes aus dem Empfangspuffer "bytTWI_Buf" interpretiert:

bytGD_Len = bytTWI_Buf(1)               'Number of bytes
bytGD_Cmd1 = bytTWI_Buf(2)              'Command 1
bytGD_Cmd2 = bytTWI_Buf(3)              'Command 2

Entsprechend Command 1 erfolgt eine Verzweigung.

Obige Beispiele: "CLS"

'Display set commands, "D", ASCII 68
If bytGD_Cmd1 = 68 Then                 'Display set commands
   Select case bytGD_Cmd2
       Case 1                           'Init GLCD
           InitLCD
       Case 2                           'Clear GLCD, text & graph
           Cls       
       Case 3                           'Clear Text
           Cls Text
       Case 4                           'Clear Graphics
           Cls Graph
       Case Else                        'Unknown command 2
          bytTWI_Err = 20
   End Select
End If

... und "LCDAT"

'Charcter commands, "C", ASCII 67
If bytGD_Cmd1 = 67 Then                 'Character display commands
      Select Case bytGD_Cmd2
         Case 1                         'SetFont commands
            .....         
         Case 2                         'Display a string "LCdat"
            bytGD_Row0 = bytTWI_Buf(4)  'Display row
            bytGD_Col0 = bytTWI_Buf(5)  'Display column
            bytGD_Color = bytTWI_Buf(6) 'Display color
            strGD_Strg = ""
            For i = 7 To bytGD_Len      'Create string
                j = bytTWI_Buf(i)       'ASCII code
                strChar = Chr(j)        'converted to character
                strGD_Strg = strGD_Strg + strChar  'make string
            Next i
            Lcdat bytGD_Row0 , bytGD_Col0 , strGD_Strg , bytGD_Color
         Case Else
            bytTWI_Err = 21             'unknown command 2
      End SELECT
   End If

Möglicherweise sind hier je nach verwendetem GLCD und der zugehörigen Library Anpassungen an den blau gekennzeichneten Befehlen erforderlich.

Fonts für die Textdarstellung

Eine Übergabe von Fontnamen über Variable im Befehl " Setfont xxx", "xxx" als Variable, funktioniert nicht. Daher wurden 3 feste Fonts ausgewählt und explizit in den Setfont-Befehlen aufgeführt ("font16x16", "font8x8", "font6x8"). Hier sind ggf. Anpassungen erforderlich. Die Fonts müssen im Hauptprogramm hinter dem End-Statement dem BASCOM-Compiler bekannt gemacht werden, z.B. mit $include "font16x16.font", und im Verzeichnis der .bas-Datei gespeichert sein.

Trotz der in diversen Internetforen verlautbarten Probleme erwies sich der Anschluss des Pollin-GLCD TG12864B -03 (128x64 Pixel, KS0108-kompatibel) als fast problemlos. Bei meinem Exemplar stimmen allerdings folgende Anschlussbezeichnungen nicht:
CS1 liegt an pin 16 (nicht an der Beschriftung pin 15), CS2 liegt an pin 15 (nicht an der Beschriftung pin 16), beide vertauscht.
LED+ liegt an pin 20 (nicht an der Beschriftung pin 19), LED- liegt an pin 19 (nicht an der Beschriftung pin 20), beide vertauscht

Wenn also beide Bildhälften bei Anschluss gemäß Beschriftung vertauscht erscheinen, CS1 und CS2 vertauschen, am einfachsten im o.g. "Config Graphlcd...". Wenn die Hintergrundbeleuchtung nicht geht, LED+ und LED- vertauschen. Bei Anschluss von LED+ über 47 Ohm an +5V, LED- an Masse, sind die Ausleuchtung zufriedenstellend und der Stromverbrauch noch mäßig.

4       Die Master-Befehle im Einzelnen

Die GLCD-Parameter werden in den Subroutinen über die Parameterliste "Call Sub(Par1, Par2, ...)" in der gleichen Reihenfolge und Bedeutung wie in den LCD-Befehlen des Displays übergeben. Alle Parameter sind mit "byVal" erklärt, Datentyp Byte. Die Übergabe kann also mit Konstanten oder Variablen erfolgen. Die nicht in Parameterlisten übergebenen Variablen sind im Hauptprogramm erklärt:

Dim bytGD_Addr As Byte                 'I2C-Address
Dim bytGD_Len As Byte                  'Message length
Dim bytGD_Cmd1 As Byte                 'Command 1
Dim bytGD_Cmd2 As Byte                 'Command 2

Die Variablen zum Aufsetzen der GLCD-Befehle (bytGD_Addr, bytGD_Len, bytGD_Cmd1, bytGD_Cmd2) werden in den einzelnen Routinen gesetzt, erscheinen also nicht als Call-Parameter.

GCLD_INIT        "InitLCD"       LCD initialisieren
GCLD_CLS         "CLS"           Grafik- und Textdisplay löschen
GCLD_CLSText     "CLS Text"      Textdisplay löschen
GCLD_CLSGraph    "CLS Graph"     Grafikdisplay löschen

Diese 4 Routinen: Call ohne Parameter.

GLCD_SETFONT    "Set font"      Text-Font setzen

'Call GLCD_SetFont(Font-Nr. = 1...3)
Call GLCD_SetFont(2)

Setze Font auf den zweiten aus den möglichen 3 ("font16x16", "font8x8", "font6x8").

GLCD_LCDAT      "LCDAT"         Text anzeigen

'Call GLCD_LCDAT(Row1, Col1, Text , Color)
Call GLCD_LCDAT(2, 50, ">>> Test <<<", 0)

">>> Test <<<" in Zeile 2 (1...8) und Spalte 50 (0...127) schreiben.
"Color" = 0 heißt "normale" Textdarstellung, =1: invers.

Etwas verwirrend: Die Zeilennummerierung weicht vom Grafikmodus ab. Grafik: Zeilen 0...63 für ein 128x64 Pixel-Display.
Im Textmodus zählen die Zeilen von 1 bis 8, wobei der 16x16-Font zwei Zeilen füllt, also für "Row1" die Werte 1...8. Die Spalten "Col1" zählen von 0 bis 127.
Möglicherweise ein Fehler im Grafik-Controller meines Displays: Bei Anzeigen von Texten ab Spalte 0 wird die Textzeile in der rechten Displayhälfte um eine Pixelzeile nach unten verschoben dargestellt.
Für die Textdarstellung mit "LCDAT" ist der erste Parameter ist die Zeile, der zweite die Spalte.
Bei den nachfolgenden Grafikbefehlen ist es umgekehrt, zuerst Spalte, dann Zeile.

Je nach vorher eingestelltem Font sind mehr oder weniger Zeichen in einer Zeile darstellbar,
Font 16x16:   8 Zeichen (16 Pixel x 8 Zeichen = 128)
Font   8x  8: 16 Zeichen (8 Pixel x 16 Zeichen = 128)
Font   6x  8: 21 Zeichen (6 Pixel x 21 Zeichen = 126, 2 Pixel übrig)

GLCD_PSET       "PSET"             Pixel zeichnen/löschen

'Call GLCD_PSET(Col1, Row1, Color)
Call GLCD_PSET(50, 20, 1)

Pixel in Spalte 50 (0...127) und Zeile 20 (0...63) malen.
Color-Parameter ist die Pixelfarbe,"1" = Pixel malen, "0" = Pixel löschen.

GLCD_LINE       "LINE"                Linie zeichnen/löschen

'Call GLCD_LINE(Col1, Row1, Col2, Row2, Color)
Call GLCD_LINE(0, 0, 127, 0, 1)

Waagerechte Linie am oberen Rand (Row=0) von Spalte 0 bis 127 malen.
Color-Parameter ist die Linienfarbe,"1" = Linie malen, "0" = Linie löschen.

GLCD_BOX            "BOX"           Box zeichnen/löschen
GLCD_BOXFILL    "BOXFILL"    Gefüllte Box zeichnen/löschen

'Call GLCD_BOX(Col1, Row1, Col2, Row2, Color)
Call GLCD_BOX(0, 35, 100, 40, 1)

Identisch für BOXFILL.
Rechteck (Box, leer oder gefüllt) zwischen Zeilen 35/40 und Spalten 0/100 malen.
Color-Parameter ist die Boxfarbe,"1" = Box malen, "0" = Box löschen.

Macht man Col2 als berechnete Größe variabel, ist ein SWR- oder S-Meter schon fast fertig. Im Masterprogramm ist ein Testbeispiel programmiert (siehe das Bild zu Anfang).

GLCD_CIRCLE      '"CIRCLE"     "Kreis zeichnen/löschen

'Call GLCD_CIRCLE(Col1, Row1, Rad, Color)
Call GLCD_CIRCLE(63, 31, 30, 1)

Male einen Kreis um den Mittelpunkt (63, 31) mit Radius 30.
Color-Parameter ist die Kreisfarbe,"1" = Kreis malen, "0" = Kreis löschen.

5       Nachtrag (18.03.2012)

Keine Grafikfunktion im eigentlichen Sinne, aber die fehlte doch noch:
Das selektive Löschen einer Textzeile.

GLCD_DelTextRow

'Call GLCD_DelTextRow(Row, Col)
Call GLCD_DelTextRow(5, 21)

Lösche Textzeile 5, 21 Textzeichen (Zeile von 1...8, Zeichen von 8...21).

Als Zeichenanzahl ist die zuletzt mit GLCD_SETFONT vorgenommene Fontauswahl maßgebend, unabhängig von der Zeichengröße der zu löschenden Zeile. Im o.g. Beispiel wurde der Font zuletzt auf 6x8 Pixel gesetzt, daher 21 Zeichen. Soll in diesem Fall z.B. eine Zeile mit 16x16 Pixel gelöscht werden, muss der Befehl zweimal ausgeführt werden, da 16x16 zwei Zeilen belegt. Die Erweiterung ist im Download abgelegt, Version 1.01.

Zugegeben, der Weg zur Fertigstellung dieses kleinen Projekts kam mal wieder nicht ganz ohne Umwege und Fehler aus. Unwägbarkeiten können u.a. sowohl in der richtigen Ansteuerung des GLCD als auch in der I2C-Kommunikation liegen. Hier war es insbesondere die fruchtlose Auseinandersetzung mit dem TWI-Interrupt. Um Anschluss und Funktion des GLCD am Prozessor zunächst zu prüfen, ist im Download auch ein kleines GLCD-Testprogramm beigefügt, das hier ganz am Anfang stand, bevor es an die I2C-Steuerung ging. Es benutzt die für die spätere I2C-Kopplung identische Anschlussbelegung.

Wenn immer ich eine Frage zur AVR-Programmierung hatte, war Michael, DL1DMW [3], stets zur Stelle. Auch Klaus, DJ7OO [4], gab bereitwillig Hilfestellung bei meinen ersten Überlegungen. Beiden meinen herzlichen Dank dafür.

Referenzen

Hinweis vom 14.12.2012: Der Server www.mitchsoft.de ist momentan nicht zu erreichen. Vielleicht kommt er ja wieder.

[1] http://www.mitchsoft.de/Elektronik/AVR/index.html
[2] http://www.rn-wissen.de/index.php/TWI
      http://www.rn-wissen.de/index.php/TWI_Praxis
[3] http://www.amateurfunkbasteln.de/
[4] http://www.kh-gps.de/
[5] http://www.gammon.com.au/forum/?id=10940

 

Einordung: