Forum: Mikrocontroller und Digitale Elektronik itoa mit zwei Dezimalstellen


von MarioG (Gast)


Lesenswert?

Guten Morgen zusammen,

ich verwende ein HD44780 kompatibles Display an einem Atmega32.
Auf dem Display möchte ich die Uhrzeit anzeigen.
Als LCD-Bibliothek verwende ich die von Peter Fleury. Die funktioniert 
auch einwandfrei.

Mein Problem liegt eher bei der itoa Funktion, die AVR-GCC mitbringt. 
Solange die Stellen für Sekunden, Minuten oder Stunden einstellig sind, 
ist der ausgegebene String auch nur einstellig. Das ist natürlich 
unschön, wenn die Einer zuerst auf der Zehnerstelle stehen und erst bei 
Zahlen >9 auf Ihre eigentliche Stelle rücken.

Gibt es da eine elegante Möglichkeit, dem String eine führende 0 zu 
verpassen?

von Klaus W. (mfgkw)


Lesenswert?

Über Eleganz kann man natürlich streiten, aber spontan fällt mir sowas 
ein:
1
  puffer[0] = '0';
2
  itoa( minuten, puffer+( minuten<=9 ), 10 );

Der Rückgabewert von itoa() ist dann natürlich nicht mehr unbedingt der 
eigentliche Stringanfang.

von Klaus (Gast)


Lesenswert?

MarioG schrieb:
> Gibt es da eine elegante Möglichkeit, dem String eine führende 0 zu
> verpassen?

sprintf() ?

MfG Klaus

