Hallo!
In diesem Beitrag möchte ich darüber berichten wie man LCDs (Liquid Crystal Displays) mit Bascom ansteuert. Damit meine ich die ein- oder mehrzeiligen Textdisplays (alphanumerisch), nicht die Grafikdisplays. Die Grafikdisplays sind etwas schwieriger zu handhaben und sind vielleicht mal Thema eines anderen Beitrags.
Gleich vorab. Eigentlich ist es sehr einfach. Man sucht in der Bascom-Hilfe nach "LCD", liest sich alles durch, schließt das LCD an und fertig. Alles was ich noch bieten kann, ist ein kleiner Bericht der aufzeigt wie ich es gemacht habe und vielleicht noch eine kleine Auflistung der wichtigsten LCD-Befehle.
Viele Text-LCDs verwenden den LCD-Controller HD44780. Diese und alle kompatiblen Displays werden von Bascom voll unterstützt. Solche LCDs bekommt man ziemlich günstig bei Pollin. Wenn man dort im Shop nach "Industriestandard" sucht, dann findet man ein paar wirklich günstige LCDs, die mit Bascom funktionieren sollten.
Gängige LCD-Controller:
Es gibt zwei Möglichkeiten wie Bascom ein LCD ansteuert. Entweder über einen Datenbus (BUS-Modus) oder über auswählbare Pins eines Ports (PORT-Modus). Der BUS-Modus ist nur dann möglich, wenn man z.B. auch einen externen Speicher an den AVR-µC anhängen kann (Bus Interface). Dann teilen sich der externe Speicherbaustein und das LCD die Leitungen. Der ATmega8 hat keinen solchen Bus. Für uns ist nur der PORT-Modus interessant. Im PORT-Modus können wir selber bestimmen an welchen Pins das LCD hängt. Dafür braucht dieser Modus aber auch etwas mehr Programmspeicher im µC.
Die Daten können an das LCD über 8 oder 4 µC-Pins übermittelt werden (8-Bit Modus bzw. 4-Bit Modus). Der 8-Bit Modus ist ein wenig schneller. Dafür werden im 4-Bit Modus nicht so viele µC-Pins belegt.
Die LCDs mit HD44780-Controller stellen normalerweise diese Anschlüsse bereit:
01 -- GND (VSS)
02 -- 5 V (VCC oder VDD)
03 -- Kontrast (VO oder VEE)
04 -- RS (Register Select)
05 -- R/W (Read/Write)
06 -- E (Enable)
07 -- D0 (Datenbit 0, im 4-Bit Modus nach GND schalten)
08 -- D1 (Datenbit 1, im 4-Bit Modus nach GND schalten)
09 -- D2 (Datenbit 2, im 4-Bit Modus nach GND schalten)
10 -- D3 (Datenbit 3, im 4-Bit Modus nach GND schalten)
11 -- D4 (Datenbit 4)
12 -- D5 (Datenbit 5)
13 -- D6 (Datenbit 6)
14 -- D7 (Datenbit 7)
15 -- evt. Hintergrundbeleuchtung, siehe Datenblatt
16 -- evt. Hintergrundbeleuchtung, siehe Datenblatt
Anschluss an den ATmega8:
LCD-Pin 1 (VSS) --> GND
LCD-Pin 2 (VDD) --> 5 V Versorgungsspannung
LCD-Pin 3 (Kontrast) --> z.B. Poti/Trimmer für Kontrasteinstellung
LCD-Pin 4 (RS) --> an einen Pin des ATmega8 (z.B. PORTD.2)
LCD-Pin 5 (R/W) --> GND
LCD-Pin 6 (E) --> an einen Pin des ATmega8 (z.B. PORTD.3)
LCD-Pin 7 (D0) --> im 4-Bit Modus nach GND schalten
LCD-Pin 8 (D1) --> im 4-Bit Modus nach GND schalten
LCD-Pin 9 (D2) --> im 4-Bit Modus nach GND schalten
LCD-Pin 10 (D3) --> im 4-Bit Modus nach GND schalten
LCD-Pin 11 (D4) --> an einen Pin des ATmega8 (z.B. PORTD.4)
LCD-Pin 12 (D5) --> an einen Pin des ATmega8 (z.B. PORTD.5)
LCD-Pin 13 (D6) --> an einen Pin des ATmega8 (z.B. PORTD.6)
LCD-Pin 14 (D7) --> an einen Pin des ATmega8 (z.B. PORTD.7)
LCD-Pin 15 (HG-Bel.) --> siehe Datenblatt
LCD-Pin 16 (HG-Bel.) --> siehe Datenblatt
Leider gibt es große Unterschiede zwischen den Displays, was die Temperaturabhängigkeit betrifft. LCDs für Normaltemperaturen arbeiten meist mit einer positiven Spannung am VO-Pin (Kontrast). Und Displays mit erweitertem Temperaturbereich oder große Displays, brauchen meist eine negative Spannung am VO-Pin. Leider findet man gerade bei Billig-LCDs erst beim Anschließen heraus, mit welcher Spannung der VO-Pin versorgt werden muss.
Ziemlich gute Informationen bekommt man unter http://www.sprut.de/electronic/lcd/index.htm. Also wenn dein Display nicht so funktioniert wie es funktionieren sollte, dann lohnt es sich, dort mal vorbei zu schauen und sich geballtes Wissen über die LCDs rein zu ziehen. Und zum Erstellen der evt. benötigten negativen Spannung, hat sprut.de auch etwas zu sagen: http://www.sprut.de/electronic/switch/minus.html
Das Problem mit der negativen Spannung umgeht man am einfachsten, mit einem neuen LCD. ;-) Für meine ersten Tests verwende ich das bei Pollin gekaufte "Powertip PC 1602-F". Leider ist Pollin nicht gerade verlässlich, was die Verfügbarkeit der Produkte betrifft. Es kann also leicht sein, dass dieses LCD nicht erhältlich ist wenn du bei Pollin danach suchst.
Die normalen LCD-Routinen von Bascom nutzen den R/W-Pin nicht. Es wird einfach lange genug gewartet, so dass Bascom das LCD nicht auslesen muss. Die Mindestwartezeiten sind im HD44780-Datenblatt aufgeführt. Das funktioniert ziemlich gut.
Der R/W-Pin muss nur dann beschaltet werden, wenn man in Bascom die LCD-Routinen einer Zusatz-Library, wie z.B. die LCD4BUSY-Library, nutzt. Das bringt's aber nur, wenn das LCD sehr schnell reagieren soll. Z.B. wenn sich die Anzeige nicht nur alle Sekunden, sondern im Millisekundenbereich ändern soll. Dann könnte es auch sehr langsame LCDs geben, die sich nicht an das ausgemachte Timing halten. Dann kann man den R/W-Pin in Verbindung mit der LCD4BUSY-Library ebenfalls nutzen.
Aber im Normalbetrieb und so lange es keine Probleme damit gibt, ist es nicht notwendig den R/W-Pin an den µC anzuschließen. Zumindest nicht, wenn man Bascom nutzt.
Die Ansteuerung eines LCD läuft unter Bascom ähnlich einfach wie die Ausgabe von Text mit dem Befehl PRINT
. Statt mit PRINT
an die UART, schickt man den Text mit dem Befehl LCD
an das Display. Zusätzlich gibt es noch ein paar Befehle um den Cursor auf dem Display zu positionieren und das Display zu löschen. Aber viel mehr ist nicht dahinter. Das Schwierigste an der Sache ist, das Display richtig anzuschließen und in Bascom richtig zu konfigurieren.
Zum Konfigurieren des LCD stellt Bascom ein paar Befehle zur Verfügung. Da für uns nur der PORT-Modus interessant ist, gehe ich nicht näher auf die Befehle für den BUS-Modus ein. Wenn man nicht toll herumkonfiguriert, dann nimmt Bascom an, dass wir das LCD im 4-Bit PORT-Modus ansprechen möchten.
Mit diesem Befehl wird Bascom mitgeteilt, welche Pins zur Ansteuerung des LCDs verwendet werden. Das würde für den oben gezeigten Schaltplan so aussehen:
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , _
Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Die Hilfe zu diesem Befehl findet man hier: http://avrhelp.mcselec.com/index.html?config_lcdpin.htm
Damit gibt man den Typ des Displays an. Gemeint ist die Anzahl an Zeilen und Spalten. Mögliche Einstellungen sind:
Weiters kann man mit diesem Befehl auch die Verwendung eines anderen Chipsatzes einstellen. Neben dem Standard (HD44780) kann man noch zwischen "KS077" und "DOGM" wählen. Nähere Infos stehen in der Hilfe zu diesem Befehl.
Beispiel:
Config Lcd = 16 * 2
Die Hilfe zu diesem Befehl findet man hier: http://avrhelp.mcselec.com/index.html?config_lcd.htm
Die Anzeige des LCD bestimmen hauptsächlich die vier Befehle CURSOR
, CLS
, LOCATE
und LCD
. Es gibt noch weitere LCD-Befehle wie z.B. HOME
, SHIFTLCD
, SHIFTCURSOR
, DISPLAY
und INITLCD
. Nähere Infos darüber findest du in der Bascom-Hilfe. Weiters sollte man wissen, dass die Ausgabe auf ein LCD ziemlich langsam ist und deshalb der Befehl LCD
nicht in einem Interrupt-Handler eingesetzt werden sollte.
Mit diesem Befehl stellt man das Verhalten des Cursors ein. Der Cursor ist bei LCDs meist ein Unterstrich. Diesen kann man ein-/ausschalten und blinken lassen.
Beispiel:
CURSOR OFF
CURSOR ON BLINK
Die Hilfe zu diesem Befehl findet man hier: http://avrhelp.mcselec.com/index.html?cursor.htm
CLS
löscht das Display und setzt den Cursor in die linke, obere Ecke.
Die Hilfe zu diesem Befehl findet man hier: http://avrhelp.mcselec.com/index.html?cls.htm
LOCATE
setzt den Cursor in die angegebene Zeile und Spalte.
Beispiel:
LOCATE 1, 1 ' Zeile 1 Spalte 1
LOCATE 2, 10 ' Zeile 2 Spalte 10
Statt LOCATE 1, 1
könnte man auch den Befehl HOME
verwenden.
Die Hilfe zu diesem Befehl findet man hier: http://avrhelp.mcselec.com/index.html?locate.htm
Dieser Befehl initialisiert das Display. INITLCD
braucht man im Normalfall nicht, da Bascom das Display automatisch beim Start initialisiert. Aber INITLCD
bietet sich an, um zwischendurch das Display zurück zu setzen, falls etwas (z.B. ein Relais) die Displayausgabe gestört hat. Das Initialisieren dauert ein wenig und sieht manchmal auch nicht besonders gut aus. Deshalb sollte man es nicht übertreiben und das Display nur nur im Notfall alle paar Minuten und im Normalfall nur alle paar Stunden neu initialisieren. Wie oft du INITLCD
wirklich einsetzt, musst du natürlich selber entscheiden. Wenn Störungen öfter auftreten, dann solltest du dir vielleicht lieber Gedanken über eine bessere Entstörung der Schaltung machen.
Die Hilfe zu diesem Befehl findet man hier: http://avrhelp.mcselec.com/index.html?initlcd.htm
Mit diesem Befehl schreibt man auf das Display. LCD
verhält sich sehr ähnlich dem PRINT
-Befehl und kann meist genau so eingesetzt werden. Statt mit PRINT
auf die UART, schreibt man mit LCD
auf das Display.
Beispiel:
CLS
LCD "Zeile 1"
LOCATE 2, 1
LCD "Zeile 2!
Die Hilfe zu diesem Befehl findet man hier: http://avrhelp.mcselec.com/index.html?lcd_2.htm
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 100
$swstack = 100
$framesize = 100
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , _
Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 16 * 2
Cls
Locate 1 , 1
Lcd "Hallo Welt"
End
Die Erklärungen stehen im Quellcode.
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 100
$swstack = 100
$framesize = 100
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , _
Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 16 * 2
Cursor Off
Dim Initcounter As Byte
Dim Bt As Byte
Dim S As String * 2
Do
For Initcounter = 1 To 36
'LCD löschen
Cls
'Haupttext der ersten Zeile anzeigen
Locate 1 , 1
Lcd "Hallo Welt...."
'Haupttext der zweiten Zeile anzeigen
Locate 2 , 1
Lcd "Servus LCD...."
'Jede Sekunde um 1 hochzählen und neuen Wert anzeigen
For Bt = 1 To 99
'Neuen Wert in einen Text umwandeln
S = Str(bt)
S = Format(s , "00")
'Neuen Wert in der ersten Zeile ab Spalte 15 anzeigen
Locate 1 , 15
Lcd S
'Neuen Wert in der zweiten Zeile ab Spalte 15 anzeigen
Locate 2 , 15
Lcd S
'Eine Sekunde warten
Wait 1
Next Bt
'Das LCD nach ca. einer Stunden neu initialisieren
If Initcounter = 36 Then
Initlcd
End If
Next Initcounter
Loop
End
Der Haupttext wird jede Minute neu geschrieben. Die Zahl wird jede Sekunde neu geschrieben. Es wird also nicht jede Sekunde alles neu geschrieben, sondern nur der sich ändernde Bereich (die Zahl). Würde man jede Sekunde das ganze Display löschen und neu beschreiben, dann würde die Anzeige unangenehm flackern.
mfg Gerold :-)
Den zugehörigen Original-Beitrag findest du im Loetstelle-Forum.
Ich programmiere Progressive Web Applications, Mobile Apps, Desktop-Programme und noch vieles mehr. Falls es dich interessiert, findest du mehr Informationen darüber auf meiner Business-Website.