Hallo,
ich verwende die LCD Routine von Peter Danneger, funktioniert übrigens
einwandfrei!
Habe ein 4x20 LCD bekommen aber da funktioniert leider nicht bzw. es
funktioniert aber wie ein LCD 2x16 (Routine ist für 2x16).
im Datei lcd_drv.c ist die Formatierung dafür:
#########################################
void lcd_pos( u8 line, u8 column )
{
if( line & 1 )
column += 0x40; // estaba 40
lcd_command( 0x80 + column );
}
########################################
bin ich aber leider nicht ganz schlau geworden, kann mich jemand helfen?
Gruß
Alejandro P. schrieb:> Hallo,> ich verwende die LCD Routine von Peter Danneger, funktioniert übrigens> einwandfrei!
Naja, man sollte den Code, den man verwendet, auch verstehen und nicht
nur unverstanden benutzen.
>> Habe ein 4x20 LCD bekommen aber da funktioniert leider nicht bzw. es> funktioniert aber wie ein LCD 2x16 (Routine ist für 2x16).
Das 4x20 ist von der Ansteuerung her wie ein 2x40 organisiert. Es teilen
sich also zwei Zeilen einen DD-RAM-Bereich. Wie die Zeilen mechanisch
angeordnet sind, ist vo, Modell (Routing der Platine) abhängig. Also
Datenblatt befragen oder ausprobieren. Meist ist die Zeilenaufteilung
etwas "verwürfelt".
>> im Datei lcd_drv.c ist die Formatierung dafür:>> #########################################>> void lcd_pos( u8 line, u8 column )> {> if( line & 1 )> column += 0x40; // estaba 40>> lcd_command( 0x80 + column );> }>> ########################################>> bin ich aber leider nicht ganz schlau geworden, kann mich jemand helfen?
Die Funktion sorgt lediglich dafür, dass ungerade Zeilen im zweiten
DD-RAM-Bereich landen (Offset 64). Für die Aufteilung innerhalb eines
DD-RAM-Bereiches ist diese Funktion nicht zuständig. Entweder wird das
woanders gemacht, oder Du musst Dich selbst darum kümmern. Betrachte das
LCD als 2x40, dann müsstest Du zurecht kommen.
>> Gruß
Welcher Typ ist der LCD-Kontroller?
Da gibt es einen von Samsung, KS0073, der lt. Datenblatt
fast 100% kompatibel zum HD44780 ist.
"Fast" bedeutet in diesem Falle:
--andere Zeilenadressen
--andere Init-Sequenz, hier rate ich dringend(!) sich das Dateblatt
des Herstellers anzusehen!!!!
Du musst dir im Datenblatt ansehen, wo die Zeilenanfänge deines LCD sind
(also an welcher Startadresse). Zur Not kann man das auch einfach
ausprobieren.
In diesem Code wird 0x80 mit etwas verundet. 0x80 ist offensichtlich die
Kennung im Byte, dass es sich um einen Positionierbefehl handelt. Der
Rest ist die Adresse, an die der Cursor gesetzt werden soll.
Wo kommt diese Adresse her?
Das ist in erster Linie die Spaltennummer, die du angibst. Die
Formulierung line & 1 ist nichts anderes, als das Abtesten, ob eine
ungerade Zeilennummer angegeben wurde. Da der Originalcode von maximal 2
Zeilen ausgeht, ist das gleichbedeutend mit der Abfrage, ob die
Zeilennummer gleich 1 ist. Der einzige Unterschied: Wenn du dich vertust
und zb eine Zeilennummer von 3 angibst, funktioniert diese Abfrage immer
noch und alles landet in Zeile 1
Wenn dem so ist, du also eine Zeilennummer von 1 angegeben hast, wird
zur Spaltennummer noch 0x40 dazuaddiert. Und genau das ist der Offset,
den das LCD benutzt um die angezeigten Zeilen zu trennen.
Ein LCD hat einfach nur einen linearen Speicher. Also so
0 1 2 3 4 5 6 7 8 9 10
+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+
Das LCD ist jetzt so gebaut, dass es sich aus diesem Speicher bestimmte
Bereiche herausholt, die es in den einzelnen Zeilen anzeigt.
0 1 2 3 4 5 6 7 8 9 10
+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+
| | | |
<-- Zeile 1 ----> <-- Zeile 2 ---->
Wenn du also ein A in der ersten Zeile ganz links anzeigen willst, dann
schreibst du es hier hin
0 1 2 3 4 5 6 7 8 9 10
+---+---+---+---+---+---+---+---+---+---+---+
| A | | | | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+---+
| | | |
<-- Zeile 1 ----> <-- Zeile 2 ---->
also an Adresse 0
WIllst du das A an den Anfang der zweiten Zeile, dann wird das A hier
hin geschrieben
0 1 2 3 4 5 6 7 8 9 10
+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | A | | | | |
+---+---+---+---+---+---+---+---+---+---+---+
| | | |
<-- Zeile 1 ----> <-- Zeile 2 ---->
also an Adresse 6 (in diesem Beispiel)
Das ist im Grunde schon alles, was man von seinem LCD wissen muss:
Welche Adressdistanz liegt zwischen den einzelnen Zeilen. Und Achtung:
Die Zeilen können auch durcheinander sein: Im Speicher kann es sein,
dass auf Zeile 1 die Zeile 3 folgt und dann erst 2 und 4.
Du musst daher jetzt:
Im Datenblatt nachsehen, wie das bei deinem LCD ist.
Daraus eine Berechnungsmethode ableiten, wie du die Adresse ausrechnen
kannst, wenn du Zeilennummer und Spaltennummer gegeben hast.
In meinem Beispiel wäre das zb
<----- Zeilenoffset --->
0 1 2 3 4 5 6 7 8 9 10
+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | A | | | | |
+---+---+---+---+---+---+---+---+---+---+---+
| | | |
<-- Zeile 1 ----> <-- Zeile 2 ---->
Zeilenoffset: 6
Adresse = Spaltennummer + Zeilenoffset * Zeilennummer
Probiers aus: Wenn du in Zeile 2 ( Zeilennummer: 1) an die Spalte 3
(Spaltennummer: 2) schreiben willst
Adresse = 2 + ( 6 * 1 )
Adrsse = 8
In der Grafik kann man sich davon überzeugen, dass das tatsächlich das
3te Zeichen in der 2ten Zeile wäre.
@ Karl heinz Buchegger (kbuchegg)
Nur so aus Neugier.
Machst du die ASCII-Zeichnungen jedes mal neu, oder kopierst du die aus
alten Beiträgen in die neuen? ;-)
Hallo,
hatte nicht mehr im Foro geschaut!
@Herbert, @ Kluchscheißender, @Peter Dannegger und an alle
vielen Dank für eure nette Hilfe und Antworten
@Karl heinz Buchegger
sehr nette und hilfreiche Einführung vielen Dank!
so, LCD ist ein GM-C2004A von Goldentek aber ich glaube ist etwas alt da
ich kein Datenblatt gefunden habe! habe paar ähnlicher gefunden aber ich
glaube nicht identisch.
Herbert K. schrieb:
> ohne den Typ des Displays bzw./und des Kontrollers wäre es mehr ein> Raten, hier zu helfen.
Jein, von mein 2x16 habe ich kein Datenblatt gefunden aber ich habe
rumprobiert bis ich es am laufen bekommen habe (wie Karl Heinz sagt!),da
ist auf alle Fälle ein HD44780 drin und war von daher einfacher, im 4x20
tippe ich mehr auf ein KS0070.
Kluchscheißender Kluchscheißer schrieb:
> Naja, man sollte den Code, den man verwendet, auch verstehen und nicht> nur unverstanden benutzen.
du hast vollkommen Recht nun gibt es tausende LCD Routinen und natürlich
nicht alle gleich, die Routine von Tutorial hat bei mir funktioniert
(mit dem 4x20) und ich habe zu mindestens versucht es zu verstehen.
Die Routine von Peter war die Einzige die in meinem 2x16 auf Anhieb
funktioniert hat und das beste daran ist, dass man jede einzelne Pin im
verschiedene Ports anschliessen kann, deswegen möchte die selbe Routine
für mein 4x20 LCD verwenden.
Karl heinz Buchegger schrieb:
> Da der Originalcode von maximal 2 Zeilen ausgeht, ist das leichbedeutend> mit der Abfrage, ob die Zeilennummer gleich 1 ist.
das hate ich auf alle Fälle verstanden.
Peter Dannegger schrieb:
> void lcd_pos( u8 line, u8 column )> {> switch( line ){> case 1: column += 0x20;> case 2: column += 0x20;> case 3: column += 0x20;> }> lcd_command( 0x80 + column );> }
Jup, das ist der richtiger Richtung muß ich noch ein bißchen rumspielen.
Herbert K. schrieb:
> Vielleicht hilft dieser Beitrag weiter:> Beitrag "LCD Treiber Routine 4*40"
das Probiere auf jedem Fall auch noch!
eine Frage noch, wie kann ich hier Code einfügen damit es so aussiet wie
bei Petter?
Gruß
so hat es auf alle Fälle funktioniert, ich habe ein lange Text
geschrieben um herauszufinden wo jeder Zeile anfängt und das ergabt:
1 Zeile bei 0
2 Zeile bei 40
3 Zeile bei 20
4 Zeile bei 54
das bedeutet wenn ich auf Zeile 4 schreiben will dann kann ich so
schreiben:
1
lcd_pos(0,54);
2
lcd_text((u8*)"Vierte 1234567891234");
und es fuktioniert! ok soweit so gut.
Nun wenn ich aber in der "switch - case" der Anfang von jede Zeile
ändere dann funktioniert nur bei dem Zeile 4,
also wenn ich es so ändere:
1
case3:column+=0x54;
kann ich dann so schreiben:
1
lcd_pos(3,0);
2
lcd_text((u8*)"Vierte 1234567891234");
und funktioniert aber sobald ich eine von der andere "case" ändere dann
kommt nur unsinn in der ganze LCD und ich verstehe nicht warum !
Die Case laufen ineinander über, d.h. case 1 macht alle 3 Additionen
(was bestimmt falsch ist, case 3 müßte zuerst stehen).
Schreib einfach noch ein break; am Ende jeder Case-Zeile, dann sollte es
gehen.
Peter
o man!
ich bin ein Idiot!
Peter Dannegger schrieb:
> Die Case laufen ineinander> Schreib einfach noch ein break; am Ende jeder Case-Zeile, dann sollte es> gehen.
klar!
aber warum kann man manchmal so was selber nicht sehen? ich habe kurz
gedacht aber dachte es liegt wo anders, Sch... naja heute Abend probiere
es wieder.
Vielen Dank.
Das halte ich für recht übersichtlich, problemlso anzupassen,
und sollte nicht zu langsam laufen.
Bzw. LCD_DDADR_LINE... eingesetzt natürlich.
PS: Falls man dem Frieden mit den Feldgrenzen nicht traut,
kann man ja auch line%4 nehmen.
Noch besser ist es, lcd_pos als Inline-Funktion im h-File zu definieren.
Denn dann wird sie komplett wegoptimiert, da ja Zeile und Spalte fast
immer Konstanten sind.
Es bleibt dann nur noch