von DirkB (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Über Eleganz kann man natürlich streiten, aber spontan fällt mir sowas
> ein:

Irgendwie kommtja auch noch der ':' in die Uhrzeit mit rein. Und das 
wird auch nicht anders sein.

von Karl H. (kbuchegg)


Lesenswert?

Für eine enizelne Zahl würde ich eventuell auch itoa nehmen.
Wenn Flash-Platz kein Problem ist, würde ich aber gleich sprintf nehmen. 
Ist einfach komfortabler, weil man da die komplette Uhrzeit in einem 
Aufwasch formatieren lassen kann

  sprintf( buffer, "%02d:%02d:%02", stunden, minuten, sekunden );
  lcd_puts( buffer );

fertig.
Ein bischen Overhead ist mir dann der Komfort schon wert.

von Klaus W. (mfgkw)


Lesenswert?

> Irgendwie kommtja auch noch der ':' in die Uhrzeit mit rein. Und das
> wird auch nicht anders sein.

nicht unbedingt, den Doppelpunkt kann man ja einmal ausgeben und muß ihn 
nicht laufend aktualisieren.
Insofern braucht man ihn nicht im String mit der Zahl.

von Klaus (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> nicht unbedingt, den Doppelpunkt kann man ja einmal ausgeben und muß ihn
> nicht laufend aktualisieren.
> Insofern braucht man ihn nicht im String mit der Zahl.

Ob das positionieren des LCD-Cursors auf das jeweilige Zahlenfeld 
schneller ist, als immer den ganzen String auszugeben ... ?

MfG Klaus

von Klaus W. (mfgkw)


Lesenswert?

Auf einem Mega32 kann man ja nicht viel falsch machen, da wird jede 
Lösung gehen; siehe die pragmatische Variante von Karl-Heinz B..
Insofern kann man lange sinnlos um die beste Variante streiten.

von Horst H. (horha)


Lesenswert?

Hallo,

Man kann auch ein eigenes itoa benutzen.
Puffer muss 8 Zeichen lang sein.

Temp = stunden / 10;
Puffer[0] = Temp + '0';
Temp = Stunden - 10*Temp;//== stunden % 10
Puffer[1] = Temp + '0';
Puffer[2] = ':';  // Braucht nur einmal sein
Temp = minuten / 10;
Puffer[3] = Temp + '0';
Temp = minuten - 10*Temp;
Puffer[4] = Temp + '0';
Puffer[5] = ':';   // Braucht nur einmal sein
Temp = sekunden - 10*Temp;
Puffer[6] = Temp + '0';
Puffer[7] = 0;  // Braucht nur einmal sein

Und es gibt sicher noch tausende Varianten ;-)

von MarioG (Gast)


Lesenswert?

Vielen Dank schonmal für die zahlreichen Antworten!
Meine Frage zielte ja schon eher in die Richtung, das hauseigene itoa zu 
verwenden, ab.
Vom Komfort her gefällt mir die Version mit sprintf dann doch schon am 
besten. Ich werde das mal austesten und dann berichten. (wird aber vor 
morgen nicht passieren, da ich jetzt weg muß...)

von Karl H. (kbuchegg)


Lesenswert?

MarioG schrieb:
> Vielen Dank schonmal für die zahlreichen Antworten!
> Meine Frage zielte ja schon eher in die Richtung, das hauseigene itoa zu
> verwenden, ab.

Wenn du sowieso eine hauseigene itoa Lösung hast, ist es am besten sich 
mit dem Systemprogrammierer kurzzuschliessen und ihn um eine 
Spezialversion zu bitten.

Denn für itoa bedeutet die Forderung keine führenden 0-en zu erzeugen 
Aufwand.

Damit bist du in der paradoxen Situation, dass itoa erst Aufwand 
betreibt um die führenden 0-en wegzukriegen und du hinten nach Aufwand 
betreibst um diese wieder reinzukriegen.

von René S. (grassh0pper)


Lesenswert?

hatte gestern auch ganau das gleiche problem.
habs evtl. etwas pfuschig gelöst:
nimm für jede ziffer eine eigene variable:
stunden 1er, stunden 10er, minuten 1er, minuten 10er, usw...
wie gesagt vlt nicht die schönste lösung aber funzt!

gruß grassh0pper

von Karl H. (kbuchegg)


Lesenswert?

rené s. schrieb:
> hatte gestern auch ganau das gleiche problem.
> habs evtl. etwas pfuschig gelöst:
> nimm für jede ziffer eine eigene variable:
> stunden 1er, stunden 10er, minuten 1er, minuten 10er, usw...
> wie gesagt vlt nicht die schönste lösung aber funzt!

keine so gute Lösung.
Du verringerst zwar den Aufwand bei der Ausgabe, dafür hast du aber mehr 
Aufwand beim Weiterzählen der Uhrzeit. Wenn dann zb noch Weckzeiten ins 
Spiel kommen, schlägt das ganze dann ins Gegenteil um. Für ein bischen 
einfachere Programmierung in der Ausgabe treibst du eine Menge 
Mehraufwand in der internen Behandlung von Zeiten.

von Hubert G. (hubertg)


Lesenswert?

Man kann auch mit strlen abfragen ob eine oder zwei Stellen vorhanden 
sind und die 0 dann wieder einfügen.

von Horst H. (horha)


Lesenswert?

Hubert G. schrieb:
> Man kann auch mit strlen abfragen ob eine oder zwei Stellen vorhanden
> sind und die 0 dann wieder einfügen.
Leider Nein, denn die führende '0' müßte davor eingefügt werden.
Wer weiß was dort steht und somit überschreibt.

Die Methode von Klaus Wachtler funktioniert deshalb, weil er einen 
Puffer = array of char vorgibt.
Die sicherste, insbesondere bei falschen Werten, ist sprintf.

von MarioG (Gast)


Lesenswert?

Das schöne Wetter hat mich davon abgehalten, das zu testen. Ich werd das 
aber schon noch nachholen.

Karl Heinz Buchegger schrieb:
> Wenn du sowieso eine hauseigene itoa Lösung hast, ist es am besten sich
> mit dem Systemprogrammierer kurzzuschliessen und ihn um eine
> Spezialversion zu bitten.

Da hab ich mich wohl mißverständlich ausgedrückt. Ich meinte mit 
'hauseigen' die, die avr-gcc mitbringt.

von Purzel H. (hacky)


Lesenswert?

>sprintf()...

Boahh. Dann ist der halbe Speicher weg und man kann sich gleich den 
Strick suchen...

von Karl H. (kbuchegg)


Lesenswert?

Multi Oschi schrieb:
>>sprintf()...
>
> Boahh. Dann ist der halbe Speicher weg und man kann sich gleich den
> Strick suchen...

Übertreib nicht.
Bei einem Mega32 hat er genug Speicher, dass er sich sprintf für den 
Anfang leisten kann.

von MarioG (Gast)


Lesenswert?

Da bei sprintf der Compiler Probleme bereitete, hab ich jetzt einfach 
den Vorschlag von Klaus Wachtler übernommen.
Für meine Anwendung völlig ausreichend und funktioniert auch wunderbar.
Vielen Dank für die Hilfe nochmal!

von Udo S. (urschmitt)


Lesenswert?

MarioG schrieb:
> Da bei sprintf der Compiler Probleme bereitete
Ich bezweifle daß der Compiler das Problem ist.
Bei uns heisst es: "Das Problem sitzt meistens vor der Tastatur"
Und zu 99% stimmt das, sogar dort wo mit Software Geld verdient wird :-)

