Hallo Ich habe eine Frage was die lcd library von Peter Fleury betrift. Bei mir funktioniert sie eigentlich sehr gut, nur habe ich es noch nicht geschaft eine Variabel (char, int, eigentlich egal was) als Dezimalzahl ans LCD auszugeben. Weiss jemand ob das überhaupt möglich ist und wenn ja wie es funktioniert? Für eure Antworten danke ich euch schon im voraus. Gruss Sepp
Danke für die schnelle Antwort. Ist sprintf nicht ein Befehl zur Ausgabe an ein Terminal??? Wie muss ich itoa anwenden? Vieleicht meine Frage noch mal etwas genauer: Eine Variabel (unsigned char Test;) soll über den Befehl lcd_puts(); aus der LCD Library von Peter Fleury als Dezimalzahl an ein LCD ausgegeben werden. Wie geht dass? Falls du mit deiner Antwort genau dass gemeint hast, bitte ich um weitere Erklärungen, denn ich habs anscheinend nicht kapiert.
Hi, Fritz hatte schon recht, mit itoa() oder sprintf() kannste das machen. itao() geht nur für Zahlen, sprintf() kann im Vergleich mehr, aber beide schreiben die Werte in einen Buffer rein, den Du übergibst. Dann musst Du nur noch die Zeichen aus dem Buffer einzeln per lcd_puts() an das LCD senden. Die genaue Syntax für die beiden Funktionen hab ich gerade nicht im Kopf, da musste selbst mal suchen. sprintf() ist glaube ich genau wie printf(), nur dass Du vorher einen ausreichend großen Buffer angibst. Könnte dann so aussehen: char buffer[10]; int zahl = 42; sprintf(buffer, "Zahl: %d", zahl); while (...) lcd_puts(buffer[i]); Bye Daniel Jelkmann
Nein, nein! lcd_puts gibt schon den string aus, lcd_putc macht es zeichenweise. es geht z.b. so: char text[34]; sprintf(text,"Es ist %02d:%02d Uhr", stund, min); Ergibt: Es ist 09:15 Uhr Mehr dazu gibts in der Doku der avr-libc. Wennst Linux hast kannst auch "man 3 printf" in der Konsole eingeben.
Ok; ich habe die erste Methode getestet (von Daniel Jelkmann) und das funktioniert wunderbar!! Jetzt kommt aber bereits das nächste Problem: Mit diesem Befehl wird mein Programm um unglaubliche 5KB grösser!!!!! Da kann ich mit meinem AT90S8535 nicht mehr gerade viel anfangen (8KB SRAM). Gibts da keine platzsparendere Möglichkeit? Muss ein neuer uP her?
Wenn Du den Komfort von printf() haben willst, braucht das viel Platz. Steht auch in der Doku. Es gibt drei verschiedene Varianten von printf-Bibliotheken: * Standard, kann alles außer Gleitkomma * minimal, kann keine Feldweiten, keine Füllzeichen, fast nichts, taugt eigentlich bestenfalls fürs Debuggen * voll, d. h. Standard + Gleitkomma Wenn Du wirklich 5 KB mehr Flash brauchst, vermute ich allerdings, daß Du die Gleitkommavariante ausgewählt hast. Brauchst Du diese denn überhaupt? Auf einem AT90S8515 ist der Unterschied in der Codegröße zwischen Standard und Gleitkomma fast 2 KB, außerdem braucht die Gleitkommaversion noch malloc(), wenn Du das sonst nicht benötigst, ist das nochmal ein halbes KB. Wenn Du knapp mit Flash dran bist, mußt Du Dir halt die Ausgaben selbst zimmern. Auch dafür bietet die Bibliothek Basisroutinen, siehe Doku. Meist lohnt es sich, sich über solche Kleinigkeiten vorher klar zu werden. Die zwei Euro mehr für einen ATmega16 statt eines ATmega8 (der AT90S8535 ist sowieso Auslaufmodell) machen das Kraut gerade bei einem Einzelstück nicht fett, wenn Du Dir überlegst, wie viel umständlicher Du dafür dies oder jenes jetzt vielleicht machen mußt, nur weil printf() nicht mehr reinpaßt. Zusätzlich kann man den ATmega16 sogar noch via JTAG debuggen, wenn's eng wird. Die gute Nachricht: der ATmega16 ist pinkompatibel zum AT90S8535...
Ich hab bei mir lcd_puts vergessen, sorry. Trotzdem ist seine Methode unnötig kompliziert, es muss heissen: char text[34]; sprintf(text,"Es ist %02d:%02d Uhr", stund, min); lcd_puts(text); Leider wird das Programm grösser, aber dafür hast du die ganze printf Funktionen zur Verfügung. Wenn du keine Fliesskomma Sachen brauchst, kannst du es anders linken: LDFLAGS += -Wl,-u,vfprintf -lprintf_min
Vielen Dank für Eure Tipps. Ich habe mich entschieden dass ich mir einen Atmega 128 oder was ähnliches anschaffe; der Aufwand lohnt sich wirklich nicht, und ein neuer uP ist sowieso schon lange fällig.
Ja, zum Experimentieren ist der '128 auf alle Fälle zu empfehlen. Platz ohne Ende. :-) Aber Vorsicht mit -lprintf_min: Formatieranweisungen wie %02d degradieren dann zu %d -- Feldbreite, Precision usw. wird in der Minimalvariante schlicht ignoriert. Dafür ist sie eben die Minimalvariante. Einfach nichts weiter an Linkeroptionen angeben und die Standardvariante benutzen.
Hi, sorry, mit dem lcd_puts() hat Fritz natürlich recht, da wird gleich der ganze String ausgegeben. Dann muss die while(...)-Geschichte natürlich raus und einfach ein lcd_puts(buffer); dahin... Wenn Dir die printf()-Geschichte zu groß wird und Du nur einfache Sachen ausgeben willst, kannst Du es Dir auch selbst zusammencoden, wie Jörg schon schreibt. Wenn Du z.B. weisst, dass die Variable nie größer als 999 wird und Du somit mit 3 Stellen auskommst, könntest Du das so machen: int zahl = 987; char buffer[4]; // 3 Ziffern + Nullzeichen buffer[0] = 48 + zahl / 100 % 10; buffer[1] = 48 + zahl / 10 % 10; buffer[2] = 48 + zahl % 10; buffer[3] = 0; lcd_puts(buffer); Die 48 entspricht dem Zeichen 0 in der ASCII-Tabelle, 49 der 1, 50 der 2, usw. Das sollte dann eigentlich klappen. (Wenn Du keine führenden Nullen haben willst, musst Du if-Abfragen einbauen.) Bye Daniel Jelkmann
Hmm, erstmal Verbesserungsvorschlag für den gezeigten Code: int zahl = 987; div_t d; char buffer[4]; // 3 Ziffern + Nullzeichen d = div(zahl, 10); buffer[2] = '0' + d.rem; d = div(d.quot, 10); buffer[1] = '0' + d.rem; d = div(d.quot, 10); buffer[0] = '0' + d.rem; buffer[3] = 0; lcd_puts(buffer); div() ist eine der weniger bekannten Funktionen des C-Standards. Sie nutzt sich die Tatsache aus, daß bei einer Division auch immer automatisch der Rest (Modulus) berechnet wird, so daß man beide Ergebnisse auch gleich gemeinsam zurückgeben kann. Intern wird für div(), den Operator / oder den Operator % jeweils dieselbe Funktion gerufen. Da die Division die kostpieligste Grundrechenart ist, kann man damit Rechenzeit sparen. Es wird natürlich auch offensichtlich, daß man um alles auch gleich eine Schleife schreiben kann. ;-) Die Benutzung von '0' statt 48 verdeutlicht optisch, daß man hier nicht an einer Zahl, sondern an einem ASCII-Zeichen interessiert ist. (Sie hat den zusätlichen Vorteil, daß man damit standardkonform völlig unabhängig vom benutzten Zeichensatz ist, da der C-Standard vorschreibt, daß die Ziffern im `char' alle aufeinanderfolgend abgebildet sein müssen.) Man kann natürlich genausogut auch itoa() benutzen. Siehe Doku.
Hi Jörg, danke für Deinen Verbesserungsvorschlag. Das mit dem div() hab ich noch in keinem Code so gesehen, nur in der AVR-Doku :) Aber der Vorteil leuchtet ein und es scheint ja durchaus sinnvoll zu sein, ich werde mir versuchen es zu merken und auch in Zukunft anzuwenden. Bye Daniel Jelkmann
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.