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
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
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
@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
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
@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
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
> 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.
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
@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
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.
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
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.
)
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?
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
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
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
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
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"
@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
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
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
@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
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.