Forum: Mikrocontroller und Digitale Elektronik Pollin LCD Zeilen einstellen, aber wie?


von Michael Thom (Gast)


Lesenswert?

Moinsen!

Nun habe ich eine init welche richtigt läuft und auch eine kleine fprint 
geschrieben. Sie kann noch nichts besonders!

Wenn ich einen langen Text oder das abc schreibe bleiben Buchenstaben 
weg und in der nächsten Zeile geht es irgendwann weiter.
z.B.: ....blup und bla ... 12345
      ijklmn pqrstuvwxyz
Wo das Leerzeichen ist zwischen n und p ist ein Zeilenwechsel von 
Controller des LCD! Soweit habe ich es ja begriffen, doch wie andere ich 
es von 39 auf 27 Zeichen in jeder der 4 Zeilen???

Pollin LCD WD-C2704M-1HNN 4 Zeilen x 27 Zeichen Text mit einem HD44780 
Controller

mfg

Taz

von Michael U. (Gast)


Lesenswert?

Hallo,

garnicht.
Du mußt Dich bei der Ausgabe darum kümmern, am Ende einer Zeile die 
Anfangsadresse der nächsten gewünschten Zeile zu setzen.
Das Display hat 80 Zeichen Ram (das Pollin dürfte 2 Kontroller haben?),
die Zuordnung der Adressen zur Darstellung sollte in der 
Display-Beschreibung zu finden sein.
Sonst eben ausprobieren, an welcher Adresse Zeile 2 beginnt usw.

Gruß aus Berlin
Michael

von Michael Thom (Gast)


Lesenswert?

Hi Michael!

Dann wäre es sicherlich einfacher eine printf() Funktion an zu passen 
und mit ihr die Ausgabe auf den Port zu machen?!
Ich proge in C unter µVision3 von Keil auf eine AT89C51CC03 im 8-Bit 
Modus.

mfg

Taz

von Falk (Gast)


Lesenswert?

@Michael Thom

>Dann wäre es sicherlich einfacher eine printf() Funktion an zu passen
>und mit ihr die Ausgabe auf den Port zu machen?!

Naja, wenn du das volle Programm brauchst (Floating Point etc.) dann ja.

MfG
Falk

von Michael Thom (Gast)


Lesenswert?

Hi Falk,

im Forum hier stehen eine Menge Beiträge zu prinf(). Da muss ich nur 
sehen das ich den Code auf mein µC  und in C gut übertrage. Dann sollte 
es doch schon gehen, oder sehe ich das verkehrt?

mfg

Taz

von Falk (Gast)


Lesenswert?

@Michael Thom

>im Forum hier stehen eine Menge Beiträge zu prinf(). Da muss ich nur
>sehen das ich den Code auf mein µC  und in C gut übertrage. Dann sollte
>es doch schon gehen, oder sehe ich das verkehrt?

Jain. Das printf für dein LCD hat zwei Aufgaben

a) Den Formatstring parsen(analysieren) un dementsprechend einen String 
generieren.

b) Die Ausgabe der einzelnen Chars des String in LCD koordinieren, was 
auf grund er nichtlinearen Adresszuordung nicht so ganz einfach ist.

Ersteres gibt es schon fertig, nimm einfach sprintf. Zweiteres musst du 
selber machen.

MFG
Falk


von Michael Thom (Gast)


Lesenswert?

Danke Falk,

mit sprintf kann ich super einen string ausgeben. Werde einfach zwei 
print-Funktion schreiben für das obere und unter Display!

Aber ich habe mal eine Frage zu folgenden Programmcode:

va_list ap;

va_start(ap, pText);
    vprintf(text, ptext, ap);
va_end

Wenn ich mir das anschauen, vermute ich das die Platzhalter mit den 
Variablen gefüllt werden! Also wo %d steht wird der Wert von int c = 3 
reingeschrieben.
Ist aber nur eine Vermutung, darum wollte ich gerne lieber nachfragen 
und ob ich es mit sprintf auch so handhaben muss?

