(LCD 4Bit Mode mit Busy Abfrage) |
Crowdy (Diskussion | Beiträge) (→4-Bit Ansteuerung mit Busy(I/O Mode)) |
||
(31 dazwischenliegende Versionen von 15 Benutzern werden nicht angezeigt) | |||
Zeile 3: | Zeile 3: | ||
==Einleitung== | ==Einleitung== | ||
− | LCD ist eine Abkürzung und bedeutet '''''L'''iquid '''C'''rystal '''D'''isplay''. Übersetzt bedeutet dies Flüssigkristall-Anzeige. Flüssigkristalle sind organische Verbindungen, die Eigenschaften von Flüssigkeiten und Festkörpern besitzen. Zwischen zwei Glasplatten mit Polarisationsfiltern schwimmen die Flüssigkristalle. | + | LCD ist eine Abkürzung und bedeutet '''''L'''iquid '''C'''rystal '''D'''isplay''. Übersetzt bedeutet dies Flüssigkristall-Anzeige. Flüssigkristalle sind organische Verbindungen, die Eigenschaften von Flüssigkeiten und Festkörpern besitzen. Zwischen zwei Glasplatten mit Polarisationsfiltern schwimmen die Flüssigkristalle. Durch Anlegen einer Wechselspannung ändert sich die Polarisationsebene der Flüssigkristalle und damit, ob das einfallende Licht reflektiert oder absorbiert wird. |
− | + | ||
− | + | ||
+ | Bei einem LCD-Modul befindet sich neben dem LCD auch ein Controller zur Ansteuerung des LCDs. | ||
==Text-Displays== | ==Text-Displays== | ||
Zeile 14: | Zeile 13: | ||
===Anschlußbelegung für ≤80 Zeichen Displays=== | ===Anschlußbelegung für ≤80 Zeichen Displays=== | ||
− | Text-Displays verfügen | + | Text-Displays verfügen über genormte 14 Anschluss Pins (LCD-Module mit Backlight über 16 Pins). Lediglich bei der Backlight Versorgungsspannung und Polung kann es Unterschiede geben. Im Zweifelsfall hilft hier der Blick ins Datenblatt. Entweder sind die Anschlüsse in einer Reihe (1 × 14(16)) oder zweireihig (2 × 7(8)) herausgeführt. |
{|{{Blauetabelle}} | {|{{Blauetabelle}} | ||
Zeile 128: | Zeile 127: | ||
|1 | |1 | ||
|* | |* | ||
− | |setzt den Cursor auf | + | |setzt den Cursor auf den Anfang der 1. Zeile (Addresse 0) |
|1.64mS | |1.64mS | ||
|- | |- | ||
Zeile 244: | Zeile 243: | ||
|- | |- | ||
|S | |S | ||
− | |0 = Display nicht | + | |0 = Display nicht schieben |
|1 = Display schieben | |1 = Display schieben | ||
|- | |- | ||
Zeile 286: | Zeile 285: | ||
===8-Bit Ansteuerung (Busmode)=== | ===8-Bit Ansteuerung (Busmode)=== | ||
− | + | Die "8-Bit Busmode"-Ansteuerung funktioniert nur bei AVR Prozessoren mit externem Bus Interface. Diesen Mode unterstützen allerdings nur die wenigsten Atmel AVR Prozessoren, z.B. der AT90S8515 und ATmega128. Der Busmode empfiehlt sich, wenn man in der Applikation auch externen Speicher verwendet. | |
[[Bild:lcdmodul_8bit_schem.png|center|thumb|600px|8-Bit Ansteuerung. Quelle: Peter Fleury]] | [[Bild:lcdmodul_8bit_schem.png|center|thumb|600px|8-Bit Ansteuerung. Quelle: Peter Fleury]] | ||
Zeile 312: | Zeile 311: | ||
Das Programm zur Ansteuerung des Displays im 8-Bit Bus Mode. Verwendet wird die lcdlibrary von Peter Fleury. | Das Programm zur Ansteuerung des Displays im 8-Bit Bus Mode. Verwendet wird die lcdlibrary von Peter Fleury. | ||
− | Folgende Einstellungen sind für obiges | + | Folgende Einstellungen sind für obiges Beispiele in der Header Datei lcd.h vorzunehmen: |
<pre> | <pre> | ||
Zeile 390: | Zeile 389: | ||
[[Bild:lcdmodul_4bitbusy_schem.png|center|thumb|600px|4-Bit Ansteuerung mit Busy]] | [[Bild:lcdmodul_4bitbusy_schem.png|center|thumb|600px|4-Bit Ansteuerung mit Busy]] | ||
+ | Anmerkung: Unbenutzte Pins des Datenports vom LCD sollten in der Regel auf GND gelegt werden, da sie ansonsten auf keinem definierten Pegel liegen und Störsignale empfangen. Je nach Hersteller des LCD-Boards kann es aber auch sein, dass die unbenutzen Datenleitung (DB0-DB3), aufgrund eines internen Pull-up-Transistors, zur einwandfreien Funktion tatsächlich offen gelassen werden müssen. Beispiel hierfür wären Boards mit dem Chipsatz "KS0073" wie das "LCD 204B LED". | ||
+ | |||
+ | Hier ein [http://picasaweb.google.de/lh/photo/7xU12-9CwCJUXh5XCC7LsQ?authkey=Gv1sRgCI3H2aul1-TmNg&feat=directlink Beispielaufbau] auf einem Steckboard. | ||
+ | |||
+ | ====LUNA-AVR Programm==== | ||
+ | |||
+ | Das Programm zur Ansteuerung des Displays im 4-Bit-Mode mit dem internen [http://avr.myluna.de/doku.php?id=de:lcd LCD-Interface] von [http://avr.myluna.de LunaAVR]. Die einzelnen Pins müssen nicht am gleichen Port betrieben werden. Das Beispiel zeigt zusätzlich das Setzen und Verwenden von selbst erstellten Zeichen auf dem Display. | ||
+ | <pre> | ||
+ | '*************************************************************************** | ||
+ | ' Title : lcd example (internal interface) | ||
+ | ' Last updated: 24.08.2012 | ||
+ | ' Target : LCD HD44780 ?x2 (16x2, 20x2, ..) | ||
+ | ' Compiler : LunaAVR 2012.r7.beta build 3390 or newer | ||
+ | '*************************************************************************** | ||
+ | |||
+ | |||
+ | const F_CPU = 16000000 | ||
+ | avr.device = attiny2313 | ||
+ | avr.clock = F_CPU | ||
+ | avr.stack = 16 | ||
+ | |||
+ | dim i as byte | ||
+ | |||
+ | ' Die Signale können an *beliebigen* Port-Pins des Controllers | ||
+ | ' angeschlossen werden. Sie müssen *nicht* einer Portgruppe | ||
+ | ' angehören (PortA, PortB, ..). | ||
+ | lcd.PinDB4 = portb.0 | ||
+ | lcd.PinDB5 = portb.1 | ||
+ | lcd.PinDB6 = portb.2 | ||
+ | lcd.PinDB7 = portb.3 | ||
+ | lcd.PinEN = portb.4 | ||
+ | lcd.PinRS = portb.5 | ||
+ | |||
+ | 'Initialisierung durchführen | ||
+ | lcd.init | ||
+ | 'Cursor einschalten und blinken lassen | ||
+ | lcd.cursor.enable | ||
+ | lcd.cursor.blink.enable | ||
+ | delay() | ||
+ | delay() | ||
+ | delay() | ||
+ | |||
+ | 'blinken abschalten (deaktiviert auch den Cursor, Herstellerabhängig) | ||
+ | lcd.cursor.blink.disable | ||
+ | lcd.cursor.enable | ||
+ | |||
+ | 'Einzelnes Zeichen ausgeben "A" | ||
+ | lcd.char 65 | ||
+ | delay() | ||
+ | |||
+ | 'Cursor sichtbar versetzen | ||
+ | for i=0 to 3 | ||
+ | delay() | ||
+ | lcd.cursor.right | ||
+ | next | ||
+ | 'Formatierte Zahlen ausgeben "00" bis "99" (zur Vermeidung von str() bei kleineren Controllern) | ||
+ | lcd.number 23 | ||
+ | delay() | ||
+ | lcd.char asc(":") | ||
+ | delay() | ||
+ | lcd.cursor.set 1,9 | ||
+ | lcd.number 1 | ||
+ | delay() | ||
+ | |||
+ | lcd.DefChar smily,0 ' Eigenes Sonderzeichen definieren (0-7 möglich) | ||
+ | lcd.DefChar heart,1 ' Eigenes Sonderzeichen definieren (0-7 möglich) | ||
+ | |||
+ | lcd.cursor.set 2,1 ' Cursor positionieren | ||
+ | lcd.textd "Hallo Lcd "+chr(0)+chr(1) ' Text und eigenes Sonderzeichen ausgeben | ||
+ | delay() | ||
+ | delay() | ||
+ | |||
+ | 'Gesamten Anzeigebereich verschieben | ||
+ | for i=0 to 3 | ||
+ | lcd.screen.left | ||
+ | delay() | ||
+ | next | ||
+ | delay() | ||
+ | for i=0 to 3 | ||
+ | lcd.screen.right | ||
+ | delay() | ||
+ | next | ||
+ | |||
+ | 'Ende des Beispiels | ||
+ | do | ||
+ | loop | ||
+ | |||
+ | ' Erstellt mit Lcd Zeicheneditor in der LunaIDE | ||
+ | data smily | ||
+ | .db &b00000 | ||
+ | .db &b01010 | ||
+ | .db &b00000 | ||
+ | .db &b00100 | ||
+ | .db &b10001 | ||
+ | .db &b01110 | ||
+ | .db &b00000 | ||
+ | .db &b00000 | ||
+ | enddata | ||
+ | |||
+ | data heart | ||
+ | .db &b00000 | ||
+ | .db &b00000 | ||
+ | .db &b01010 | ||
+ | .db &b11111 | ||
+ | .db &b11111 | ||
+ | .db &b01110 | ||
+ | .db &b00100 | ||
+ | .db &b00000 | ||
+ | enddata | ||
+ | |||
+ | |||
+ | |||
+ | procedure delay() | ||
+ | waitms 250 | ||
+ | endproc | ||
+ | </pre> | ||
+ | |||
+ | |||
====BASCOM-AVR Programm==== | ====BASCOM-AVR Programm==== | ||
Zeile 395: | Zeile 512: | ||
Das Programm zur Ansteuerung des Displays im 4-Bit I/O Mode benötigt einer spezielle LCD Bibliothek, die 'lcd4busy.lib'. Leider müssen bei der Verwendung dieser Bibliothek alle Pins des LCD Modul an den selben Prozessor Port angeschlossen werden. | Das Programm zur Ansteuerung des Displays im 4-Bit I/O Mode benötigt einer spezielle LCD Bibliothek, die 'lcd4busy.lib'. Leider müssen bei der Verwendung dieser Bibliothek alle Pins des LCD Modul an den selben Prozessor Port angeschlossen werden. | ||
<pre> | <pre> | ||
+ | $lib "lcd4busy.lib" 'ersetzt die Standard LCD Bibliothek | ||
$regfile = "m32def.dat" | $regfile = "m32def.dat" | ||
$crystal = 16000000 | $crystal = 16000000 | ||
− | |||
Config Lcd = 20 * 4 'wir verwenden ein 4 x 20 Zeichen Display | Config Lcd = 20 * 4 'wir verwenden ein 4 x 20 Zeichen Display | ||
− | Const _lcdport = | + | Const _lcdport = Portc |
− | Const _lcdddr = | + | Const _lcdddr = Ddrc |
− | Const _lcdin = | + | Const _lcdin = Pinc |
Const _lcd_e = 1 | Const _lcd_e = 1 | ||
Const _lcd_rw = 2 | Const _lcd_rw = 2 | ||
Zeile 419: | Zeile 536: | ||
Das Programm zur Ansteuerung des Displays im 4-Bit I/O Mode. Verwendet wird die lcdlibrary von Peter Fleury. | Das Programm zur Ansteuerung des Displays im 4-Bit I/O Mode. Verwendet wird die lcdlibrary von Peter Fleury. | ||
− | Folgende Einstellungen sind für obiges | + | Folgende Einstellungen sind für obiges Beispiele in der Header Datei lcd.h vorzunehmen: |
<pre> | <pre> | ||
Zeile 471: | Zeile 588: | ||
#define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ | #define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ | ||
#define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ | #define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ | ||
− | #define LCD_DATA0_PIN | + | #define LCD_DATA0_PIN 4 /**< pin for 4bit data bit 0 */ |
− | #define LCD_DATA1_PIN | + | #define LCD_DATA1_PIN 5 /**< pin for 4bit data bit 1 */ |
− | #define LCD_DATA2_PIN | + | #define LCD_DATA2_PIN 6 /**< pin for 4bit data bit 2 */ |
− | #define LCD_DATA3_PIN | + | #define LCD_DATA3_PIN 7 /**< pin for 4bit data bit 3 */ |
#define LCD_RS_PORT LCD_PORT /**< port for RS line */ | #define LCD_RS_PORT LCD_PORT /**< port for RS line */ | ||
− | #define LCD_RS_PIN | + | #define LCD_RS_PIN 3 /**< pin for RS line */ |
#define LCD_RW_PORT LCD_PORT /**< port for RW line */ | #define LCD_RW_PORT LCD_PORT /**< port for RW line */ | ||
− | #define LCD_RW_PIN | + | #define LCD_RW_PIN 2 /**< pin for RW line */ |
#define LCD_E_PORT LCD_PORT /**< port for Enable line */ | #define LCD_E_PORT LCD_PORT /**< port for Enable line */ | ||
− | #define LCD_E_PIN | + | #define LCD_E_PIN 1 /**< pin for Enable line */ |
... | ... | ||
</pre> | </pre> | ||
Zeile 564: | Zeile 681: | ||
===Ansteuerung über I²C=== | ===Ansteuerung über I²C=== | ||
− | Nur 2 Prozessor Ports benötigt man bei der I²C-Ansteuerung. Dazu wird als I²C Porterweiterungs IC der PCF8574P benötigt. | + | Nur 2 Prozessor Ports benötigt man bei der I²C-Ansteuerung. Dazu wird als I²C Porterweiterungs IC der PCF8574P benötigt. Ein Projekt mit Schaltplan und Layout dazu gibts im Artikel [http://www.rn-wissen.de/index.php/LCD_an_I2C_Huckepack_auf_RN-Miniplatine LCD an I2C Huckepack auf RN-Miniplatine]. |
[[Bild:lcdmodul_i2c_schem.png|center|thumb|600px|I²C-Ansteuerung]] | [[Bild:lcdmodul_i2c_schem.png|center|thumb|600px|I²C-Ansteuerung]] | ||
Zeile 579: | Zeile 696: | ||
Config Sda = Portc.1 'I2C SDA Pin | Config Sda = Portc.1 'I2C SDA Pin | ||
Dim _lcd_e As Byte | Dim _lcd_e As Byte | ||
− | _lcd_e = 128 ' | + | _lcd_e = 128 'LCD im 4-Bit Mode betreiben |
Cls 'loesche das LCD Display | Cls 'loesche das LCD Display | ||
Zeile 594: | Zeile 711: | ||
TODO.... | TODO.... | ||
+ | </pre> | ||
+ | |||
+ | ====Ansteuerung über I²C mit PCA9555==== | ||
+ | |||
+ | Eine weitere Möglichkeit der I²C-Ansteuerung besteht in der Nutzug des PCA9555 (16 Bit I²C I/O Expander) von Philips. Das Display wird im 8-Bit Mode betrieben. | ||
+ | |||
+ | [[Bild:Lcdmodul_i2c_pca9555_schem.png|center|thumb|600px|I²C-Ansteuerung mit PCA9555 8-Bit mit Busy]] | ||
+ | |||
+ | ====AVR-GCC Programm mit PCA9555==== | ||
+ | |||
+ | Programm ist hardwarenah umgesetzt und mit einem ATMEGA8 mit 2x16 Displaytyp getestet. Verwendet wird die twi-library von Peter Fleury. Der Programmentwurf beinhaltet keine Prüfung auf das Zeilenende bzw. Zeilenvorschub. Die Schreibadresse im DD-RAM des Displays wird fortlaufend beschrieben. Die Anzeigeadressen DD-RAM des getesteten Displays liegen bei 00h..0Fh erste Zeile und 40h..4Fh zweite Zeile. | ||
+ | |||
+ | <pre> | ||
+ | ... | ||
+ | #include <avr/io.h> | ||
+ | #include "twimaster.c" //TWI-Routinen von Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury | ||
+ | #include "pausems.c" //Einbindung einfache Pausenfunktion für ca. 1 ms | ||
+ | |||
+ | #define PCA9555 0x40 //device address of Portexpander PCA9555 | ||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Funktion fragt Buys-Flag des Displays ab ob Bereitschaft | ||
+ | // für die Datenübernahme gegeben ist | ||
+ | //******************************************************************** | ||
+ | |||
+ | void WaitForBusy (void) | ||
+ | { | ||
+ | //wenn notwendig, dann umsetzen | ||
+ | } | ||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Funktion führt Erstinitialisierung des Display durch | ||
+ | // laut Herstellerempfehlung + Initialisierung Grundfunktion | ||
+ | //******************************************************************** | ||
+ | |||
+ | void InitDisplay (void) | ||
+ | { | ||
+ | i2c_init(); // init I2C interface | ||
+ | i2c_start (PCA9555+I2C_WRITE); // set device address and write mode | ||
+ | i2c_write (0b00000110); //Command Byte PCA9555 | ||
+ | i2c_write (0b00000000); //PCA9555 Reg6 als Ausgang setzen | ||
+ | i2c_write (0b00000000); //PCA9555 Reg7 als Ausgang setzen | ||
+ | i2c_stop (); | ||
+ | |||
+ | i2c_start_wait (PCA9555+I2C_WRITE); //Schreibzugriff 1 auf Display | ||
+ | i2c_write (0b00000011); //Command Byte PCA9555 Register 3 | ||
+ | |||
+ | i2c_write (0b00000001); //PCA9555 Reg3 - 001h (E-Bit) | ||
+ | i2c_write (0b00110000); //PCA9555 Reg2 - Systemset 30h | ||
+ | i2c_write (0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme | ||
+ | pause_ms (10); | ||
+ | |||
+ | i2c_write (0b00000001); //PCA9555 Reg3 - 001h | ||
+ | i2c_write (0b00110000); //PCA9555 Reg2 - Systemset 30h | ||
+ | i2c_write (0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme | ||
+ | pause_ms (3); | ||
+ | |||
+ | i2c_write (0b00000001); //PCA9555 Reg3 - 001h | ||
+ | i2c_write (0b00110000); //PCA9555 Reg2 - Systemset 30h | ||
+ | i2c_write (0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme | ||
+ | pause_ms (3); | ||
+ | i2c_stop (); //ab hier Display bereit zum Schreiben | ||
+ | |||
+ | // WaitForBusy(); wenn notwendig | ||
+ | |||
+ | i2c_start (PCA9555+I2C_WRITE); | ||
+ | i2c_write(0b00000011); | ||
+ | i2c_write(0b00000001); | ||
+ | i2c_write(0b00111000); //PCA9555 Reg2 - Systemset 38h (8 Bit Modus, 2 Zeilen, 5x8 Punkte) | ||
+ | i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme | ||
+ | i2c_stop (); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Funktion schaltet Display ein | ||
+ | //******************************************************************** | ||
+ | |||
+ | void DisplayOnOff (uint8_t conf) | ||
+ | { | ||
+ | // WaitForBusy(); wenn notwendig | ||
+ | i2c_start (PCA9555+I2C_WRITE); //set device address and write mode | ||
+ | i2c_write(0b00000011); //Command Byte PCA9555 | ||
+ | i2c_write(0b00000001); //PCA9555 Reg3 - 001h | ||
+ | i2c_write(conf); //PCA9555 Reg2 - B3=Display e/a + B2=Cursor e/a + B1=blink. Cursor e/a | ||
+ | i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme | ||
+ | i2c_stop (); | ||
+ | } | ||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Funktion löscht Displayinhalt | ||
+ | //******************************************************************** | ||
+ | |||
+ | void ClearDisplay (void) | ||
+ | { | ||
+ | // WaitForBusy(); wenn notwendig | ||
+ | i2c_start (PCA9555+I2C_WRITE); //set device address and write mode | ||
+ | i2c_write(0b00000011); //Command Byte PCA9555 | ||
+ | i2c_write(0b00000001); //PCA9555 Reg3 - 001h | ||
+ | i2c_write(0b00000001); //PCA9555 Reg2 - Display löschen | ||
+ | i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme | ||
+ | i2c_stop (); | ||
+ | } | ||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Funktion setzt Display-Modus | ||
+ | //******************************************************************** | ||
+ | |||
+ | void SetEntryMode (void) | ||
+ | { | ||
+ | // WaitForBusy(); wenn notwendig | ||
+ | i2c_start (PCA9555+I2C_WRITE); //set device address and write mode | ||
+ | i2c_write(0b00000011); //Command Byte PCA9555 | ||
+ | i2c_write(0b00000001); //PCA9555 Reg3 - 001h | ||
+ | i2c_write(0b00000110); //PCA9555 Reg2 - DDRAM inkrementieren, Display schieben aus | ||
+ | i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit | ||
+ | i2c_stop (); | ||
+ | } | ||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Funktion schreibt ein Byte Daten ins Display | ||
+ | //******************************************************************** | ||
+ | |||
+ | void WriteDisplayChar (uint8_t data) | ||
+ | { | ||
+ | // WaitForBusy(); wenn notwendig | ||
+ | i2c_start (PCA9555+I2C_WRITE); //set device address and write mode | ||
+ | i2c_write(0b00000011); //Command Byte PCA9555 | ||
+ | i2c_write(0b00000101); | ||
+ | i2c_write(data); //PCA9555 Reg2 - Daten ins Display schreiben | ||
+ | i2c_write(0b00000100); //PCA9555 Reg3 - 000h E-Bit | ||
+ | i2c_stop (); | ||
+ | } | ||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Funktion setzt Cursorposition | ||
+ | //******************************************************************** | ||
+ | |||
+ | void SetCorsorXY (uint8_t data1, uint8_t data2) | ||
+ | { | ||
+ | if ((data1 < 16) & (data2 < 2)) | ||
+ | { | ||
+ | if (data2 < 1) | ||
+ | data2 = 0x00; | ||
+ | else | ||
+ | data2 = 0x40; | ||
+ | // WaitForBusy(); wenn notwendig | ||
+ | i2c_start (PCA9555+I2C_WRITE); //set device address and write mode | ||
+ | i2c_write(0b00000011); //Command Byte PCA9555 | ||
+ | i2c_write(0b00000001); //PCA9555 Reg3 - 001h | ||
+ | i2c_write(0b10000000 | data1 | data2); //PCA9555 Reg2 - Position setzen | ||
+ | i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit | ||
+ | i2c_stop (); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Funktion schreibt Text-Daten (nullterminierter String) ins Display | ||
+ | //******************************************************************** | ||
+ | |||
+ | void WriteDisplayText (const char *data) | ||
+ | { | ||
+ | do | ||
+ | { | ||
+ | if (*data != 0) | ||
+ | WriteDisplayChar (*data); | ||
+ | } | ||
+ | while (*data++); | ||
+ | } | ||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Funktion initialisiert alle wichtigen Funktionen auf einmal | ||
+ | //******************************************************************** | ||
+ | |||
+ | void InitDisplayAll(void) | ||
+ | { | ||
+ | InitDisplay(); | ||
+ | DisplayOnOff(0b00001100); | ||
+ | ClearDisplay(); | ||
+ | SetEntryMode(); | ||
+ | } | ||
+ | |||
+ | |||
+ | //******************************************************************** | ||
+ | // Hauptprogramm - 2x Ausgabe "Hallo Welt!" | ||
+ | //******************************************************************** | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | InitDisplay(); | ||
+ | DisplayOnOff(0b00001100); //PCA9555 Reg2 - Display ein + Cursor ein + blink. Cursor aus | ||
+ | ClearDisplay(); | ||
+ | SetEntryMode(); | ||
+ | |||
+ | //oder: InitDisplayAll(); | ||
+ | |||
+ | SetCorsorXY(2,0); | ||
+ | WriteDisplayTextData("Hallo Welt!"); | ||
+ | SetCorsorXY(5,1); | ||
+ | WriteDisplayTextData("Hallo Welt!"); | ||
+ | } | ||
</pre> | </pre> | ||
Zeile 602: | Zeile 929: | ||
==Graphik-Displays== | ==Graphik-Displays== | ||
− | In Mikrocontroller Anwendungen | + | In Mikrocontroller-Anwendungen werden seit neuestem, einhergehend mit der größeren Verbreitung von Controllern mit mehr Speicherplatz, auch immer öfter Grafik-Displays und Farb-TFTs eingesetzt. Der Aufwand an Software und Hardware ist hier allerdings um einiges höher (jedes Pixel ist einzeln anzusteuern). |
+ | |||
+ | |||
+ | ==LCD über RN LCD Adapter Std an RN-Control== | ||
+ | |||
+ | Hierbei handelt es sich um eine Beispielansteuerung eines LCD über RN LCD Adapter Std an RN-Control in C. | ||
+ | |||
+ | Komfortabel lässt sich ein LCD in C mit der LCD Library von Peter Fleury ansteuern (LCD Controller HD44780 & KS0073). | ||
+ | Die Library selbst sowie deren Online Dokumentation und weiterführende informationen sind von [http://jump.to/fleury Peter Fleury's Home Page]zu entnehmen. | ||
+ | |||
+ | Im hier aufgeführten Beispiel wird ein Crystalfontz 20x4 LCD verwendet (CFAH2004A-YYH-JPE). | ||
+ | |||
+ | Pinbelegung nach [http://www.crystalfontz.com/product/CFAH2004AYYHJPE.html Datenblatt] | ||
+ | <pre> | ||
+ | Pin No. Symbol Level Description | ||
+ | 1 VSS 0V Ground | ||
+ | 2 VDD 5.0V Supply Voltage for logic | ||
+ | 3 VO (Variable) Operating voltage for LCD | ||
+ | 4 RS H/L H: DATA, L: Instruction code | ||
+ | 5 R/W H/L H: Read(MPU?Module) L: Write(MPU?Module) | ||
+ | 6 E H,H?L Chip enable signal | ||
+ | 7 DB0 H/L Data bit 0 | ||
+ | 8 DB1 H/L Data bit 1 | ||
+ | 9 DB2 H/L Data bit 2 | ||
+ | 10 DB3 H/L Data bit 3 | ||
+ | 11 DB4 H/L Data bit 4 | ||
+ | 12 DB5 H/L Data bit 5 | ||
+ | 13 DB6 H/L Data bit 6 | ||
+ | 14 DB7 H/L Data bit 7 | ||
+ | 15 A - LED + | ||
+ | 16 K - LED - | ||
+ | </pre> | ||
+ | |||
+ | Pinbelegung des LCD Adapters nach [http://www.robotikhardware.de/download/rn_LCD_adapter_std.pdf Datenblatt] | ||
+ | <pre> | ||
+ | Pin 1 LCD DB7 | ||
+ | Pin 2 LCD DB6 | ||
+ | Pin 3 LCD DB5 | ||
+ | Pin 4 LCD DB4 | ||
+ | Pin 5 Licht ein/aus per Port (da EN2 hier nicht benötigt wird) | ||
+ | Pin 6 LCD EN | ||
+ | Pin 7 LCD R/W | ||
+ | Pin 8 LCD RS | ||
+ | Pin 9 GND LCD GND und Licht Kathode | ||
+ | Pin 10 +5V LCD VCC und Licht Anode | ||
+ | </pre> | ||
+ | |||
+ | Berücksichtigt man die folgenden Tatsachen: | ||
+ | * ATMega32 auf dem RN-Control stellt kein "external memory interface" zur Verfügung, daher ist ohne Weiteres keine 8-Bit Ansteuerung des LCD möglich. Es wird 4-Bit I/O verwendet | ||
+ | * die Zählweise der Pins beginnt in lcd.h bei 0, nicht bei 1 | ||
+ | * der LCD Adapter ist mit PORTC des RN Control verbunden (Vorteil: an den LEDs von PORTC kann erkannt werden, ob überhaupt Daten an das LCD gesendet werden) | ||
+ | * der Controler im LCD ist ein SPLC780D, welcher mit dem in lcd.h genutzten HD44780 kompatibel ist | ||
+ | müssen die nachfolgenden Zeilen in lcd.h entsprechend angepasst werden. | ||
+ | |||
+ | <pre> | ||
+ | #define XTAL 16000000 /**< clock frequency in Hz, used to calculate delay timer */ | ||
+ | </pre> | ||
+ | Die DDRAM Adressen der einzelnen Zeilen sind im Datenblatt hinterlegt. Zeile 1 und 3 sowie 2 und 4 bilden intern je eine Zeile. | ||
+ | Der manuelle Zeilenumbruch am Ende des Codeblocks bleibt Geschmacksache. | ||
+ | <pre> | ||
+ | #define LCD_LINES 4 /**< number of visible lines of the display */ | ||
+ | #define LCD_DISP_LENGTH 20 /**< visibles characters per line of the display */ | ||
+ | #define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ | ||
+ | #define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ | ||
+ | #define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ | ||
+ | #define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ | ||
+ | #define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ | ||
+ | #define LCD_WRAP_LINES 1 /**< 0: no wrap, 1: wrap at end of visibile line */ | ||
+ | </pre> | ||
+ | 4-Bit I/O Mode wird verwendet. | ||
+ | <pre> | ||
+ | #define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */ | ||
+ | </pre> | ||
+ | Wie oben angedeutet werden die Pins von 0 an gezählt. "LCD_DATA3_PIN 0" ist somit Pin 1 des LCD Adapters. | ||
+ | <pre> | ||
+ | #define LCD_PORT PORTC /**< port for the LCD lines */ | ||
+ | #define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ | ||
+ | #define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ | ||
+ | #define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ | ||
+ | #define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ | ||
+ | #define LCD_DATA0_PIN 3 /**< pin for 4bit data bit 0 */ | ||
+ | #define LCD_DATA1_PIN 2 /**< pin for 4bit data bit 1 */ | ||
+ | #define LCD_DATA2_PIN 1 /**< pin for 4bit data bit 2 */ | ||
+ | #define LCD_DATA3_PIN 0 /**< pin for 4bit data bit 3 */ | ||
+ | #define LCD_RS_PORT LCD_PORT /**< port for RS line */ | ||
+ | #define LCD_RS_PIN 7 /**< pin for RS line */ | ||
+ | #define LCD_RW_PORT LCD_PORT /**< port for RW line */ | ||
+ | #define LCD_RW_PIN 6 /**< pin for RW line */ | ||
+ | #define LCD_E_PORT LCD_PORT /**< port for Enable line */ | ||
+ | #define LCD_E_PIN 5 /**< pin for Enable line */ | ||
+ | </pre> | ||
+ | |||
+ | Testprogramm: | ||
+ | <pre> | ||
+ | #include <stdlib.h> | ||
+ | #include <avr/io.h> | ||
+ | #include <lcd.c> | ||
+ | |||
+ | |||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | |||
+ | |||
+ | lcd_init(LCD_DISP_ON_CURSOR_BLINK); | ||
+ | lcd_clrscr(); | ||
+ | lcd_puts("test"); | ||
+ | |||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </pre> | ||
==Siehe auch== | ==Siehe auch== | ||
Zeile 610: | Zeile 1.048: | ||
* [[AVR]] | * [[AVR]] | ||
* [[I2C|I²C-Bus]] | * [[I2C|I²C-Bus]] | ||
+ | * [[LCD an I2C Huckepack auf RN-Miniplatine]] | ||
==Weblinks== | ==Weblinks== |
Aktuelle Version vom 11. Juli 2013, 14:53 Uhr
Inhaltsverzeichnis
- 1 Einleitung
- 2 Text-Displays
- 3 Graphik-Displays
- 4 LCD über RN LCD Adapter Std an RN-Control
- 5 Siehe auch
- 6 Weblinks
- 7 Autore(en)
Einleitung
LCD ist eine Abkürzung und bedeutet Liquid Crystal Display. Übersetzt bedeutet dies Flüssigkristall-Anzeige. Flüssigkristalle sind organische Verbindungen, die Eigenschaften von Flüssigkeiten und Festkörpern besitzen. Zwischen zwei Glasplatten mit Polarisationsfiltern schwimmen die Flüssigkristalle. Durch Anlegen einer Wechselspannung ändert sich die Polarisationsebene der Flüssigkristalle und damit, ob das einfallende Licht reflektiert oder absorbiert wird.
Bei einem LCD-Modul befindet sich neben dem LCD auch ein Controller zur Ansteuerung des LCDs.
Text-Displays
Text-Displays kommen wegen der problemlosen Anbindung in Mikrocontroller Projekten wie Robotern am häufigsten zum Einsatz. Bei Text-LCDs kommen meistens der HD44780 von Hitachi oder ein kompatibler Controller zum Einsatz. Dieser Controller unterstützt Displays mit bis zu 80 Zeichen. Gängige Displaygrößen sind: 8 × 1, 8 × 2, 16 × 1, 16 × 2, 20 × 2, 20 × 4, 40 × 2 Zeichen Displays (Spalten × Zeilen). Hat das Display mehr als 80 Zeichen, dann benötigt das Display 2 Controller und verhält sich nach außen zur Ansteuerung, wie 2 Displays (zusätzliche Enable Leitung)
Anschlußbelegung für ≤80 Zeichen Displays
Text-Displays verfügen über genormte 14 Anschluss Pins (LCD-Module mit Backlight über 16 Pins). Lediglich bei der Backlight Versorgungsspannung und Polung kann es Unterschiede geben. Im Zweifelsfall hilft hier der Blick ins Datenblatt. Entweder sind die Anschlüsse in einer Reihe (1 × 14(16)) oder zweireihig (2 × 7(8)) herausgeführt.
Pin | Bezeichnung | Beschreibung |
1 | GND | Masse |
2 | VCC | Spannungsversorgung +5V |
3 | VEE | Kontrast Poti 0..0,5V |
4 | RS | Register Select, 1=Daten schreiben / 0=Kommando senden. |
5 | R/W | 1=Read / 0=Write zum lesen / schreiben in das Display RAM |
6 | Enable | Fallende Flanke -> Übertragen des Kommandos oder der Daten, H-Pegel -> Lesen von Daten aus dem Display |
7 | DB0 | Datenbus Bit0 LSB |
8 | DB1 | Datenbus Bit1 |
9 | DB2 | Datenbus Bit2 |
10 | DB3 | Datenbus Bit3 |
11 | DB4 | Datenbus Bit4 |
12 | DB5 | Datenbus Bit5 |
13 | DB6 | Datenbus Bit6 |
14 | DB7 | Datenbus Bit7 MSB |
HD44780 kompatibler LCD Controller
Der HD44780 LCD Controller besitzt 3 Speicher. Den DDRAM (Display Data RAM) Darin werden die anzuzeigenden Daten geschrieben. Der CGROM (Character Generator ROM) enthält die Zeichen in Form von 5x8 oder 5x10 Punktmatrizen. Im CGRAM (Character Generator RAM) können acht benutzerdefinierte Zeichen 5x8 Pixel oder vier 5x10 Pixel abgelegt werden.
Befehlsübersicht
Befehl | RS | R/W | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | Beschreibung | Ausführungszeit bei fosc=250kHz |
Clear Display | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | Löscht das Display und setzt den Cursor auf den Anfang der 1. Zeile (Addresse 0). | 1.64mS |
Cursor Home | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | * | setzt den Cursor auf den Anfang der 1. Zeile (Addresse 0) | 1.64mS |
Entry mode set | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S | Setzt die Cursor Bewegungsrichtung (I/D), spezifiziert das Display zu schieben (S). Diese Operationen werden während des Daten lesen/schreiben durchgeführt. | 40uS |
Display on/off Control | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B | Schaltet an/aus: das gesamte Display (D), Den Cursor (C) Cursor blinken (B). | 40uS |
Cursor/Display shift | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | * | * | Setzt Cursor Bewegung oder Display Bewegung (S/C), Bewegungsrichtung (R/L) | 40uS |
Function set | 0 | 0 | 0 | 0 | 1 | DL | N | F | * | * | Einstellen der Schnittstellen Datenlänge (DL), Anzahl Display Zeilen (N) und Zeichen Font (F). | 40uS |
Set CGRAM Address | 0 | 0 | 0 | 1 | CGRAM Adresse | Setzen der CGRAM Adresse. CGRAM Daten werden gesendet und empfangen nach dem setzen. | 40uS | |||||
Set DDRAM Address | 0 | 0 | 1 | DDRAM Adresse | Setzen der DDRAM Adresse. DDRAM Daten werden gesendet und empfangen nach dem setzen. | 40uS | ||||||
Read busy-flag and address counter | 0 | 1 | BF | CGRAM / DDRAM Adresse | Liest das Busy-flag (BF), welches anzeigt das interne Operationen ausgeführt werden, und liest den CGRAM oder DDRAM Adress Zeiger Inhalt. | 0uS | ||||||
Write to CGRAM or DDRAM | 1 | 0 | Schreib Daten | Schreibt Daten zum CGRAM oder DDRAM. | 40uS | |||||||
read from CGRAM or DDRAM | 1 | 1 | Lese Daten | Liest Daten vom CGRAM oder DDRAM. | 40uS |
Anmerkungen:
- DDRAM = Display Data RAM.
- CGRAM = Character Generator RAM.
- DDRAM Adresse entspricht der Cursor Position.
- * = egal.
Bit Name | Einstellung / Status | |
I/D | 0 = Erniedrige Cursor Position | 1 = Erhöhe Cursor Position |
S | 0 = Display nicht schieben | 1 = Display schieben |
D | 0 = Display aus | 1 = Display an |
C | 0 = Cursor aus | 1 = Cursor an |
B | 0 = Cursor blinken aus | 1 = Cursor blinken an |
S/C | 0 = Bewege Cursor | 1 = Schiebe Display |
R/L | 0 = Schiebe nach links | 1 = Schiebe nach rechts |
DL | 0 = 4-bit Interface | 1 = 8-bit Interface |
N | 0 = 1/8 oder 1/11 Duty (1 Zeile) | 1 = 1/16 Duty (2 Zeilen) |
F | 0 = 5x7 Punkte | 1 = 5x10 Punkte |
BF | 0 = Befehle werden akzeptiert | 1 = Interne Operation wird ausgeführt |
8-Bit Ansteuerung (Busmode)
Die "8-Bit Busmode"-Ansteuerung funktioniert nur bei AVR Prozessoren mit externem Bus Interface. Diesen Mode unterstützen allerdings nur die wenigsten Atmel AVR Prozessoren, z.B. der AT90S8515 und ATmega128. Der Busmode empfiehlt sich, wenn man in der Applikation auch externen Speicher verwendet.
BASCOM-AVR Programm
Das Programm zur Ansteuerung des Displays im 8-Bit Bus Mode.
$regfile = "8515def.dat" $crystal = 4000000 $lcd = &HC000 'Adresse LCD Daten $lcdrs = &H8000 'Adresse LCD Register select Config Lcdbus = 8 'LCD im 8-Bit Bus Mode Config Lcd = 16 * 2 'wir verwenden ein 16 x 2 Zeichen Display Cls 'loesche das LCD Display Locate 1 , 1 'Cursor auf 1 Zeile, 1 Spalte Lcd "Hello world." 'String auf Display anzeigen ...
AVR-GCC Programm
Das Programm zur Ansteuerung des Displays im 8-Bit Bus Mode. Verwendet wird die lcdlibrary von Peter Fleury.
Folgende Einstellungen sind für obiges Beispiele in der Header Datei lcd.h vorzunehmen:
... /** * @name Definitions for MCU Clock Frequency * Adapt the MCU clock frequency in Hz to your target. */ #define XTAL 4000000 /**< clock frequency in Hz, used to calculate delay timer */ /** * @name Definition for LCD controller type * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller. */ #define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ /** * @name Definitions for Display Size * Change these definitions to adapt setting to your display */ #define LCD_LINES 2 /**< number of visible lines of the display */ #define LCD_DISP_LENGTH 16 /**< visibles characters per line of the display */ #define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ #define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ #define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ #define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ #define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ #define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ #define LCD_IO_MODE 0 /**< 0: memory mapped mode, 1: IO port mode */ #if LCD_IO_MODE ... #elif defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || defined(__AVR_ATmega64__) || \ defined(__AVR_ATmega8515__)|| defined(__AVR_ATmega103__) || defined(__AVR_ATmega128__) || \ defined(__AVR_ATmega161__) || defined(__AVR_ATmega162__) /* * memory mapped mode is only supported when the device has an external data memory interface */ #define LCD_IO_DATA 0xC000 /* A15=E=1, A14=RS=1 */ #define LCD_IO_FUNCTION 0x8000 /* A15=E=1, A14=RS=0 */ #define LCD_IO_READ 0x0100 /* A8 =R/W=1 (R/W: 1=Read, 0=Write */ #else #error "external data memory interface not available for this device, use 4-bit IO port mode" #endif ...
So sieht das Programmbeispiel in AVR-GCC aus:
#include <stdlib.h> #include <avr/io.h> #include "lcd.h" int main(void) { /* Initialisiere Display, Cursor aus */ lcd_init(LCD_DISP_ON); /* loesche das LCD Display und Cursor auf 1 Zeile, 1 Spalte */ lcd_clrscr(); /* String auf Display anzeigen */ lcd_puts("Hello world."); ...
4-Bit Ansteuerung mit Busy(I/O Mode)
Mit die häufigste Anbindungsart ist sicher die 4-Bit Ansteuerung. Dabei werden die Display-Daten Nibble-weise in den Display Speicher übertragen. Das ist zwar etwas langsamer als im 8-Bit Mode, das spielt aber kaum eine Rolle. Für diese Ansteuerung werden 7 Prozessor Ports benötigt. Die Abfrage des Busy Flags ist durch die Verdrahtung des R/W Pins möglich.
Anmerkung: Unbenutzte Pins des Datenports vom LCD sollten in der Regel auf GND gelegt werden, da sie ansonsten auf keinem definierten Pegel liegen und Störsignale empfangen. Je nach Hersteller des LCD-Boards kann es aber auch sein, dass die unbenutzen Datenleitung (DB0-DB3), aufgrund eines internen Pull-up-Transistors, zur einwandfreien Funktion tatsächlich offen gelassen werden müssen. Beispiel hierfür wären Boards mit dem Chipsatz "KS0073" wie das "LCD 204B LED".
Hier ein Beispielaufbau auf einem Steckboard.
LUNA-AVR Programm
Das Programm zur Ansteuerung des Displays im 4-Bit-Mode mit dem internen LCD-Interface von LunaAVR. Die einzelnen Pins müssen nicht am gleichen Port betrieben werden. Das Beispiel zeigt zusätzlich das Setzen und Verwenden von selbst erstellten Zeichen auf dem Display.
'*************************************************************************** ' Title : lcd example (internal interface) ' Last updated: 24.08.2012 ' Target : LCD HD44780 ?x2 (16x2, 20x2, ..) ' Compiler : LunaAVR 2012.r7.beta build 3390 or newer '*************************************************************************** const F_CPU = 16000000 avr.device = attiny2313 avr.clock = F_CPU avr.stack = 16 dim i as byte ' Die Signale können an *beliebigen* Port-Pins des Controllers ' angeschlossen werden. Sie müssen *nicht* einer Portgruppe ' angehören (PortA, PortB, ..). lcd.PinDB4 = portb.0 lcd.PinDB5 = portb.1 lcd.PinDB6 = portb.2 lcd.PinDB7 = portb.3 lcd.PinEN = portb.4 lcd.PinRS = portb.5 'Initialisierung durchführen lcd.init 'Cursor einschalten und blinken lassen lcd.cursor.enable lcd.cursor.blink.enable delay() delay() delay() 'blinken abschalten (deaktiviert auch den Cursor, Herstellerabhängig) lcd.cursor.blink.disable lcd.cursor.enable 'Einzelnes Zeichen ausgeben "A" lcd.char 65 delay() 'Cursor sichtbar versetzen for i=0 to 3 delay() lcd.cursor.right next 'Formatierte Zahlen ausgeben "00" bis "99" (zur Vermeidung von str() bei kleineren Controllern) lcd.number 23 delay() lcd.char asc(":") delay() lcd.cursor.set 1,9 lcd.number 1 delay() lcd.DefChar smily,0 ' Eigenes Sonderzeichen definieren (0-7 möglich) lcd.DefChar heart,1 ' Eigenes Sonderzeichen definieren (0-7 möglich) lcd.cursor.set 2,1 ' Cursor positionieren lcd.textd "Hallo Lcd "+chr(0)+chr(1) ' Text und eigenes Sonderzeichen ausgeben delay() delay() 'Gesamten Anzeigebereich verschieben for i=0 to 3 lcd.screen.left delay() next delay() for i=0 to 3 lcd.screen.right delay() next 'Ende des Beispiels do loop ' Erstellt mit Lcd Zeicheneditor in der LunaIDE data smily .db &b00000 .db &b01010 .db &b00000 .db &b00100 .db &b10001 .db &b01110 .db &b00000 .db &b00000 enddata data heart .db &b00000 .db &b00000 .db &b01010 .db &b11111 .db &b11111 .db &b01110 .db &b00100 .db &b00000 enddata procedure delay() waitms 250 endproc
BASCOM-AVR Programm
Das Programm zur Ansteuerung des Displays im 4-Bit I/O Mode benötigt einer spezielle LCD Bibliothek, die 'lcd4busy.lib'. Leider müssen bei der Verwendung dieser Bibliothek alle Pins des LCD Modul an den selben Prozessor Port angeschlossen werden.
$lib "lcd4busy.lib" 'ersetzt die Standard LCD Bibliothek $regfile = "m32def.dat" $crystal = 16000000 Config Lcd = 20 * 4 'wir verwenden ein 4 x 20 Zeichen Display Const _lcdport = Portc Const _lcdddr = Ddrc Const _lcdin = Pinc Const _lcd_e = 1 Const _lcd_rw = 2 Const _lcd_rs = 3 Cls 'loesche das LCD Display Locate 1 , 1 'Cursor auf 1 Zeile, 1 Spalte Lcd "Hello world." 'String auf Display anzeigen ...
AVR-GCC Programm
Das Programm zur Ansteuerung des Displays im 4-Bit I/O Mode. Verwendet wird die lcdlibrary von Peter Fleury.
Folgende Einstellungen sind für obiges Beispiele in der Header Datei lcd.h vorzunehmen:
... /** * @name Definitions for MCU Clock Frequency * Adapt the MCU clock frequency in Hz to your target. */ #define XTAL 16000000 /**< clock frequency in Hz, used to calculate delay timer */ /** * @name Definition for LCD controller type * Use 0 for HD44780 controller, change to 1 for displays with KS0073 controller. */ #define LCD_CONTROLLER_KS0073 0 /**< Use 0 for HD44780 controller, 1 for KS0073 controller */ /** * @name Definitions for Display Size * Change these definitions to adapt setting to your display */ #define LCD_LINES 4 /**< number of visible lines of the display */ #define LCD_DISP_LENGTH 20 /**< visibles characters per line of the display */ #define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ #define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ #define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ #define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ #define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ #define LCD_WRAP_LINES 0 /**< 0: no wrap, 1: wrap at end of visibile line */ #define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */ #if LCD_IO_MODE /** * @name Definitions for 4-bit IO mode * Change LCD_PORT if you want to use a different port for the LCD pins. * * The four LCD data lines and the three control lines RS, RW, E can be on the * same port or on different ports. * Change LCD_RS_PORT, LCD_RW_PORT, LCD_E_PORT if you want the control lines on * different ports. * * Normally the four data lines should be mapped to bit 0..3 on one port, but it * is possible to connect these data lines in different order or even on different * ports by adapting the LCD_DATAx_PORT and LCD_DATAx_PIN definitions. * */ #define LCD_PORT PORTC /**< port for the LCD lines */ #define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ #define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ #define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ #define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ #define LCD_DATA0_PIN 4 /**< pin for 4bit data bit 0 */ #define LCD_DATA1_PIN 5 /**< pin for 4bit data bit 1 */ #define LCD_DATA2_PIN 6 /**< pin for 4bit data bit 2 */ #define LCD_DATA3_PIN 7 /**< pin for 4bit data bit 3 */ #define LCD_RS_PORT LCD_PORT /**< port for RS line */ #define LCD_RS_PIN 3 /**< pin for RS line */ #define LCD_RW_PORT LCD_PORT /**< port for RW line */ #define LCD_RW_PIN 2 /**< pin for RW line */ #define LCD_E_PORT LCD_PORT /**< port for Enable line */ #define LCD_E_PIN 1 /**< pin for Enable line */ ...
So sieht das Programmbeispiel in AVR-GCC aus:
#include <stdlib.h> #include <avr/io.h> #include "lcd.h" int main(void) { /* Initialisiere Display, Cursor aus */ lcd_init(LCD_DISP_ON); /* loesche das LCD Display und Cursor auf 1 Zeile, 1 Spalte */ lcd_clrscr(); /* String auf Display anzeigen */ lcd_puts("Hello world."); ...
4-Bit Ansteuerung ohne Busy(I/O Mode)
Mit die häufigste Anbindungsart ist sicher die 4-Bit Ansteuerung. Dabei werden die Display-Daten Nibble-weise in den Display Speicher übertragen. Das ist zwar etwas langsamer als im 8-Bit Mode, das spielt aber kaum eine Rolle. Für diese Ansteuerung werden 6 Prozessor Ports benötigt. Die R/W Leitung des Displays kann man dabei einfach auf GND legen, dann ist aber keine Busy-Bit Abfrage möglich.
BASCOM-AVR Programm
Das Programm zur Ansteuerung des Displays im 4-Bit I/O Mode.
$regfile = "m32def.dat" $crystal = 16000000 Config Lcd = 20 * 4 'wir verwenden ein 4 x 20 Zeichen Display ' Im I/O Mode wird jeder Prozessor Pin einzeln angegeben Config Lcdpin = Pin , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 , E = Portc.5 , Rs = Portc.4 Cls 'loesche das LCD Display Locate 1 , 1 'Cursor auf 1 Zeile, 1 Spalte Lcd "Hello world." 'String auf Display anzeigen ...
AVR-GCC Programm
TODO....
Ansteuerung über Porterweiterung
Mit einem Porterweiterungs Baustein wie dem 74HC595 lassen sich weitere Prozessor-Ports einsparen. Diese Lösung kommt mit 4 Prozessor Ports aus, läßt man die Abfrage des Busy-Bits (PC5) weg, sogar nur mit 3 Prozessor Ports. Trotzdem wird das Display im 8-Bit Mode betrieben.
BASCOM-AVR Programm
Das BASCOM Programm für diese Ansteuerung ist nicht ganz so einfach, da es nicht von der BASCOM Library unterstützt wird. Die Routinen zum Ansprechen des Displays muß man selbst coden.
TODO....
AVR-GCC Programm
TODO....
Ansteuerung über I²C
Nur 2 Prozessor Ports benötigt man bei der I²C-Ansteuerung. Dazu wird als I²C Porterweiterungs IC der PCF8574P benötigt. Ein Projekt mit Schaltplan und Layout dazu gibts im Artikel LCD an I2C Huckepack auf RN-Miniplatine.
BASCOM-AVR Programm
Diese Ansteuerung basiert auf der Application Note AN#118 von MCS electronics. Dazu gibt es auch eine fertige Library zu BASCOM-AVR, die die Standard LCD Library ersetzt. Dadurch können die gleichen Befehle zur Ansteuerung verwendet werden wie bei der Standard LCD Library. Das BASCOM-AVR Programm, um das LCD-Modul über I²C anzusprechen, sieht dann so aus.
$lib "Lcd_i2c.lib" 'ersetzt die Standard LCD Library $regfile = "m32def.dat" $crystal = 16000000 Const Pcf8574_lcd = &H40 'I2C Adresse Config Scl = Portc.0 'I2C SCL Pin Config Sda = Portc.1 'I2C SDA Pin Dim _lcd_e As Byte _lcd_e = 128 'LCD im 4-Bit Mode betreiben Cls 'loesche das LCD Display Locate 1 , 1 'Cursor auf 1 Zeile, 1 Spalte Lcd "Hello world." 'String auf Display anzeigen ...
AVR-GCC Programm
TODO....
Ansteuerung über I²C mit PCA9555
Eine weitere Möglichkeit der I²C-Ansteuerung besteht in der Nutzug des PCA9555 (16 Bit I²C I/O Expander) von Philips. Das Display wird im 8-Bit Mode betrieben.
AVR-GCC Programm mit PCA9555
Programm ist hardwarenah umgesetzt und mit einem ATMEGA8 mit 2x16 Displaytyp getestet. Verwendet wird die twi-library von Peter Fleury. Der Programmentwurf beinhaltet keine Prüfung auf das Zeilenende bzw. Zeilenvorschub. Die Schreibadresse im DD-RAM des Displays wird fortlaufend beschrieben. Die Anzeigeadressen DD-RAM des getesteten Displays liegen bei 00h..0Fh erste Zeile und 40h..4Fh zweite Zeile.
... #include <avr/io.h> #include "twimaster.c" //TWI-Routinen von Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury #include "pausems.c" //Einbindung einfache Pausenfunktion für ca. 1 ms #define PCA9555 0x40 //device address of Portexpander PCA9555 //******************************************************************** // Funktion fragt Buys-Flag des Displays ab ob Bereitschaft // für die Datenübernahme gegeben ist //******************************************************************** void WaitForBusy (void) { //wenn notwendig, dann umsetzen } //******************************************************************** // Funktion führt Erstinitialisierung des Display durch // laut Herstellerempfehlung + Initialisierung Grundfunktion //******************************************************************** void InitDisplay (void) { i2c_init(); // init I2C interface i2c_start (PCA9555+I2C_WRITE); // set device address and write mode i2c_write (0b00000110); //Command Byte PCA9555 i2c_write (0b00000000); //PCA9555 Reg6 als Ausgang setzen i2c_write (0b00000000); //PCA9555 Reg7 als Ausgang setzen i2c_stop (); i2c_start_wait (PCA9555+I2C_WRITE); //Schreibzugriff 1 auf Display i2c_write (0b00000011); //Command Byte PCA9555 Register 3 i2c_write (0b00000001); //PCA9555 Reg3 - 001h (E-Bit) i2c_write (0b00110000); //PCA9555 Reg2 - Systemset 30h i2c_write (0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme pause_ms (10); i2c_write (0b00000001); //PCA9555 Reg3 - 001h i2c_write (0b00110000); //PCA9555 Reg2 - Systemset 30h i2c_write (0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme pause_ms (3); i2c_write (0b00000001); //PCA9555 Reg3 - 001h i2c_write (0b00110000); //PCA9555 Reg2 - Systemset 30h i2c_write (0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme pause_ms (3); i2c_stop (); //ab hier Display bereit zum Schreiben // WaitForBusy(); wenn notwendig i2c_start (PCA9555+I2C_WRITE); i2c_write(0b00000011); i2c_write(0b00000001); i2c_write(0b00111000); //PCA9555 Reg2 - Systemset 38h (8 Bit Modus, 2 Zeilen, 5x8 Punkte) i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme i2c_stop (); } //******************************************************************** // Funktion schaltet Display ein //******************************************************************** void DisplayOnOff (uint8_t conf) { // WaitForBusy(); wenn notwendig i2c_start (PCA9555+I2C_WRITE); //set device address and write mode i2c_write(0b00000011); //Command Byte PCA9555 i2c_write(0b00000001); //PCA9555 Reg3 - 001h i2c_write(conf); //PCA9555 Reg2 - B3=Display e/a + B2=Cursor e/a + B1=blink. Cursor e/a i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme i2c_stop (); } //******************************************************************** // Funktion löscht Displayinhalt //******************************************************************** void ClearDisplay (void) { // WaitForBusy(); wenn notwendig i2c_start (PCA9555+I2C_WRITE); //set device address and write mode i2c_write(0b00000011); //Command Byte PCA9555 i2c_write(0b00000001); //PCA9555 Reg3 - 001h i2c_write(0b00000001); //PCA9555 Reg2 - Display löschen i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit auf Null zur Übernahme i2c_stop (); } //******************************************************************** // Funktion setzt Display-Modus //******************************************************************** void SetEntryMode (void) { // WaitForBusy(); wenn notwendig i2c_start (PCA9555+I2C_WRITE); //set device address and write mode i2c_write(0b00000011); //Command Byte PCA9555 i2c_write(0b00000001); //PCA9555 Reg3 - 001h i2c_write(0b00000110); //PCA9555 Reg2 - DDRAM inkrementieren, Display schieben aus i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit i2c_stop (); } //******************************************************************** // Funktion schreibt ein Byte Daten ins Display //******************************************************************** void WriteDisplayChar (uint8_t data) { // WaitForBusy(); wenn notwendig i2c_start (PCA9555+I2C_WRITE); //set device address and write mode i2c_write(0b00000011); //Command Byte PCA9555 i2c_write(0b00000101); i2c_write(data); //PCA9555 Reg2 - Daten ins Display schreiben i2c_write(0b00000100); //PCA9555 Reg3 - 000h E-Bit i2c_stop (); } //******************************************************************** // Funktion setzt Cursorposition //******************************************************************** void SetCorsorXY (uint8_t data1, uint8_t data2) { if ((data1 < 16) & (data2 < 2)) { if (data2 < 1) data2 = 0x00; else data2 = 0x40; // WaitForBusy(); wenn notwendig i2c_start (PCA9555+I2C_WRITE); //set device address and write mode i2c_write(0b00000011); //Command Byte PCA9555 i2c_write(0b00000001); //PCA9555 Reg3 - 001h i2c_write(0b10000000 | data1 | data2); //PCA9555 Reg2 - Position setzen i2c_write(0b00000000); //PCA9555 Reg3 - 000h E-Bit i2c_stop (); } } //******************************************************************** // Funktion schreibt Text-Daten (nullterminierter String) ins Display //******************************************************************** void WriteDisplayText (const char *data) { do { if (*data != 0) WriteDisplayChar (*data); } while (*data++); } //******************************************************************** // Funktion initialisiert alle wichtigen Funktionen auf einmal //******************************************************************** void InitDisplayAll(void) { InitDisplay(); DisplayOnOff(0b00001100); ClearDisplay(); SetEntryMode(); } //******************************************************************** // Hauptprogramm - 2x Ausgabe "Hallo Welt!" //******************************************************************** int main(void) { InitDisplay(); DisplayOnOff(0b00001100); //PCA9555 Reg2 - Display ein + Cursor ein + blink. Cursor aus ClearDisplay(); SetEntryMode(); //oder: InitDisplayAll(); SetCorsorXY(2,0); WriteDisplayTextData("Hallo Welt!"); SetCorsorXY(5,1); WriteDisplayTextData("Hallo Welt!"); }
Ansteuerung über RS232
Ebenfalls nur 2 Pins zur Ansteuerung benötigt die Lösung. Allerdings ist die serielle Schnittstelle bei Mikrocontrollern oft schon mit anderen Aufgaben belegt. Deshalb befindet sich meistens noch zusätzlich eine I²C-Bus Schnittstelle zur Ansteuerung auf dem Modul.
Graphik-Displays
In Mikrocontroller-Anwendungen werden seit neuestem, einhergehend mit der größeren Verbreitung von Controllern mit mehr Speicherplatz, auch immer öfter Grafik-Displays und Farb-TFTs eingesetzt. Der Aufwand an Software und Hardware ist hier allerdings um einiges höher (jedes Pixel ist einzeln anzusteuern).
LCD über RN LCD Adapter Std an RN-Control
Hierbei handelt es sich um eine Beispielansteuerung eines LCD über RN LCD Adapter Std an RN-Control in C.
Komfortabel lässt sich ein LCD in C mit der LCD Library von Peter Fleury ansteuern (LCD Controller HD44780 & KS0073). Die Library selbst sowie deren Online Dokumentation und weiterführende informationen sind von Peter Fleury's Home Pagezu entnehmen.
Im hier aufgeführten Beispiel wird ein Crystalfontz 20x4 LCD verwendet (CFAH2004A-YYH-JPE).
Pinbelegung nach Datenblatt
Pin No. Symbol Level Description 1 VSS 0V Ground 2 VDD 5.0V Supply Voltage for logic 3 VO (Variable) Operating voltage for LCD 4 RS H/L H: DATA, L: Instruction code 5 R/W H/L H: Read(MPU?Module) L: Write(MPU?Module) 6 E H,H?L Chip enable signal 7 DB0 H/L Data bit 0 8 DB1 H/L Data bit 1 9 DB2 H/L Data bit 2 10 DB3 H/L Data bit 3 11 DB4 H/L Data bit 4 12 DB5 H/L Data bit 5 13 DB6 H/L Data bit 6 14 DB7 H/L Data bit 7 15 A - LED + 16 K - LED -
Pinbelegung des LCD Adapters nach Datenblatt
Pin 1 LCD DB7 Pin 2 LCD DB6 Pin 3 LCD DB5 Pin 4 LCD DB4 Pin 5 Licht ein/aus per Port (da EN2 hier nicht benötigt wird) Pin 6 LCD EN Pin 7 LCD R/W Pin 8 LCD RS Pin 9 GND LCD GND und Licht Kathode Pin 10 +5V LCD VCC und Licht Anode
Berücksichtigt man die folgenden Tatsachen:
- ATMega32 auf dem RN-Control stellt kein "external memory interface" zur Verfügung, daher ist ohne Weiteres keine 8-Bit Ansteuerung des LCD möglich. Es wird 4-Bit I/O verwendet
- die Zählweise der Pins beginnt in lcd.h bei 0, nicht bei 1
- der LCD Adapter ist mit PORTC des RN Control verbunden (Vorteil: an den LEDs von PORTC kann erkannt werden, ob überhaupt Daten an das LCD gesendet werden)
- der Controler im LCD ist ein SPLC780D, welcher mit dem in lcd.h genutzten HD44780 kompatibel ist
müssen die nachfolgenden Zeilen in lcd.h entsprechend angepasst werden.
#define XTAL 16000000 /**< clock frequency in Hz, used to calculate delay timer */
Die DDRAM Adressen der einzelnen Zeilen sind im Datenblatt hinterlegt. Zeile 1 und 3 sowie 2 und 4 bilden intern je eine Zeile. Der manuelle Zeilenumbruch am Ende des Codeblocks bleibt Geschmacksache.
#define LCD_LINES 4 /**< number of visible lines of the display */ #define LCD_DISP_LENGTH 20 /**< visibles characters per line of the display */ #define LCD_LINE_LENGTH 0x40 /**< internal line length of the display */ #define LCD_START_LINE1 0x00 /**< DDRAM address of first char of line 1 */ #define LCD_START_LINE2 0x40 /**< DDRAM address of first char of line 2 */ #define LCD_START_LINE3 0x14 /**< DDRAM address of first char of line 3 */ #define LCD_START_LINE4 0x54 /**< DDRAM address of first char of line 4 */ #define LCD_WRAP_LINES 1 /**< 0: no wrap, 1: wrap at end of visibile line */
4-Bit I/O Mode wird verwendet.
#define LCD_IO_MODE 1 /**< 0: memory mapped mode, 1: IO port mode */
Wie oben angedeutet werden die Pins von 0 an gezählt. "LCD_DATA3_PIN 0" ist somit Pin 1 des LCD Adapters.
#define LCD_PORT PORTC /**< port for the LCD lines */ #define LCD_DATA0_PORT LCD_PORT /**< port for 4bit data bit 0 */ #define LCD_DATA1_PORT LCD_PORT /**< port for 4bit data bit 1 */ #define LCD_DATA2_PORT LCD_PORT /**< port for 4bit data bit 2 */ #define LCD_DATA3_PORT LCD_PORT /**< port for 4bit data bit 3 */ #define LCD_DATA0_PIN 3 /**< pin for 4bit data bit 0 */ #define LCD_DATA1_PIN 2 /**< pin for 4bit data bit 1 */ #define LCD_DATA2_PIN 1 /**< pin for 4bit data bit 2 */ #define LCD_DATA3_PIN 0 /**< pin for 4bit data bit 3 */ #define LCD_RS_PORT LCD_PORT /**< port for RS line */ #define LCD_RS_PIN 7 /**< pin for RS line */ #define LCD_RW_PORT LCD_PORT /**< port for RW line */ #define LCD_RW_PIN 6 /**< pin for RW line */ #define LCD_E_PORT LCD_PORT /**< port for Enable line */ #define LCD_E_PIN 5 /**< pin for Enable line */
Testprogramm:
#include <stdlib.h> #include <avr/io.h> #include <lcd.c> int main(void) { lcd_init(LCD_DISP_ON_CURSOR_BLINK); lcd_clrscr(); lcd_puts("test"); return 0; }
Siehe auch
Weblinks
- MCS electronics AN #118 - I²C LCD and Keyboard library
- Peter Fleury's Homepage - Interfacing a HD44780 Based LCD to an AVR, LCD library for HD44870 based LCD's