mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Devision und Restbildung


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Bert (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo
möchte in einem Programm zur Anzeige eines Messwertes eine vierstellige 
Zahl in seine Ziffern zerlegen. Habe das Beispiel in Mikro.. gefunden 
und es so progarmmiert:
spannung_anz1 = spannung_anz % 10;    // 4. Zahl
    spannung_anz2 = spannung_anz / 10;
    spannung_anz3 = spannung_anz2 % 10;    // 3. Zahl
    spannung_anz4 = spannung_anz2 / 10;
    spannung_anz5 = spannung_anz4 % 10;    // 2. Zahl
    spannung_anz6 = spannung_anz4 / 10;
    spannung_anz7 = spannung_anz6 % 10;    // 1. Zahl
    spannung_anz8 = spannung_anz6 / 10;
    
    itoa(spannung_anz7, Buffer, 10 );
    lcd_printlc(4,9," ");
    lcd_printlc(4,9,Buffer);
    
    itoa(spannung_anz5, Buffer, 10 );
    lcd_printlc(4,11," ");
    lcd_printlc(4,11,Buffer);
    
    itoa(spannung_anz3, Buffer, 10 );
    lcd_printlc(4,13," ");
    lcd_printlc(4,13,Buffer);
    
    itoa(spannung_anz1, Buffer, 10 );    // 4. letzte Zahl stimmt
    lcd_printlc(4,15," ");
    lcd_printlc(4,15,Buffer);
Es wird nur die 4. Stelle korrekt angezeigt. Die 1. bis 3. Stelle 
verändert sich nicht. Was mach ich falsch?
C, AVR GCC

Bert

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Wie ist Buffer definiert?

Das Ganz ist zu kompliziert gemacht.

Autor: Bert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Buffer habe ich so angegeben

char Buffer[30];

Autor: Bert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kennst du eine einfache Lösung?

Autor: rbx (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
um Ärger mit Division und Datentypen o.ä. aus dem Weg zu gehen helfen 
u.a. logische Operationen.

Autor: Dirk B. (dirkb2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bert schrieb:
> Kennst du eine einfache Lösung?

Was ist denn dein eigentliches Problem?

itoa kann auch Werte über 9 richtig umwandeln.

Autor: Keiner N. (nichtgast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst deinem itoa einfach den ganzen Wert zum Fraß vorwerfen. Du 
must deine spannung_anz nicht vorher klein schnipseln.

Autor: Carl D. (jcw2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bert schrieb:
> Kennst du eine einfache Lösung?

Itoa kann auch mehrstellige Zahlen bearbeiten.

PS: nicht alles, was man im Internet findet, taugt was.

Autor: Harry L. (mysth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Viel sinnvoller ist in so einem Fall Festkomma-Arithmetik.
https://www.mikrocontroller.net/articles/Festkommaarithmetik

Und es heißt Division!

Autor: Peter D. (peda)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Warum so umständlich?
    sprintf( Buffer, "%4d", spannung_anz );
    lcd_printlc(4,9,Buffer);

Autor: Bert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das eigentliche Ziel bei der Wandlung ist, die Zahl (Messwert) zu 
zerlegen.
Bekomme z.B. den Wert von 4237 zurück. Diesen möchte ich in mV und V 
anzeigen. Mit der vorher durchgeführten Teilung sind es 4237 mV. Diesen 
Wert möchte ich auch in V anzeigen lassen. Es geht dabei um den 
spannungbereich von ca. 4,5V bis 12,5V und das richtige setzen des 
Kommars.

Autor: Carl D. (jcw2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bert schrieb:
> Das eigentliche Ziel bei der Wandlung ist, die Zahl (Messwert) zu
> zerlegen.
> Bekomme z.B. den Wert von 4237 zurück. Diesen möchte ich in mV und V
> anzeigen. Mit der vorher durchgeführten Teilung sind es 4237 mV. Diesen
> Wert möchte ich auch in V anzeigen lassen. Es geht dabei um den
> spannungbereich von ca. 4,5V bis 12,5V und das richtige setzen des
> Kommars.

Aber wenn die 4 Ziffern der mV's im Puffer stehen, dann würdest du die 
V's und ihre Nachkommastellen darin schon finden, oder?

Autor: Och Nee (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Bert schrieb:
> Bekomme z.B. den Wert von 4237 zurück. Diesen möchte ich in mV und V
> anzeigen. Mit der vorher durchgeführten Teilung sind es 4237 mV. Diesen
> Wert möchte ich auch in V anzeigen lassen. Es geht dabei um den
> spannungbereich von ca. 4,5V bis 12,5V und das richtige setzen des
> Kommars.

Och mönsch ....
   sprintf( Buffer, "%2d.%03d", spannung_anz/1000, spannung_anz%1000);

Ich weiss nicht was lcd_printlc macht aber das kriegst
du schon noch hin ....

Spannung darf dabei nicht negativ sein sonst muss man noch
Vorkehrungen treffen ...

Autor: m.n. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
rbx schrieb:
> um Ärger mit Division und Datentypen o.ä. aus dem Weg zu gehen helfen
> u.a. logische Operationen.

Oder einfach nur Subtraktion und Addition.
Beitrag "schnelle Wandlung long -> ASCII"

Autor: Michael B. (laberkopp)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Peter D. schrieb:
> Warum so umständlich?
>     sprintf( Buffer, "%4d", spannung_anz );
>     lcd_printlc(4,9,Buffer);

Ach du Scheisse, das Monster printf auffahren um eine GANZZAHL 
auszugeben ? Das nennt man aber Resourcenverschwendung par excellence.

Bert schrieb:
> Bekomme z.B. den Wert von 4237 zurück. Diesen möchte ich in mV und V
> anzeigen. Mit der vorher durchgeführten Teilung sind es 4237 mV. Diesen
> Wert möchte ich auch in V anzeigen lassen. Es geht dabei um den
> spannungbereich von ca. 4,5V bis 12,5V und das richtige setzen des
> Kommars.

Wahrscheinlich Kommas, aber das geht doch auch hinterher, wenn in buffer 
erst mal die 4-stellige Zahl steht. Einfach die erste Stelle ausgeben, 
dann ein Komma, dann die letzten 3 Stellen.

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael B. schrieb:
> Ach du Scheisse, das Monster printf auffahren um eine GANZZAHL
> auszugeben ? Das nennt man aber Resourcenverschwendung par excellence.

Für ungenutzten Flash gibt es kein Geld zurück. Die MCs haben heutzutage 
typisch ab 32kB aufwärts, da spielt das keine Rolle mehr.
Zu Zeiten des ATtiny2313, ATtiny15 hatte ich mir auch Gedanken zum Flash 
sparen gemacht, aber das ist schon ewig her.
Heutzutage ich viel wichtiger, das man Code schnell, fehlerfrei und 
wartbar erstellen kann.
Und wenn es keine triftigen Gründe dagegen gibt, würde ich Kommazahlen 
einfach als float darstellen:
    sprintf( Buffer, "%6.3f", spannung_anz / 1e3 );
    lcd_printlc(4,9,Buffer);

Autor: Εrnst B. (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch wenn das bei einer für Menschen gedachten Ausgabe völlig irrelevant 
ist ...


Och Nee schrieb:
> sprintf( Buffer, "%2d.%03d", spannung_anz/1000, spannung_anz%1000);

Kann man noch optimieren und Quotient + Rest in einem Durchlauf 
berechnen:
#include <stdlib.h>
#include <stdio.h>


void print_mV(uint16_t mV) {
  div_t splitted=div(mV,1000);
  printf("%3d.%03d\n",splitted.quot,splitted.rem);
}
(Statt printf einfach die Wunsch-Ausgabefunktion verwenden).

Wird dann zu:
print_mV:
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
        ldi r22,lo8(-24)
        ldi r23,lo8(3)
        rcall __divmodhi4
..... prinf-Aufruf-gedöns .....

Also ein call einer handoptimierten ASM-Routine aus der lib und fertig.

Und nachdem die "div"-Funktion mit dem div_t Rückgabewert zum 
C89-Standard gehört, ist das auch kein unportables Gefrickel.


Nachtrag:
Hab dem GCC mal wieder zu wenig zugetraut. Mit Optimierung macht er 
dasselbe aus mV/1000, mV%1000 ...
also lohnt es nicht, umständlich mit der "div"-Funktion zu hantieren

: Bearbeitet durch User
Autor: W.S. (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Michael B. schrieb:
> Ach du Scheisse, das Monster printf auffahren um eine GANZZAHL
> auszugeben ? Das nennt man aber Resourcenverschwendung par excellence.

Der Peter kennt nix besseres. Zum Beispiel kennt er <math.h> wohl 
garnicht. Deshalb kommt er auf sowas nicht - genauso wie der TO:
  long   L; // Variable hier rein
  ldiv_t T;
  int    i;
  char   Buffer[soviel wie gewünscht];

  i = soweit nach rechts wie gewünscht;
  while(i)
  { T = ldiv(L,10);
    L = T.quot;
    Buffer[i--] = '0'+T.rem;
  }

W.S.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
W.S. schrieb:
> Zum Beispiel kennt er <math.h> wohl garnicht.

Für die Verwendung von ldiv() ist stdlib.h und nicht math.h 
obligatorisch.

>   while(i)
>   { T = ldiv(L,10);
>     L = T.quot;
>     Buffer[i--] = '0'+T.rem;
>   }

Buffer wird nicht terminiert:

$ cat ldiv.c
#include <stdio.h>
#include <stdlib.h>

int main ()
{
    long   L = 12345;
    ldiv_t T;
    int    i;
    char   Buffer[20];

    i = 10;

    while(i)
    {
        T = ldiv(L,10);
        L = T.quot;
        Buffer[i--] = '0'+T.rem;
    }
    puts (Buffer);

    return 0;
}
$ cc ldiv.c -o ldiv && ./ldiv
0000012345▒\▒▒▒W▒

Aua.

: Bearbeitet durch Moderator
Autor: Apollo M. (Firma: @home) (majortom)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
... probiert mal und ersetze

spannung_anz4 = spannung_anz %10;
spannung_anz3 = spannung_anz /10%10;
spannung_anz2 = spannung_anz /100%10;
spannung_anz1 = spannung_anz /1000%10;

das thema hatte ich auch schon und hat nur so funktioniert?!

mt

Autor: W.S. (Gast)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
Frank M. schrieb:
> Aua.

Und wieso aua?
Für copy&paste ohne eigenes Nachdenken? Ach nö. Ich will den Leuten den 
Weg aufzeigen und ihnen nicht den Brei mit dem Löffel in den Mund 
füttern.

Man hätte sowas schon vor Jahren in der Lernbetty nachlesen können. Aber 
stattdessen kommt immer wieder sowas wie Peters Vorschlag hier in die 
Threads. Seine Ansicht:

Peter D. schrieb:
> Für ungenutzten Flash gibt es kein Geld zurück. Die MCs haben heutzutage
> typisch ab 32kB aufwärts, da spielt das keine Rolle mehr.

kann ich wirklich NICHT teilen. Richtig ist, daß es für dutlich 
weniger Flash-Verbrauch tatsächlich Geld gibt, nämlich das, was man beim 
Chipkauf eingespart hat. Selbst für nen Bastler spring was dabei heraus: 
Wer sich nicht zu blöd anstellt, kriegt mit der 32K-Bastlerversion des 
Keil mehr auf die Reihe als jemand, der statt nachzudenken immer nur 
nach der übernächst größeren Version greift und sich dann auch noch mit 
dem vom Gcc erzeugten Code befassen muß.

W.S.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
2 lesenswert
nicht lesenswert
W.S. schrieb:
> Und wieso aua? Für copy&paste ohne eigenes Nachdenken?

Stimmt, beim Copy&Paste hier in Deinen Beitrag hast Du offentbar 
tatsächlich nicht nachgedacht.

Der Source hält nicht, was Du vollmundig versprichst. Nicht nur, dass Du 
mit fehlerhaftem Code einen Anfänger in die Irre führst, er setzt auch 
keinen Dezimal-Punkt bzw. Komma. Dein Code konvertiert nur Integer. Da 
ist Peters Einzeiler hundertmal besser.

> Ach nö. Ich will
> den Leuten den Weg aufzeigen und ihnen nicht den Brei mit dem Löffel in
> den Mund füttern.

Mit fehlerhaftem Code? Ist das Dein Ernst?

> Man hätte sowas schon vor Jahren in der Lernbetty nachlesen können.

Warum sollte man das tun? Ist die Lernbetty der ultimative Code, der 
alle Fragen des Universums beantwortet? Offenbar nicht. Der 
Lernbetty-Code scheint nämlich einen Terminierungsfehler zu haben, der 
bei Dir glücklicherweise nicht zutage tritt. Dein Codefetzen ermuntert 
mich jedenfalls nicht zum Studium des Lernbetty-Codes - ganz im 
Gegenteil.

: Bearbeitet durch Moderator
Autor: Manfred (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bert schrieb:
> Bekomme z.B. den Wert von 4237 zurück. Diesen möchte ich in mV und V anzeigen.

Etwas in der Art habe ich gerade gebaut, um beim Schreiben eines 
Floatwertes auf eine SD-Karte den Dezimalpunkt los zu werden und durch 
ein Komma zu ersetzen.

Wert durch 1000 geteilt und zum Integer gemacht, hat der Integerwert die 
vollen Volt.

Schreibe Volt, schreibe Komma.

Wert durch 1000 minus den Integerwert habe ich die Millivolt.

Wenn Millivolt kleiner 100 schreibe eine Null raus.
Wenn Millivolt kleiner 10 schreibe noch eine Null raus.
Schreibe Millivolt.

Wenn Du Zeit hast, kannst Du das wirklich kleckerweise zum Display 
rausschreiben. Hat der Prozessor vorrangig andere Dinge zu tun, musst' 
einen String basteln und diesen in einem Zuge zum Display senden.

Peter D. schrieb:
>> Ach du Scheisse, das Monster printf auffahren um eine GANZZAHL
>> auszugeben ? Das nennt man aber Resourcenverschwendung par excellence.
> Für ungenutzten Flash gibt es kein Geld zurück. Die MCs haben heutzutage
> typisch ab 32kB aufwärts, da spielt das keine Rolle mehr.

Schön für Dich. Ich habe mich neulich in die Situation manövriert, dass 
32k nicht genügen wollten und ein Umbau der Hardware sehr aufwendig 
geworden wäre. Ich habe dabei eine Menge gelernt, anstatt 
hingeschissenen 60k läuft das nun mit 30k und hat auch eingermaßen 
Struktur bekommen. Aber schon klar, Speicher zahlt der Kunde, da kann 
der Programmierer nach Belieben mit herumaasen.

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenns denn unbedingt schnell und klein sein muß:
Beitrag "Formatierte Zahlenausgabe in C"

Autor: Peter D. (peda)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Manfred schrieb:
> Aber schon klar, Speicher zahlt der Kunde, da kann
> der Programmierer nach Belieben mit herumaasen.

Nö, ein guter Programmierer weiß schon ganz genau, worauf es ankommt. In 
der Regel kommt ein hoher Speicherverbrauch nur durch eine unüberlegte 
Aneinanderreihung von unnützen Funktionsaufrufen.
Der Code des TO zeigt sehr eindrucksvoll, wie man es nicht macht. Es 
wird 8* lcd_printlc aufgerufen, wo 1* völlig gereicht hätte.

Viel einsparen kann man daher, wenn man den Code etwas aufräumt und vor 
allem erstmal überlegt und nicht wie wild drauflos tippt. Ich nehme oft 
erstmal Papier und Bleistift, um mir vom Programmablauf einen Plan zu 
machen.
Der Verzicht auf Standardlibs bringt dagegen oft nur wenig Einsparung 
bezogen auf die gesamte Applikation. Er macht aber das ganze sehr 
unübersichtlich und damit fehleranfällig. Das wirst Du mit der Zeit aber 
auch noch merken.

An dem obigen Link sieht man doch schön, wie sich mein Programmierstil 
in den 9 Jahren geändert hat.

: Bearbeitet durch User

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.