mfg

Taz

von Karl H. (kbuchegg)


Lesenswert?

> darum wollte ich gerne lieber nachfragen
> und ob ich es mit sprintf auch so handhaben muss?

Ja.
Der einzige Unterschied zwischen printf und sprintf
liegt darin, dass printf das Ergebnis (den String) in
die I/O Kanäle schiebt, während sprintf das Ergebnis
in einen character Buffer stellt.
Intern werden von sprintf, printf, fprintf normalerweise
sogar die gleichen Funktionen benutzt um den String
zu formatieren.


von Michael Thom (Gast)


Lesenswert?

Hi!

Also mit folgender Funktion bekomme ich auf den LCD die Ausgabe:

[Hier bin ich! 256 0          ] Zeile 1

int f1print (unsigned char text[], ...)
{
 int i;
 int lenght;
 char temp[39];
 va_list ap;
 lenght = 0;
 lenght = strlen(text);
 va_start(ap,text);
   sprintf(temp,text,ap);
 va_end(ap);
 for (i=0;i<lenght;i++)
 {
    write_data(temp[i], 1);
 }
return 0;
}

Ich habe in meiner main die f1print folgender maßen aufgerufen:

f1print("Hier bin ich! %d %f", i, i);

Wobei int i = 5 ist.

Wieso klappt die Ausgabe nicht richtig?

Taz

von Michael Thom (Gast)


Lesenswert?

Hey!

Ein \r, \t und \n funtzt auch nicht bei mir!

Habe ich was entscheidenes vergessen oben in meiner Funktion?

Grüße

Taz

von Falk (Gast)


Lesenswert?

@Michael Thom

>Ein \r, \t und \n funtzt auch nicht bei mir!

Kann ja auch gar nicht. Dein LCD ist "dumm", es kann nur Zeichen 
darstellen. Es weiss nicht, dass es bei

\r an den Zeilenanfang
\n in die nächste Zeile springen soll.

Das musst du "per Hand" machen.

MFG
Falk

von Karl H. (kbuchegg)


Lesenswert?

Michael Thom wrote:
>
> f1print("Hier bin ich! %d %f", i, i);
>
> Wobei int i = 5 ist.
>
> Wieso klappt die Ausgabe nicht richtig?

Weil i immer noch ein int ist. %f wird für float
oder double benutzt.

von Michael Thom (Gast)


Lesenswert?

Hi,

darauf hätte ich auch selbst kommen können. Habe wohl zu hohe 
Erwartungen an mein µC und LCD.
Doch warum klappt das nicht mit der Formatausgabe:

f1print("Hier bin ich! %d %f", i, i);

Wobei int i = 5 ist und raus kommt => Hier bin ich! 256 0

muss ich dass auch per Hand nachtragen?

mfg

Taz

von Michael Thom (Gast)


Lesenswert?

okay mit %f kommt was verkehrtes raus, aber bei %d sollte zumindest 5 
stehen und nicht 256.

Grüße

Taz

von Karl H. (kbuchegg)


Lesenswert?

Nein. sollte es nicht.
Deine Format Argumente passen nicht zu den tatsächlich
übergebenen Argumenten. Ab da kann alles mögliche passieren.

(Was wahrscheinlich passiert ist:
 Die Argumente werden von rechts nach links auf den
 Stack gelegt. Und zwar 2 * 2 Bytes. Beim Auswerten hat sich
 der  %f gleich mal 4 Bytes vom Stack geholt, sodass der %d
 sich irgendwas vom Stack holen musste. Zufällig war das halt
 256.
)

von Michael Thom (Gast)


Lesenswert?

Habe es schon abgeändert:

dir = 5;
f1print("Hier bin ich! %d", dir);

und Ausgabe:

Hier bin ich! 256+

von Michael Thom (Gast)


Lesenswert?

achso,

int dir;

und habe mal die zeilen geändert:

double dir = 5;
f1print("Hier bin ich! %f", dir);

und Ausgabe:

Hier bin ich! 0.0

???
Werden die Argumente nicht übergeben?

von Michael Thom (Gast)


Lesenswert?

Wenn ich die

sprintf(temp, "lenght: %d", len); // len = 22

und an mein write-data () übergebe kommt die Anzeige korekt raus!

irgendwie scheinen meine Argument nicht richtig eigebaut zu werden habe 
ich da einen Fehler begangen?

int f1print (unsigned char *text, ...)
{
 int i;
 int len;
 char temp[39];
 va_list ap;

 len = 0;

 len = strlen(temp);

 va_start(ap,text);
   sprintf(temp,text,ap);
 va_end(ap);

// Test für eine Ausgabe
//sprintf(temp, "lenght: %d", len);
// Funktion ist völlig konrekt ausgegeben worden!
 for (i=0;i<len;i++)
 {
    write_data(temp[i], 1);
 }
 return 0;
}

lg

Taz

von Michael Thom (Gast)


Lesenswert?

Ich habe den Code jetzt soweit geändernt, dass er wie folgt aussieht:

int f1print (char *text, ...)
{
 int i;
 int len;
 char temp[39];
 va_list ap;

 len = 0;

 len = strlen(temp);

 va_start(ap,text);
   sprintf(temp,text,ap);
 va_end(ap);

// Test für eine Ausgabe
//sprintf(temp, "lenght: %d", len);
// Funktion ist völlig konrekt ausgegeben worden!

 for (i=0;i<len;i++)
 {
    write_data(temp[i], 1);
 }

 return 0;
}

Aber dennoch kommt immer noch : Hier bin ich! 256

Und das obwohl wo 256 steht nur eine 5 sein sollte!

Hat jemand eine Idee warum?

mfg

Taz

von Stefan Seegel (Gast)


Lesenswert?

Schau mal hier:

Beitrag "lib für Pollin LCD (WINTEK2704)"

da hatte ich mal eine Bibliothek für dieses Display veröffentlicht.
Selbige kümmert sich auch um das etwas eigenartige Zeilengehüpfe.

Gruß
Stefan

von Michael Thom (Gast)


Lesenswert?

Habe ich mir angesehen!

Die Funktion puts gibt aber nur eine Zeichenfolge aus! Ich möchte 
nachher aber schreiben können "f1print("Position: %d:", dir);" , mit 
beliebig vielen Variablen!
Und wenn ich mir den Code anschaue kann dieser das nicht, oder liege ich 
da fehl?

Gruß

Taz

von Karl H. (kbuchegg)


Lesenswert?

Ich hab schon lange nichts mehr mit
"variadischen Funktionen" gemacht.
Das ist auch das Stichwort, mit dem du im
Google was finden solltest: "variadische Funktionen"

von Falk (Gast)


Lesenswert?

@Michael Thom

> va_start(ap,text);
>   sprintf(temp,text,ap);
> va_end(ap);

Was machen die Funktionen va_start und va_end?

So wie ich es sehe, ist deine Funktion nicht dazu geeignet, die 
Zeilenstuerung zu übernehmen. Dazu brauchst du (globale) Variablen für 
Zeile und Spalte. Nach jedem ausgegebenen Zeichen msst du prüfen, ob du 
einen Zeilensprung machen musst oder nicht. Das sehe ich bei dir 
überhaupt nicht.

MfG
Falk


von Michael Thom (Gast)


Lesenswert?

also,

wenn ich das richtig verstanden habe von Karl heinz Buchegger. Hat er 
mir zugestimmt das bei diesem ablauf die variablen mit ihren jetzigen 
Wert den sie besitzen in den String integrit werden.

("hey %d", i) // i=5 => "hey 5"

TAz

von Michael Thom (Gast)


Lesenswert?

Da habe ich was vergessen in der befehlskette, denke ich! Werde mal 
weiter suche!

Grüße

Taz

von Michael Thom (Gast)


