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:
1
spannung_anz1=spannung_anz%10;// 4. Zahl
2
spannung_anz2=spannung_anz/10;
3
spannung_anz3=spannung_anz2%10;// 3. Zahl
4
spannung_anz4=spannung_anz2/10;
5
spannung_anz5=spannung_anz4%10;// 2. Zahl
6
spannung_anz6=spannung_anz4/10;
7
spannung_anz7=spannung_anz6%10;// 1. Zahl
8
spannung_anz8=spannung_anz6/10;
9
10
itoa(spannung_anz7,Buffer,10);
11
lcd_printlc(4,9," ");
12
lcd_printlc(4,9,Buffer);
13
14
itoa(spannung_anz5,Buffer,10);
15
lcd_printlc(4,11," ");
16
lcd_printlc(4,11,Buffer);
17
18
itoa(spannung_anz3,Buffer,10);
19
lcd_printlc(4,13," ");
20
lcd_printlc(4,13,Buffer);
21
22
itoa(spannung_anz1,Buffer,10);// 4. letzte Zahl stimmt
23
lcd_printlc(4,15," ");
24
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
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.
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?
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 ....
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 ...
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.
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:
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:
1
#include<stdlib.h>
2
#include<stdio.h>
3
4
5
voidprint_mV(uint16_tmV){
6
div_tsplitted=div(mV,1000);
7
printf("%3d.%03d\n",splitted.quot,splitted.rem);
8
}
(Statt printf einfach die Wunsch-Ausgabefunktion verwenden).
Wird dann zu:
1
print_mV:
2
/* prologue: function */
3
/* frame size = 0 */
4
/* stack size = 0 */
5
.L__stack_usage = 0
6
ldi r22,lo8(-24)
7
ldi r23,lo8(3)
8
rcall __divmodhi4
9
..... 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
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:
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
... 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
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.
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.
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.
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.