Hallo,
ich habe ein LCD-Modul von Reichelt gekauft von Electrnic Assembly
gekauft und versuche diesen in C zu initialisieren.
Es soll angeblich einen HD44780 Controller besitzen bzw einen "nicht
Kompaktiblem" was ich vermute.
Ich habe das LCD laut dem Datenblatt nach dem Befehlsatz vom HD44780
initialisiert, aber leider tut sich nichts. Weiss einer, woran das
Problem liegen kann, bzw welche init ich sonst verwenden soll (Von
welchem Controller). Oder hat jemand eine lauffähige Init in C.
Displayer schrieb:> Juergen schrieb:>> Weiss einer, woran das>> Problem liegen kann>> Ja, der Code in Zeile 42 ist falsch und das Display ist falsch> angeschlossen.
Was meinst du damit?
Hallo,
162B-N3LW Unterschiede zu anderen LCD Anzeigen:
https://www.elpro.org/de/index.php?controller=attachment&id_attachment=10111
Ein "POWER-ON-RESET" habe ich bisher bei anderen LCD des Formats 2xx 16
Zeichen nicht gesehen.
Wenn man einem Thread zum 162B-N3LW hier im Forum liest, so ist es wohl
wichtig das "POWER-ON-RESET" Timing einzuhalten
Karl M. schrieb:> Hallo Juergen,>> das LCD sollte mit fast jedem LCD Treiber laufen, wobei die 4Bit> Initialisierung komisch aussieht, da man sonst 3 malig das Nibbel 0x03> mit entsprechendem Zeitverhalten sendet.>> http://cdn-reichelt.de/documents/datenblatt/A500/L...>> Welche Sprache verwendest Du ?> LunaAVR hat ein LCD 4Bit Interface (Lcd4.interface) das man einfach> verwenden kann, und bei Bedarf auch parametrisieren kann.>> Die Dokumentation steckt direkt im Lcd4.interface DokuWiki oder auch in> diesem Beitrag:> "http://forum.myluna.de/viewtopic.php?f=1&t=1157&p=...>> http://avr.myluna.de/doku.php
DelayMs(15);
LCD_cmd4(0x30);
DelayMs(5);
LCD_cmd4(0x30);
DelayMs(5);
LCD_cmd4(0x30);
DelayMs(5);
LCD_cmd4(0x20);
DelayMs(5);
LCD_cmd4(0x28);
LCD_cmd4(0x0F);
LCD_cmd4(0x01);
LCD_cmd4(0x06);
Ich sehe gar nichts, außer die blaue Displaybeleuchtung.
RW liegt auf GND. Sonst sehe ich nicht, wenn ich am Kontrast drehe, sehe
ich entweder gar nichts oder die weisse Balken
Karl M. schrieb:> Hallo,>> 162B-N3LW Unterschiede zu anderen LCD Anzeigen:>> https://www.elpro.org/de/index.php?controller=atta...>> Ein "POWER-ON-RESET" habe ich bisher bei anderen LCD des Formats 2xx 16> Zeichen nicht gesehen.> Wenn man einem Thread zum 162B-N3LW hier im Forum liest, so ist es wohl> wichtig das "POWER-ON-RESET" Timing einzuhalten
Genau, das Datenblatt habe ich auch.
Aber laut HD44780 soll man ein Pause von 15ms einhalten.
laut dem Datenblatt 10ms
Hallo Juergen,
was ist den LCD_cmd4()?
bei der 4Bit Init sendet man nur 4Bit, also ein Nibbel, danach aber 8Bit
Kommandos, die als 2x 4Bit übertragen werden müssen.
Das hast Du in deinem Programm wohl nicht gemacht.
Karl M. schrieb:> Hallo Juergen,>> was ist den LCD_cmd4()?>> bei der 4Bit Init sendet man nur 4Bit, also ein Nibbel, danach aber 8Bit> Kommandos, die als 2x 4Bit übertragen werden müssen.>> Das hast Du in deinem Programm wohl nicht gemacht.
wie soll ich denn die befehle sonst senden?
Karl M. schrieb:> Nachtrag,>> ich verweise gerne auch auf Sprut.de dort findet man vielen weitgehende> Infos:>> http://www.sprut.de/electronic/lcd/
Das habe ich mir ausführlich angeschaut. Es passt ja alles von den
Werten, so wie es sein soll
Juergen schrieb:> Es passt ja alles von den> Werten, so wie es sein soll
Ich habe immer noch kein Programm und keinen Stromlaufplan gesehen, wie
soll man denn feststelln, ob alles richtig ist?
Hallo,
hast Du verstanden, was ich hier geschrieben habe ?
Ich denke nicht !
Juergen schrieb:>> Hallo Juergen,>>>> was ist den LCD_cmd4()?>>>> bei der 4Bit Init sendet man nur 4Bit, also ein Nibbel, danach aber 8Bit>> Kommandos, die als 2x 4Bit übertragen werden müssen.>>>> Das hast Du in deinem Programm wohl nicht gemacht.
Hallo,
wie oben schon vermutet wurde sendest Du die 0x30 als kommando im
4Bit-Mode.
Das ist falsch. Das Display ist nach PowerOn im 8Bit-Mode. Es muß also
0x3 als High-Nibble an die Datenleitungen und dann nur einen E-Impuls.
Die unteren 4 Bit, die nicht angeschlossen sind, werden vom Display
ignoriert.
Erst nach den Senden der 0x2 ist das Display im 4Bit-Mode und will das
Low-Nibble mit dem 2. E-Takt haben.
Also auch die 0x2 wird nur mit einem E-Clock geschickt, erst die 0x28
werden als 4Bit-Daten übernommen.
Siehe auch Datenblatt des HD44780.
Gruß aus Berlin
Michael
Danke Michael U.,
vielleicht merkt er nun, dass das Programm fehlerhaft ist.
---
Peter Dannegger (Peda) zeigt in seinem "LCD Tutorial 1001" auch eine
richtige Implementierung !
http://www.avrfreaks.net/forum/tutc-lcd-tutorial-1001
Karl M. schrieb:> Hallo,>> hast Du verstanden, was ich hier geschrieben habe ?> Ich denke nicht !>> Juergen schrieb:> Hallo Juergen,>> was ist den LCD_cmd4()?>> bei der 4Bit Init sendet man nur 4Bit, also ein Nibbel, danach aber 8Bit> Kommandos, die als 2x 4Bit übertragen werden müssen.>> Das hast Du in deinem Programm wohl nicht gemacht.
Nein, anscheinend nicht, kannst du es mir genauer erklaren
Karl M. schrieb:> Hallo,>> hast Du verstanden, was ich hier geschrieben habe ?> Ich denke nicht !>> Juergen schrieb:> Hallo Juergen,>> was ist den LCD_cmd4()?>> bei der 4Bit Init sendet man nur 4Bit, also ein Nibbel, danach aber 8Bit> Kommandos, die als 2x 4Bit übertragen werden müssen.>> Das hast Du in deinem Programm wohl nicht gemacht.
Nein, anscheinend nicht, kannst du es mir genauer erklaren
Michael U. schrieb:> Hallo,>> wie oben schon vermutet wurde sendest Du die 0x30 als kommando im> 4Bit-Mode.> Das ist falsch. Das Display ist nach PowerOn im 8Bit-Mode. Es muß also> 0x3 als High-Nibble an die Datenleitungen und dann nur einen E-Impuls.> Die unteren 4 Bit, die nicht angeschlossen sind, werden vom Display> ignoriert.>> Erst nach den Senden der 0x2 ist das Display im 4Bit-Mode und will das> Low-Nibble mit dem 2. E-Takt haben.> Also auch die 0x2 wird nur mit einem E-Clock geschickt, erst die 0x28> werden als 4Bit-Daten übernommen.>> Siehe auch Datenblatt des HD44780.>> Gruß aus Berlin> Michael
Und der Rest passt??? Meinst du danach geht es?
Hallo,
ich habe Dein Bitgeschiebe nicht überprüft, wirst Du ja merken, sonst
melde Dich eben nochmal.
Ich weiß nicht, wie schnell Dein MSP439 mit den Pins wackelt, E-Clock
muß mindestens 450ns lang sein, da muß also evtl noch eine kurze
Verzögerung rein.
asm("NOP"); müßte da ja auch gehen, evtl ein paar hintereinander
zwischen H- und L Flanke von E-Clock.
Gruß aus Berlin
Michael
>Und der Rest passt??? Meinst du danach geht es?
Nein, da ist noch viel mehr falsch.
Rechne mal aus was hier jeweils als Zwischenschritt herauskommt.
cmd = (cmd & 0x0F);
cmd = (cmd << 4) & 0xF0;
Genaugenommen brauchst du den ganzen Kram gar nicht.
Du musst nur deine if(cmd & (1 << bla)) anpassen.
holger schrieb:> Und der Rest passt??? Meinst du danach geht es?>> Nein, da ist noch viel mehr falsch.>> Rechne mal aus was hier jeweils als Zwischenschritt herauskommt.>> cmd = (cmd & 0x0F);> cmd = (cmd << 4) & 0xF0;>> Genaugenommen brauchst du den ganzen Kram gar nicht.> Du musst nur deine if(cmd & (1 << bla)) anpassen.
0F ist 00001111
F0 ist 11110000
Werte Werte werden an die Variable Cmd übergeben.
Meine IF cmd.... Meine ich ist richtig, war sehr lange dran, was ist
Denn daran falsch? Bin über jede Hilfe höchst erfreut
Moin,
Datenblatt S. 4 nicht vollständig gelesen ...
Initialisierung 4-Bit-Mode:
1
voidLCD_init(void)
2
{
3
DelayMs(15);// Verzögerung mindestens 15Ms
4
5
LCD_cmd2(0x20);// Umschaltbefehl von 8-Bit auf 4-Bit
6
DelayMs(5);// Verzögerung mindestens 100µs
7
8
LCD_cmd4(0x28);// 28 für 4 Bit mode
9
LCD_cmd4(0x0F);// Schaltet das Display an
10
LCD_cmd4(0x01);// Cursor bewegt sich nach rechts
11
LCD_cmd4(0x06);// Löscht das Display
12
}
Ich habe da ein "cmd2()" reingeschrieben, weil für den Umchaltbefehl nur
1 nibble (4-Bit) übertragen werden darf. Also dort bitte nur den ersten
Teil Deiner cmd4()-Routine bis einschl. 1. "enable-Sequenz". Das
versuchen Dir Michael bzw. Karl schon ein Weilchen zu erklären.
Den "8-Bit-Initialisierungs-Senf" vorher brauchst Du lt. Datenblatt
nicht.
Ob Deine delays nun alle korrekt sind, solltest Du nochmal prüfen. Auf
jeden Fall musst Du hier
1
P8OUT=0x80;// En = 1;
2
DelayUs(1);
3
P8OUT=0x00;// En = 0;
ein delay (1 Mirkosekunde) einbauen, damit das Display den enable-Impuls
(fallende Flanke) überhaupt registrieren kann (auch das schrieb Michael
schon). Keine Ahnung, wie Dein MSP getaktet ist - aber etwas mehr an
Wartezeit kann nicht schaden, damit das Display die fallende Flanke
sicher erkennen kann.
Ich gehe davon aus, dass Du Pin5 auf GND geschaltet hast.
Hast DU mal geschaut, wie steil die steigende/fallende Flanke des
enable-Impulses ist? Lt. Datenblatt dürfen das max. 25 nS sein. Falls
Dein MC das nicht schafft solltest Du den Hinweis "*) Important
parameter! Use "74LS" or "74HC" gate" beachten.
Dieter F. schrieb:> Moin,>> Datenblatt S. 4 nicht vollständig gelesen ...>> Initialisierung 4-Bit-Mode:> void LCD_init(void)> {> DelayMs(15); // Verzögerung mindestens 15Ms>> LCD_cmd2(0x20); // Umschaltbefehl von 8-Bit auf 4-Bit> DelayMs(5); // Verzögerung mindestens 100µs> }> Den "8-Bit-Initialisierungs-Senf" vorher brauchst Du lt. Datenblatt> nicht.>> Ob Deine delays nun alle korrekt sind, solltest Du nochmal prüfen. Auf> jeden Fall musst Du hier> P8OUT = 0x80; // En = 1;> DelayUs(1);> P8OUT = 0x00; // En = 0;>> ein delay (1 Mirkosekunde) einbauen, damit das Display den enable-Impuls> (fallende Flanke) überhaupt registrieren kann (auch das schrieb Michael> schon). Keine Ahnung, wie Dein MSP getaktet ist - aber etwas mehr an> Wartezeit kann nicht schaden, damit das Display die fallende Flanke> sicher erkennen kann.>> Ich gehe davon aus, dass Du Pin5 auf GND geschaltet hast.Michael U. schrieb:> Hallo,>> Ich weiß nicht, wie schnell Dein MSP439 mit den Pins wackelt, E-Clock> muß mindestens 450ns lang sein, da muß also evtl noch eine kurze> Verzögerung rein.> asm("NOP"); müßte da ja auch gehen, evtl ein paar hintereinander> zwischen H- und L Flanke von E-Clock.
Hallo nochmal und frohe Weihnachten.
So habe es jetzt nochmal geändert. Hoffe das ist richtig so, aber leider
geht es immer noch nicht. Was habe ich noch nicht beachtet? Ja, Pin5
liegt auf GND.
Ausjefenfall vielen dank jetzt schon mal für die Tolle Hilfe, ihr seid
grosse Klasse
Das hier läuft bei dir schief:
byte = (byte & 0x0F); // Variable Byte wird mit oberen 4 Bits
verändert
Das einzige was hier passiert ist das die oberen 4 Bits gelöscht werden.
Aber die brauchst du doch noch!
Als nächstes gibst du die unteren 4 Bits aus, es müssen aber die oberen
4 Bits zuerst ausgegeben werden. Die sind jetzt aber immer 0.
Die nächste Katastrophe:
byte = (byte<<4) & 0xF0; // Variable Byte wird mit unteren 4
Bits verändertn
Du schiebst die unteren 4 Bits nach oben. Wozu? Die unteren 4 Bits
werden dabei mit 0 gefüllt.
Das "& 0xF0" setzt die unteren 4 Bits nochmal auf 0.
Dann gibst du die unteren 4 Bits aus die immer 0 sind.
Deine Routinen geben immer nur 0 aus.
Man könnte das jetzt anpassen, aber ich empfehle einen kompletten Umbau.
Als erstes eine Routine zur Ausgabe eines Nibbles bauen. Die brauchst du
für später sowieso noch.
1
voidLCD_Nibble(unsignedchardata)
2
{
3
uint8_tPortwertA;// Variable deklarieren ohne Vorzeichen Integer 8-Bit Typ
4
uint8_tPortwertB;// Variable deklarieren ohne Vorzeichen Integer 8-Bit Typ
5
6
PortwertA=0;// Variable löschen
7
PortwertB=0;// Variable löschen
8
9
if(data&(1<<0))// Bit 0
10
PortwertA|=(1<<3);// Um 3 Stellen nach links verschieben (P1.3)
11
if(data&(1<<1))// Bit 1
12
PortwertA|=(1<<2);// Um 2 Stellen nach links verschieben (P1.2)
13
if(data&(1<<2))// Bit 2
14
PortwertB|=(1<<3);// Um 3 Stellen nach links verschieben (4.3)
15
if(data&(1<<3))// Bit 3
16
PortwertB|=(1<<0);// Um 0Stellen nach links verschieben (4.0)
17
18
P1OUT=PortwertA;// Variable gibt Inhalt an P1
19
P4OUT=PortwertB;// Variable gibt Inhalt an P4
20
21
P8OUT=0x04;// En = 1;
22
P8OUT=0x00;// En = 0;
23
DelayUs(5000);// Viel zu lang, kann man später aber noch kürzer machen
24
}
Dann LCD_dat4() umschreiben:
1
voidLCD_dat4(unsignedchardata)
2
{
3
P3OUT=0x80;// RS=1
4
LCD_Nibble(data>>4);
5
LCD_Nibble(data);
6
}
Dann LCD_cmd4() umschreiben:
1
voidLCD_cmd4(unsignedchardata)
2
{
3
P3OUT=0x00;// RS=0
4
LCD_Nibble(data>>4);
5
LCD_Nibble(data);
6
}
LCD_Init() anpassen:
1
voidLCD_init(void)
2
{
3
DelayUs(15000);// Verzögerung indestens 15Ms
4
LCD_Nibble(0x3);// Interface auf 8-Bit setzen
5
DelayUs(5000);// Verzögerung mindestens 5Ms
6
7
LCD_Nibble(0x3);// Interface auf 8-Bit setzen
8
DelayUs(5000);// Verzögerung mindestens 5Ms
9
10
LCD_Nibble(0x3);// Interface auf 8-Bit setzen
11
DelayUs(5000);// Verzögerung mindestens 5Ms
12
13
LCD_Nibble(0x2);// Interface auf 4-Bit setzen
14
DelayUs(5000);// Verzögerung mindestens 5Ms
15
16
LCD_cmd4(0x28);// 28 für 4 Bit mode
17
LCD_cmd4(0x0F);// Schaltet das Display an
18
LCD_cmd4(0x01);// Cursor bewegt sich nach rechts
19
LCD_cmd4(0x06);// Löscht das Display
20
}
So kommst du wenigstens auf den richtigen Weg.
Ob deine Portoperationen so richtig sind weiss ich nicht,
da ich den Controller nicht kenne.
holger schrieb:> So kommst du wenigstens auf den richtigen Weg.> Ob deine Portoperationen so richtig sind weiss ich nicht,> da ich den Controller nicht kenne.
Funktioniert leider immer noch nicht.Haben wir noch irgendwas übersehen?
Enable wird zu kurz sein;) Mal so ändern:
P8OUT = 0x04; // En = 1;
DelayUs(5000); // Viel zu lang, kann man später
aber P8OUT = 0x00; // En = 0;
DelayUs(5000); // Viel zu lang, kann man später
aber noch kürzer machen
Hallo Juergen,
unabhängig von den vielen Vorschlägen, ich würde Peter Danneggers
Implementierung wählen, hast Du dich noch nicht um das Datenblatt und
dem "POWER-ON-RESET" gekümmert.
Um einen zu verstehen, was das soll und wie Du es umsetzen möchtest.
Karl M. schrieb:> Ein "POWER-ON-RESET" habe ich bisher bei anderen LCD des Formats 2xx 16> Zeichen nicht gesehen.> Wenn man einem Thread zum 162B-N3LW hier im Forum liest, so ist es wohl> wichtig das "POWER-ON-RESET" Timing einzuhalten
Frickelfritze schrieb:> Juergen schrieb:>> Haben wir noch irgendwas übersehen?>> Register Select muss auch beim Init (korrekt) bedient werden.
Was ist damit gemeint?Wie kann ich das realisieren oder umsetzen?
holger schrieb:> Enable wird zu kurz sein;) Mal so ändern:>> P8OUT = 0x04; // En = 1;> DelayUs(5000); // Viel zu lang, kann man später> aber P8OUT = 0x00; // En = 0;> DelayUs(5000); // Viel zu lang, kann man später> aber noch kürzer machen
Tut mir Leid Holger, aber immer noch nicht... Bekomme langsam die
Krise...
Juergen schrieb:> Was ist damit gemeint?
Oh Mann. Die RS Leitung. Schau die Beschaltung deines LCDs an.
Da man ja den aktuellen Code nicht komplett zu Gesicht bekommt
weiss ja kein Schwein ob du die Leitung bedienst oder nicht.
In den letzten Kommentaren (source-Schnipsel) kommt jedenfalls
die Bedienung von RS nicht vor.
Karl M. schrieb:> Hallo Juergen,>> unabhängig von den vielen Vorschlägen, ich würde Peter Danneggers> Implementierung wählen, hast Du dich noch nicht um das Datenblatt und> dem "POWER-ON-RESET" gekümmert.> Um einen zu verstehen, was das soll und wie Du es umsetzen möchtest.>> Karl M. schrieb:>> Ein "POWER-ON-RESET" habe ich bisher bei anderen LCD des Formats 2xx 16>> Zeichen nicht gesehen.>> Wenn man einem Thread zum 162B-N3LW hier im Forum liest, so ist es wohl>> wichtig das "POWER-ON-RESET" Timing einzuhalten
Das Datenblatt habe ich mir jetzt bestimmt 10 mal durchgelesen.... Der
Punkt 74LS... sagt mir nichts bzw verstehe ich nicht, wie ich das
umsetzen soll.
Beim Poweronreset steht eine Zeit von min 0.1 bis 10 ms,
diese Zeit braucht er bis er die Flanke erreicht, ich warte ja am anfang
15ms, als warte ich länger als genug :-)
Frickelfritze schrieb:> Juergen schrieb:>> Was ist damit gemeint?>> Oh Mann. Die RS Leitung. Schau die Beschaltung deines LCDs an.>> Da man ja den aktuellen Code nicht komplett zu Gesicht bekommt> weiss ja kein Schwein ob du die Leitung bedienst oder nicht.>> In den letzten Kommentaren (source-Schnipsel) kommt jedenfalls> die Bedienung von RS nicht vor.
Das ist der vollständige Code :-)
also oben in der Textdatei.
das ist nur ein Auszug. Ich benutze es natürlich
void LCD_dat4(unsigned char data)
{
P3OUT = 0x80; // RS=1
LCD_Nibble(data >> 4);
LCD_Nibble(data);
}
void LCD_cmd4(unsigned char data)
{
P3OUT = 0x00; // RS=0
LCD_Nibble(data >> 4);
LCD_Nibble(data);
}
Juergen schrieb:> das ist nur ein Auszug. Ich benutze es natürlich
Aber beim Schreiben von Nibbles (im Init) wird das RS
nicht explizit bedient sondern steht zufällig igendwie.
Frickelfritze schrieb:> Aber beim Schreiben von Nibbles (im Init) wird das RS> nicht explizit bedient sondern steht zufällig igendwie.
Und dann soll der Codeteil funktionieren ?
Was sagt Dir das Datenblatt, welche Werte muss R/W, RS, E haben ?
Frickelfritze schrieb:> holger schrieb:>> LCD_Init() anpassen:>> void LCD_init(void)>> {> .............>> }>> Beim Eintritt in LCD_Init ist RS vermutlich undefiniert.
Alle Werte müssen LOW sein.
Habe beide Werte auf 0 gesetzt vor der Init.
P8OUT = 0x00; // En = 0;
P3OUT = 0x00; // RS = 0;
Wieder nichts :-(
holger schrieb:> P4DIR = 0x06; // D6 und D7 bestimmen>> Müsste das nicht 0x09 sein?
Du Bist der Beste. Das War der Fehler. Ich bin ein Idiot :-)
Nur, er zeigt was komisches an....
Hallo,
na, ist ja eine Menge passiert inzwischen. Schön, daß man jetzt was zu
sehen bekommt.
Zum jetzigen Problem:
const unsigned char Msg1[] = "LCD Test";
const unsigned char Msg2[] = "MSP430";
Du initialisierst hier ein Array of CHAR mit 9 Zeichen (8 Buchstaben und
0-Byte) und ein Array mit 7 Zeichen.
Und hier
for(i=0;i<16;i++)
{
LCD_dat4(Msg1[i]);
DelayUs(5000);
}
LCD_cmd4(0xc0);
for(i=0;i<16;i++)
{
LCD_dat4(Msg2[i]);
DelayUs(5000);
}
Gibst Du aus diesen Arrays jeweils 16 Zeichen aus...
Alles, was nach dem jeweiligen Arrayende kommt, ist zufälliger
Speicherinhalt.
Wenn man nur 8 bzw. 6 Buchstaben als Text hat, sollte man auch nicht
mehr ausgeben.
Gruß aus Berlin
Michael