Lesenswert?

Axo,

die Anregung es so zu progen habe ich von:

Beitrag "Re: printf-Funktion für Displayausgabe schreiben"

Es schien mir eigentlich eine einfache saubere Lösung zu sein.

von Karl H. (kbuchegg)


Lesenswert?

Dann lies noch mal genau.
Der benutzt vsprintf und nicht sprintf.

von Michael Thom (Gast)


Lesenswert?

Moin!

Ja, dachte es würde auch mit sprintf gehen. Wahrscheinlich habe ich zu 
lange vor dem Bildschirm gehangen und war blind um nach links und rechts 
zu blicken. Ob es noch andere Möglichkeiten gibt!

Habe es jetzt einfacher gemacht!

int f1print (char *text, double x, double y);
{
....

sprintf(temp,text, x,y);

....
}

Mit unterschiedlichen Variablen wärs mir lieber. Doch vielleicht habe 
ich später dafür noch Zeit! Wenn ich den gesamten Code ausdrucke und 
optimiere!
Erstmal sollte alles laufen nach meiner Vorgabe, dann kann man immer 
noch mehr daraus machen

Ich danke euch an der Kritik und Hilfe die man mir zukommen liest, sie 
hat geholfen!!!

Grüße

Taz

von Falk (Gast)


Lesenswert?

@Michael Thom

>Habe es jetzt einfacher gemacht!

>Mit unterschiedlichen Variablen wärs mir lieber. Doch vielleicht habe

Das kann man auf zwei Wegen lösen.

a) Einfach sprintf und die Ausgabe aufs LCD getrennt lassen, dann kannst 
du alle Schikanen von sprintf nutzen.

b) Professionell, verwende eine variable Parameterliste, das ist aber 
ein wenig kniffelig. Ich weiss nicht, wie das jetzt im Detail 
funktioniert.

>Erstmal sollte alles laufen nach meiner Vorgabe, dann kann man immer
>noch mehr daraus machen

Dann schreib erstmal ne Funktion, die die Zeilenverwaltung mancht.

MfG
Falk

von Karl H. (kbuchegg)


Lesenswert?

Falk wrote:

> b) Professionell, verwende eine variable Parameterliste, das ist aber
> ein wenig kniffelig. Ich weiss nicht, wie das jetzt im Detail
> funktioniert.

Hab das schon lange nicht mehr gemacht.
Aber der Schlüssel sind die v-Funktionen. In diesem
Fall vsprintf.

Hier gibts ja einen Denkfehler (den ich auch wieder
lange Zeit gemacht habe). In dieser Spezialfunktion
f1Print liegt ja keine beliebig lange Argumentliste
mehr vor. f1Print braucht eine xxprintf Funktion
die genau 3 Argumente nimmt:

 * Einen Pointer auf den Ergebnisbuffer
 * Einen Pointer auf den Formatstring
 * Einen Pointer auf die Argumentliste

Das alles liegt in f1Print vor und die Funktion die
diese 3 Argumente nimmt, heist nun mal vsprintf()

sprintf will ja ganz was anderes
 * Einen Pointer auf den Ergebnisbuffer
 * Einen Pointer auf den Formatstring
 * beliebig viele weitere Argumente

"beliebig viele weitere Argumente" ist aber nicht dasselbe
wie einen "Pointer auf die Argumentliste". Wenn man so will
kann man auch sagen: sprintf erwartet die Argumente nach
wie vor auf dem Stack, während vsprintf sie schon in
eine "Listenstruktur" verpackt haben möchte (es ist meist
keine echte Liste). Durch den va_list/va_start Mambo Zambo
wird genau diese Transformation gemacht.

Fehler fallen hier so gut wie nicht auf, da sprintf aufgrund des
... im Prototypen alles frisst. Es kommt halt nicht das richtige
raus, wenn man Glück hat schmiert das Teil ab ansonsten
sucht man sich im Fehlerfall dumm und dämlich.

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.