Forum: Mikrocontroller und Digitale Elektronik 40x4 LCD Modul Probleme


von Andre G. (andgst01)


Lesenswert?

Schönen Sonntag Abend!

Ich versuche gerade ein 40x4 Zeichen LCD - Modul (NHD-0440WH-ATMI-JT#, 
Datenblatt: 
https://www.newhavendisplay.com/specs/NHD-0440WH-ATMI-JT.pdf) an einem 
AtMega 2560 zum Laufen zu bringen.

Im Datenblatt des LCDs ist ein Beispiel angegeben wie man das LCD Modul 
initialisiert.
Das verwende ich, aber irgendwie funktioniert es nicht wirklich.
In der ersten Zeile des Displays sind immer alle Pixel aktiv, trotz 
löschen des Displays in der initLCD Funktion.

Einen Verdrahtungsfehler schließe ich aus, wenn ich nämlich den Cursor 
auf das erste Zeichen in der ersten Zeile setzt und blinken lasse, dann 
sieht man dass das Kästchen auf dem Display flackert ("blinkender 
Cursor" aber nicht wirklich).
Wenn ich einen Verdrahtungsfehler gemacht hätte (E1 Leitung nicht 
angeschlossen) dann würde das nich passieren, die obere Hälfte würde 
dann einfch "nichts tun".

Ja, der Kontrast ist korrekt eingestellt, wenn ich den Cursor in Zeile 3 
blinken lasse dann sehe ich das ohne Probleme.

Hier ist der Code:
1
/*
2
3
Ports:
4
######
5
6
7
PB1    SCK for programmer
8
PB2    MOSI for programmer
9
PB3    MISO for programmer
10
11
PC0    LCD D0
12
PC1    LCD D1
13
PC2    LCD D2
14
PC3    LCD D3
15
PC4    LCD D4
16
PC5    LCD D5
17
PC6    LCD D6
18
PC7    LCD D7
19
20
PG0    LCD E2
21
PG1    LCD E1
22
PG2    LCD RS
23
24
*/
25
26
#define F_CPU 16000000UL      //Clock is 16MHz
27
28
#include <avr/io.h>
29
#include <util/delay.h>
30
31
void LCD_Command_TOP(char i) //Top half of the display
32
{
33
  PORTC = i;
34
  PORTG = PORTG & 0b11111011;  //Set RS to 0
35
  PORTG = PORTG | 0b00000010;  //set E1 to 1
36
  _delay_ms(2);
37
  PORTG = PORTG & 0b11111101;  //set E1 to 0
38
}
39
void LCD_Command_BOT(char i) //Bottom half of the display
40
{
41
  PORTC = i;
42
  PORTG = PORTG & 0b11111011;  //Set RS to 0
43
  PORTG = PORTG | 0b00000001;  //set E2 to 1
44
  _delay_ms(2);
45
  PORTG = PORTG & 0b11111110;  //set E2 to 0
46
}
47
/************************************************************************/
48
void LCD_Data_TOP(char i) //Top half of the display
49
{
50
  PORTC = i;
51
  PORTG = PORTG | 0b00000100;    //set RS to 1
52
  PORTG = PORTG | 0b00000010;    //set E1 to 1
53
  _delay_ms(2);
54
  PORTG = PORTG & 0b11111101;    //set E1 to 0
55
}
56
void LCD_Data_BOT(char i) //Bottom half of the display
57
{
58
  PORTC = i;
59
  PORTG = PORTG | 0b00000100;    //set RS to 1
60
  PORTG = PORTG | 0b00000001;    //set E2 to 1
61
  _delay_ms(2);
62
  PORTG = PORTG & 0b11111110;    //set E2 to 0
63
}
64
/************************************************************************/
65
void init_LCD()
66
{
67
  _delay_ms(15);
68
  LCD_Command_TOP(0x30); //Wake up
69
  LCD_Command_BOT(0x30);
70
  _delay_ms(5);
71
  LCD_Command_TOP(0x30); //Wake up
72
  LCD_Command_BOT(0x30);
73
  _delay_ms(5);
74
  LCD_Command_TOP(0x30); //Wake up
75
  LCD_Command_BOT(0x30);
76
  _delay_ms(5);
77
  _delay_ms(0x38);
78
  //Function Set = 8bit mode; 2‐line; 5x8
79
  LCD_Command_BOT(0x38);
80
  
81
  LCD_Command_TOP(0x08); //Turn off display
82
  LCD_Command_BOT(0x08);
83
  LCD_Command_TOP(0x01); //Clear display
84
   LCD_Command_BOT(0x01);
85
   LCD_Command_TOP(0x06); //Entry mode cursor increment
86
   LCD_Command_BOT(0x06);
87
   LCD_Command_TOP(0x0c); //Turn on display; no cursor
88
   LCD_Command_BOT(0x0c);
89
}
90
91
void Init()
92
  {
93
    //set up the IO registers
94
    DDRC = 0xFF;        //PORT C is all outputs for the LCD
95
    DDRG = DDRG | 0b00000111;  //PORT G pins 0, 1 and 2 are used as outputs for the LCD
96
    //init the LCD
97
    init_LCD();
98
  }
99
100
int main(void)
101
{
102
  Init();
103
104
  //clear the top part of the LCD
105
  LCD_Command_TOP(0x01);
106
  //blinking cursor
107
  LCD_Command_TOP(0b00001011);
108
    
109
    while(1)
110
    {
111
    //do nothing
112
    }
113
}

Ist vielleicht einfach das Display defekt (ESD?), oder was übersehe ich 
hier?

von Pieter (Gast)


Lesenswert?

ist das richtig?

76  _delay_ms(5);

77   _delay_ms(0x38); ???

78   //Function Set = 8bit mode; 2‐line; 5x8

79   LCD_Command_BOT(0x38); und TOP???

von Andre G. (andgst01)


Lesenswert?

Pieter schrieb:
> ist das richtig?
>
> 76  _delay_ms(5);
>
> 77   _delay_ms(0x38); ???
>
> 78   //Function Set = 8bit mode; 2‐line; 5x8
>
> 79   LCD_Command_BOT(0x38); und TOP???

Das "delay 0x38" finde ich auch etwas seltsam, aber so steht es im 
Datenblatt.


Das mit dem fehlenden "LCD_Command_TOP(0x38)" steht ebenso im 
Datenblatt, deshalb habe ich es ohne nachzudenken übernommen.

(Ich dachte "vielleicht muss man ja nur dem 'unteren' LCD controller 
sagen dass 8 bits verwendet werden und der gibt das dann an den oberen 
controller weiter")

Wenn ich "LCD_Command_TOP(0x38)" dazuschreibe geht es perfekt!


Was lerne ich daraus:
Datenblätter sind nicht perfekt und enthalten auch Fehler!

Danke!

von Thomas Z. (usbman)


Lesenswert?

Ich würde ja sagen die E Signale sind falsch. 2 ms High und 0 ms Lo 
passt irgendwie nicht zusammen.
LCD_Data bzw LCD_Comnand Funktionen machen nichts mit dem Parameter. Das 
Ding dürfte nicht ohne Warnings compilieren.

: Bearbeitet durch User
von Andre G. (andgst01)


Lesenswert?

Thomas Z. schrieb:
> Ich würde ja sagen die E Signale sind falsch. 2 ms High und 0 ms Lo
> passt irgendwie nicht zusammen.
> LCD_Data bzw LCD_Comnand Funktionen machen nichts mit dem Parameter. Das
> Ding dürfte nicht ohne Warnings compilieren.

Was?

Erste Zeile in den Funktionen:
PORTC = i;

Das ist nicht "nichts damit machen" ...

von Thomas Z. (usbman)


Lesenswert?

Andre G. schrieb:
> Das ist nicht "nichts damit machen" ...

stimmt hatte ich überlesen, das E Signal ist trotzdem komisch.

von Andre G. (andgst01)


Lesenswert?

Thomas Z. schrieb:
> Andre G. schrieb:
>> Das ist nicht "nichts damit machen" ...
>
> stimmt hatte ich überlesen, das E Signal ist trotzdem komisch.

Naja wenn ich noch mehr Verzögerungen einfüge, dann würde ein kompletter 
Schreibzyklus dauert eh schon ungefähr 2 Sekunden. (Ein Zeichen in jedes 
"Kästchen" schreiben)

Und es funktioniert ja ...

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Ein kompletter E Cycle soll 1200ns dauern, dabei ist die minimale 
Pulslänge für E high minimal 140ns. 1ms ist also deutlich übertrieben. 
Selbst wenn man alle Zeiten gegenüber dem DB verdoppelt, kommt man mit 
2µs aus, davon 1µs high und min. 1µs low.
Siehe das DB des LCD, Seite 7.

: Bearbeitet durch User
von Andre G. (andgst01)


Lesenswert?

Matthias S. schrieb:
> Ein kompletter E Cycle soll 1200ns dauern, dabei ist die minimale
> Pulslänge für E high minimal 140ns. 1ms ist also deutlich übertrieben.
> Selbst wenn man alle Zeiten gegenüber dem DB verdoppelt, kommt man mit
> 2µs aus, davon 1µs high und min. 1µs low.
> Siehe das DB des LCD, Seite 7.

Wieso hat der Hersteller in dem Beispielcode dann so ewig lange 
Wartezeiten?

Um "copy paste" - Programmierer zu ärgern?

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Andre G. schrieb:
> Wieso hat der Hersteller in dem Beispielcode dann so ewig lange
> Wartezeiten?

Woher soll ich das wissen? :-P
Vllt. kannten die Autoren den '_delay_us()' Aufruf noch nicht, der kommt 
erst im Kurs für Fortgeschrittene?
Ernst nehmen sollte man die langen Zeiten in der Init Phase. Da kann man 
ruhig etwas länger stillhalten. Ob man da 15ms wartet oder 50ms, ist 
auch unerheblich.

von Andre G. (andgst01)


Lesenswert?

Matthias S. schrieb:
> Andre G. schrieb:
>> Wieso hat der Hersteller in dem Beispielcode dann so ewig lange
>> Wartezeiten?
>
> Woher soll ich das wissen? :-P
> Vllt. kannten die Autoren den '_delay_us()' Aufruf noch nicht, der kommt
> erst im Kurs für Fortgeschrittene?
> Ernst nehmen sollte man die langen Zeiten in der Init Phase. Da kann man
> ruhig etwas länger stillhalten. Ob man da 15ms wartet oder 50ms, ist
> auch unerheblich.

Ja, das ist mir schon klar.
Die Initialisierung kann ruhig lange dauern, das stört niemanden (oder 
mich nicht).

Ich habe ein wenig herumprobiert, den Code so gelassen wie er ist, und 
einfach mal die delays in den Funktionen LCD_Data_xxx und 
LCD_Command_xxx geändert.
Bei 100 µS delay aktualisiert das Display vernünftig schnell und alles 
wird immer noch vom Display korrekt angezeigt (keine falsch 
interpretierten bytes, ...).

von Thomas Z. (usbman)


Lesenswert?

Andre G. schrieb:
> Wieso hat der Hersteller in dem Beispielcode dann so ewig lange
> Wartezeiten?

Im Datenblatt steht übrigens nichts von delay_ms(2) dort steht delay(2) 
also vermutlich 2 µs.

von Andre G. (andgst01)


Lesenswert?

Thomas Z. schrieb:
> Andre G. schrieb:
>> Wieso hat der Hersteller in dem Beispielcode dann so ewig lange
>> Wartezeiten?
>
> Im Datenblatt steht übrigens nichts von delay_ms(2) dort steht delay(2)
> also vermutlich 2 µs.

Oh, das erklärt einiges ...

von Purzel H. (hacky)


Lesenswert?

Zu den Wartezeiten. Das Booten nach dem Powerup dauert immer sehr lange. 
Aber eigentlich nur das. Sonst sollte man 5 Refreshes des Inhaltes pro 
Sekunde hinbekommen. Die Aenderung sollte aber Minimal sein, sonst wirkt 
es nervoes.

von Bernhard M. (boregard)


Lesenswert?

Andre G. schrieb:
> ...
>
1
> ...
2
>   LCD_Command_BOT(0x30);
3
>   _delay_ms(5);
4
>   _delay_ms(0x38);
5
>   //Function Set = 8bit mode; 2‐line; 5x8
6
>   LCD_Command_BOT(0x38);
7
>

Das ist falsch, das muss sein:
1
...
2
  LCD_Command_BOT(0x30);
3
  _delay_ms(5);
4
  //Function Set = 8bit mode; 2‐line; 5x8
5
  LCD_Command_TOP(0x38);
6
  LCD_Command_BOT(0x38);

Denn so hast Du TOP nicht richtig initialisiert (es sind ja 2 
Controller).

von Andre G. (andgst01)


Lesenswert?

Bernhard M. schrieb:
> Andre G. schrieb:
>> ...
>>
1
>> ...
2
>>   LCD_Command_BOT(0x30);
3
>>   _delay_ms(5);
4
>>   _delay_ms(0x38);
5
>>   //Function Set = 8bit mode; 2‐line; 5x8
6
>>   LCD_Command_BOT(0x38);
7
>>
>
> Das ist falsch, das muss sein:
>
1
> ...
2
>   LCD_Command_BOT(0x30);
3
>   _delay_ms(5);
4
>   //Function Set = 8bit mode; 2‐line; 5x8
5
>   LCD_Command_TOP(0x38);
6
>   LCD_Command_BOT(0x38);
7
>
>
> Denn so hast Du TOP nicht richtig initialisiert (es sind ja 2
> Controller).

Stimmt.
Wenn ich das jetzt richtig verstanden habe dann sind das eigentlich zwei 
2x40 Displays die "parallelgeschaltet" sind was die Datenleitungen 
angeht.
Über die E1 und E2 Leitungen kann man auswählen welches Display man 
ansprechen will, das obere oder das untere.

Dann könnte man ja eigentlich zum Löschen des ganzen Displays den 
Lösch-Code senden und beide E Leitungen aktivieren, oder?

von Teo D. (teoderix)


Lesenswert?

Andre G. schrieb:
> Dann könnte man ja eigentlich zum Löschen des ganzen Displays den
> Lösch-Code senden und beide E Leitungen aktivieren, oder?

Ja, könntest Du... NUR ist es meist ratsam entweder nur die betreffenden 
Stellen zu überschreiben oder gleich das komplette Display neu zu 
befüllen. "Clear Display" führt meist nur zu unschönem Flimmern.

von Andre G. (andgst01)


Lesenswert?

Teo D. schrieb:
> Andre G. schrieb:
>> Dann könnte man ja eigentlich zum Löschen des ganzen Displays den
>> Lösch-Code senden und beide E Leitungen aktivieren, oder?
>
> Ja, könntest Du... NUR ist es meist ratsam entweder nur die betreffenden
> Stellen zu überschreiben oder gleich das komplette Display neu zu
> befüllen. "Clear Display" führt meist nur zu unschönem Flimmern.

Ja, aktuelle mache ich das so dass ich im µC einen String habe der den 
aktuell anzuzeigenden Text speichert.
Dieser wird ein paar mal pro Sekunde auf das Display geschrieben.

Wenn etwas geändert werden soll, dann wird das in dem String geändert.
(und dann automatisch beim nächsten "Frame update" auf den LCD 
übernommen)

(Ich habe das "Cursor auf Position xy setzen" irgendwie noch nicht 
hinbekommen ...)

von LCD (Gast)


Lesenswert?

Thomas Z. schrieb:
> Andre G. schrieb:
>> Wieso hat der Hersteller in dem Beispielcode dann so ewig lange
>> Wartezeiten?
>
> Im Datenblatt steht übrigens nichts von delay_ms(2) dort steht delay(2)
> also vermutlich 2 µs.

Im Datenblatt stehen in der Tabelle der Kommandos (Seite 6) die nötigen 
Wartezeiten. Entweder 37us oder 1,52ms. Das heißt nicht, dass der 
Zugriff so lange dauern muss, sondern dass man NACH JEDEM Befehl die 
genannte Zeit abwarten muss, da das Display in dieser Zeit beschäftigt 
ist. Bei einem Clear Display oder Return Home sind das eben 1,52ms, 
sonst immer 37us. Statt stumpfsinnig zu warten kann man auch das Busy 
Flag auslesen. Wird aber nicht viel bringen, da das Display trotzdem 
seine Zeit braucht.
Es ist auch noch darauf zu achten, dass die Zeitangaben für eine 
Oszillatorfrequenz von 270kHz gelten. Bei diesem Display ist über die 
Genauigkeit der internen Taktfrequenz keine Angabe gemacht. Oft sind da 
aber 20% zu erwarten, da billige Oszillatoren verwendet werden. Ich 
persönlich würde 2ms und 50us als Wartezeit verwenden.

von Andre G. (andgst01)


Lesenswert?

LCD schrieb:
> Thomas Z. schrieb:
>> Andre G. schrieb:
>>> Wieso hat der Hersteller in dem Beispielcode dann so ewig lange
>>> Wartezeiten?
>>
>> Im Datenblatt steht übrigens nichts von delay_ms(2) dort steht delay(2)
>> also vermutlich 2 µs.
>
> Im Datenblatt stehen in der Tabelle der Kommandos (Seite 6) die nötigen
> Wartezeiten. Entweder 37us oder 1,52ms. Das heißt nicht, dass der
> Zugriff so lange dauern muss, sondern dass man NACH JEDEM Befehl die
> genannte Zeit abwarten muss, da das Display in dieser Zeit beschäftigt
> ist. Bei einem Clear Display oder Return Home sind das eben 1,52ms,
> sonst immer 37us. Statt stumpfsinnig zu warten kann man auch das Busy
> Flag auslesen. Wird aber nicht viel bringen, da das Display trotzdem
> seine Zeit braucht.
> Es ist auch noch darauf zu achten, dass die Zeitangaben für eine
> Oszillatorfrequenz von 270kHz gelten. Bei diesem Display ist über die
> Genauigkeit der internen Taktfrequenz keine Angabe gemacht. Oft sind da
> aber 20% zu erwarten, da billige Oszillatoren verwendet werden. Ich
> persönlich würde 2ms und 50us als Wartezeit verwenden.

Danke1

Nein, Busy-Flag auslesen geht nicht, ich habe den R/!W Pin des Displays 
auf GND gelötet.
(Immer auf WRITE, Pins sparen ...)

Eigentlich könnte man sich ja E2 auch sparen und einfach E1 invertieren.
Wenn man nicht die obere Hälfte anspricht, dann spricht man ja 
zwangsweise mit der unteren Hälfte ...
(Spart einen µC Pin, aber man braucht einen Inverter ...)

von Teo D. (teoderix)


Lesenswert?

Andre G. schrieb:
> Nein, Busy-Flag auslesen geht nicht, ich habe den R/!W Pin des Displays
> auf GND gelötet.
> (Immer auf WRITE, Pins sparen ...)

Lohnt eh nur wenn große Temperaturschwankungen zu erwarten sind. Da 
ändern sich die Taktfrequenzen der Display recht stark.
(LCD schrieb:
> Es ist auch noch darauf zu achten, dass die Zeitangaben für eine
> Oszillatorfrequenz von 270kHz gelten. Bei diesem Display ist über die
> Genauigkeit der internen Taktfrequenz keine Angabe gemacht. Oft sind da
> aber 20% zu erwarten, da billige Oszillatoren verwendet werden. Ich
> persönlich würde 2ms und 50us als Wartezeit verwenden.)


Andre G. schrieb:
> Eigentlich könnte man sich ja E2 auch sparen und einfach E1 invertieren.

Wenn Du aber mehrfach auf das selbe Display schreiben willst, brauchst 
Du jedes mal ein Dummybefehl (Cur.Pos. oä.) für das Andere!

von Andre G. (andgst01)


Lesenswert?

Teo D. schrieb:

> Lohnt eh nur wenn große Temperaturschwankungen zu erwarten sind. Da
> ändern sich die Taktfrequenzen der Display recht stark.

Nein, das Ganze soll bei "Raumtemperatur" betrieben werden.


Teo D. schrieb:
> Andre G. schrieb:
>> Eigentlich könnte man sich ja E2 auch sparen und einfach E1 invertieren.
>
> Wenn Du aber mehrfach auf das selbe Display schreiben willst, brauchst
> Du jedes mal ein Dummybefehl (Cur.Pos. oä.) für das Andere!

Ja, aber ich schreibe eh immer ein ganzes "Frame" also wäre das kein 
Problem.

von Karl B. (gustav)


Lesenswert?

Andre G. schrieb:
> //Function Set = 8bit mode; 2‐line; 5x8

Hi, das ist für zwei Zeilen initialisiert.
Nur zur Erinnerung:
Das Display hat zwei Controller.
Einen für die oberen zwei Zeilen,
einen weiteren für die unteren zwei Zeilen.
Manchmal ist die Reihenfolge auch verschachtelt.
Also z.B. Controller 1 für Zeilen 1 und 3, Controller 2 für Zeilen 2 und 
4.
Die Controller werden nur über den jeweils zugehörigen Enable-Impuls 
angesprochen.
Das Pinout sieht dafür doch schon zwei Enable-Eingänge vor.

"...9 E1 MPU Operation Enable signal. Falling edge triggered for top 2 
line
...
15 E2 MPU Operation enable signal. Falling edge triggered for bottom 2
lines..."

Die Initialisierung muss für beide Controller erfolgen.
Also zweimal dasselbe hintereinander. Nur mit dem richtigen 
Enable-Impuls und auf dem richtigen Pin.
Die Ausgaberoutine muss dementsprechend angepasst werden.
Wird nur momentan ein Zeichen auf Zeile 1 ausgegeben, dann nur ein 
Enable-Impuls, gültig für diese Zeile.
Dann geht die Ausgabe zügig, ohne immer alles durchzurattern.
Probleme mit der Adressierung der Spalten dürften kaum auftreten,
da der HD44780 standardmäßig von 40-zeiligen LCDisplays ausgeht.
Zum Beispiel für ein 16 zeiliges:

Da auch LCDs mit "nur" 16 Spalten Controller verwenden, die ursprünglich 
für
40 Spalten ausgelegt sind, gibt es für die Darstellung von "Fließtexten" 
die
weitere Schwierigkeit, daß der Text nicht automatisch nach Terminalart 
am Ende der
jeweiligen Zeile umgebrochen wird. Es wird vielmehr auch der nicht 
darstellbare
Adressbereich zunächst vollgeschrieben, erst dann erscheint der weitere 
Text auf
Anfang Zeile 2.

Würden keine Positionierungsangaben gesetzt, erschiene die Ziffernfolge
fortlaufend hintereinander auf dem Display.
Bei Adressenincrement also:
0 1 2 3 4 5 6 7 8 9
und bei Adressendecrement:
0
?
Ja, richtig, denn hierbei wird erst der "nicht darstellbare" 
Adressbereich
von "hinten" vollgeschrieben.
Wollte man nun die Ziffernfolge 9 8 7 6 5 4 3 2 1 0 darstellen im
Adressendecrement, müßte nämlich ganz am Anfang eine
Positionierungsangabe gesetzt werden (hex C9).
(Bei Adressendecrement erscheinen also Texte "verkehrt".)

Mit sowas brauchte man sich bei einem 40-zeiligen nicht herumzuärgern.
Zur Sicherheit doch noch einmal ausprobieren.

ciao
gustav

: Bearbeitet durch User
von noiasca (Gast)


Lesenswert?

Andre G. schrieb:
> Eigentlich könnte man sich ja E2 auch sparen und einfach E1 invertieren.
> Wenn man nicht die obere Hälfte anspricht, dann spricht man ja
> zwangsweise mit der unteren Hälfte ...
> (Spart einen µC Pin, aber man braucht einen Inverter ...)

würde ich nicht machen.
Es gibt befehle die du an beide "logischen" Displays senden musst z.B. 
Clear oder das ganze initialisieren am Anfang. Das kannst dann jeweils 
doppelt machen oder eben beide E Pins gemeinsam pulsen.

von Karl B. (gustav)


Lesenswert?

noiasca schrieb:
> Das kannst dann jeweils
> doppelt machen oder eben beide E Pins gemeinsam pulsen.

Hi,
gerade der Enable-Impuls bzw. die Erkennung desselben ist etwas 
kritischer. Auf die Flanke kommt es an.
Schaltungstechnisch wird das meistens im Chip so gelöst, dass durch 
Verschaltung mehrerer Gatter eine Gatterverzögerung erzeugt wird. Am 
Ausgang werden die beiden Zweige wieder zusammengeführt. Dadurch ist die 
Verzögerung gerade so groß, dass nur kurze Flanke übrigbleibt, auf die 
dann getriggert wird.
Also, die E-Pins sollten vom Hardwarestandpunkt aus gesehen nicht direkt 
parallelgeschaltet werden.
Abgesehen davon wird mit jedem Enableimpuls der Adresszähler 
weitergezählt, (je nach Initsequenzauswahl "shift" etc.) auch auf der 
"anderen" Hälfte, wenn beide E-Pins parallelgeschaltet würden.
Welche Folgen das hat? Die Anzeige wandert unten auch. Möchtest Du das 
so?
Was hindert einen eigentlich daran, das Ganze softwaremäßig zu lösen?
Eine Kommandozeile mehr oder weniger macht den Kohl auch nicht fett.
Und an Ports am µC mangelt es doch hier sicherlich auch nicht.
Zur Not kann man ja auch den Vierbit-Modus noch einführen.

ciao
gustav

: Bearbeitet durch User
von Hugo H. (hugo_hu)


Lesenswert?

Das
1
//clear the top part of the LCD
2
  LCD_Command_TOP(0x01);

dauert ein wenig. 1,52 ms nach der fallenden Flanke des 
Enable-Impulses kann es dann weitergehen. DB Seite 6 ganz oben rechts. 
Enable selbst muss nur min. 140 ns auf high sein - die fallende Flanke 
ist der "entscheidende Impuls / Trigger".

Wenn Du das Cusrsor-Kommando gleich "Hinterherschiesst" (ohne die 
Wartezeit von 1,52 ms) dann mag er das nicht ...

: Bearbeitet durch User
von Hugo H. (hugo_hu)


Lesenswert?

Und das

Display ON/
OFF control

0 0 0 0 0 0 1 D C B

D=1: Entire display on
C=1: Cursor on
B=1: Blinking cursor on

hast Du mit 0b0000 1 0 1 1  D = 0 -> Display aus und Blinke-Cursor an 
nicht ganz glücklich umgesetzt ...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.