Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Laderegler Test Tueftler Seite

(4-Bit Ansteuerung mit Busy(I/O Mode))
 
(24 dazwischenliegende Versionen von 11 Benutzern werden nicht angezeigt)
Zeile 127: Zeile 127:
 
|1
 
|1
 
|*
 
|*
|setzt den Cursor auf das Anfang der 1. Zeile (Addresse 0)
+
|setzt den Cursor auf den Anfang der 1. Zeile (Addresse 0)
 
|1.64mS
 
|1.64mS
 
|-  
 
|-  
Zeile 285: Zeile 285:
 
===8-Bit Ansteuerung (Busmode)===
 
===8-Bit Ansteuerung (Busmode)===
  
Für 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.
+
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 389: 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 418: 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 Beispile in der Header Datei lcd.h vorzunehmen:
+
Folgende Einstellungen sind für obiges Beispiele in der Header Datei lcd.h vorzunehmen:
  
 
<pre>
 
<pre>
Zeile 563: Zeile 681:
 
===Ansteuerung über I&sup2;C===
 
===Ansteuerung über I&sup2;C===
  
Nur 2 Prozessor Ports benötigt man bei der I&sup2;C-Ansteuerung. Dazu wird als I&sup2;C Porterweiterungs IC der PCF8574P benötigt.
+
Nur 2 Prozessor Ports benötigt man bei der I&sup2;C-Ansteuerung. Dazu wird als I&sup2;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&sup2;C-Ansteuerung]]
 
[[Bild:lcdmodul_i2c_schem.png|center|thumb|600px|I&sup2;C-Ansteuerung]]
Zeile 593: Zeile 711:
 
   TODO....
 
   TODO....
  
 +
</pre>
 +
 +
====Ansteuerung über I&sup2;C mit PCA9555====
 +
 +
Eine weitere Möglichkeit der I&sup2;C-Ansteuerung besteht in der Nutzug des PCA9555 (16 Bit I&sup2;C I/O Expander) von Philips. Das Display wird im 8-Bit Mode betrieben.
 +
 +
[[Bild:Lcdmodul_i2c_pca9555_schem.png|center|thumb|600px|I&sup2;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 930:
  
 
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).  
 
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 609: Zeile 1.048:
 
* [[AVR]]
 
* [[AVR]]
 
* [[I2C|I&sup2;C-Bus]]
 
* [[I2C|I&sup2;C-Bus]]
 +
* [[LCD an I2C Huckepack auf RN-Miniplatine]]
  
 
==Weblinks==
 
==Weblinks==
Zeile 614: Zeile 1.054:
 
* [http://www.mcselec.com/index.php?option=com_content&task=view&id=82&Itemid=57 MCS electronics AN #118] - I&sup2;C LCD and Keyboard library
 
* [http://www.mcselec.com/index.php?option=com_content&task=view&id=82&Itemid=57 MCS electronics AN #118] - I&sup2;C LCD and Keyboard library
 
* [http://jump.to/fleury Peter Fleury's Homepage] - Interfacing a HD44780 Based LCD to an AVR, LCD library for HD44870 based LCD's
 
* [http://jump.to/fleury Peter Fleury's Homepage] - Interfacing a HD44780 Based LCD to an AVR, LCD library for HD44870 based LCD's
* [http://www.display3000.com Display3000 Homepage] - Verkaufen Farb TFTs und TFT-Komplettlösungen inkl. Bascom Ansteuerung und div. Utilities
 
 
  
 
==Autore(en)==
 
==Autore(en)==

Aktuelle Version vom 11. Juli 2013, 14:53 Uhr

LCD-Modul

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.

8-Bit Ansteuerung. Quelle: Peter Fleury

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.

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 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.

4-Bit Ansteuerung

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.

Ansteuerung über Porterweiterung

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.

I²C-Ansteuerung

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.

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.

...
#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

Autore(en)

m a r v i n


LiFePO4 Speicher Test