von Karl H. (kbuchegg)


Lesenswert?

Wahrscheinlich fehlt einfach nur der richtige Include für sprintf

#include <stdio.h>

von Horst H. (horha)


Lesenswert?

Hallo,

ach wie schade.
Ich hatte gerade
Temp = stunden / 10;
durch
Temp = ( int (stunden) * 26) >> 8 ;
ersetzt, was auch nur bis knapp über 60 funktioniert und ohne Divsion 
auskommt.

von MarioG (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wahrscheinlich fehlt einfach nur der richtige Include für sprintf
>
> #include <stdio.h>

Das hatte ich schon beachtet.

Udo Schmitt schrieb:
> Ich bezweifle daß der Compiler das Problem ist.
> Bei uns heisst es: "Das Problem sitzt meistens vor der Tastatur"
> Und zu 99% stimmt das, sogar dort wo mit Software Geld verdient wird :-)

Das Problem sitzt insofern vor der Tastatur, als daß ich nicht bereit 
war, ewig Zeit zu investieren, um den Fehler zu suchen und zu beheben.
Ich sollte vielleicht erwähnen, daß ich nicht unter Windows mit 
AVRStudio arbeite, sondern unter Linux mit Codeblocks. Das Problem 
scheint in der in meinem ubuntu release (10.10 bzw maverick merkaat) 
verwendeten avr-libc zu liegen.
Die Fehlermeldung lautete wie folgt:
"/usr/lib/avr/lib/libc.a(vfprintf_std.o): In function `vfprintf':
/build/buildd/avr-libc-1.6.8/avr/lib/avr2/../../../libc/stdio/vfprintf.c 
:338:  undefined reference to `__mulhi3'
/build/buildd/avr-libc-1.6.8/avr/lib/avr2/../../../libc/stdio/vfprintf.c 
:341:  undefined reference to `__mulhi3'"

An einer Problemlösung wäre ich natürlich schon interessiert!

Horst Hahn schrieb:
> Hallo,
>
> ach wie schade.
> Ich hatte gerade
> Temp = stunden / 10;
> durch
> Temp = ( int (stunden) * 26) >> 8 ;
> ersetzt, was auch nur bis knapp über 60 funktioniert und ohne Divsion
> auskommt.

Temp = ( int (stunden) * 26) / 256 ;
würde das der Compiler nicht genauso interpretieren? Wäre auf jeden fall 
einfacher zu lesen ;)

von Heiner (Gast)


Lesenswert?

char puffer[4];

 lcd_clear();

 itoa((int) stunden+100, puffer, 10);
 lcd_string(&puffer[1]);

 lcd_string(" : ");

 itoa((int) minuten+100, puffer, 10);
 lcd_string(&puffer[1]);

 lcd_string(" : ");

 itoa((int) sekunden+100, puffer, 10);
 lcd_string(&puffer[1]);

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.