Huhu zusammen,
ich bins nochmal, ich habe nochmal eine Frage da ich nun irgendwie
durcheinander gekommen bin mit meinem Code :/.
Und zwar steuer ich einen 16bit-DA Wandler per SPI an 2 Bytes werden
übertragen und ich messe auch den richtigen Spannungswert. so nun möchte
ich die beiden Bytes die ich an den DA wandler setze ins Verhältniss der
Spannung setzen (einen Soll-Wert)
Der DA Wandler gibt bei 0xFFFF 2,5 Volt aus dementsprechend 0V bei
0x0000
So nun wollte ich das auf einem LCD ausgeben dafür sieht meine Rechnung
so aus. Der gesendete Wert ist im uint_t16 "Data" register gespeichert.
Die Rechnung:
((((25 * Data) / 65536) /10))
eigentlich könnte die /10 gestrichen werden und die 25 durch 2,5 ersetzt
werden, aber ich wollte das ohne Kommazahlen machen da hatte ich
probleme mit.
So die Rechnung da oben wäre für die Vorkomma stelle, welche auch
korrekt angezeigt wird.
Nur bei der Nachkomma stelle hapert es.
Hier der Code
1
set_cursor(0,4);
2
charF[200];
3
sprintf(F,"D: %u.%03u",(((25*Data)/65536)/10)),
4
(((25*Data)/65536)/10)%1000;
5
lcd_string(F);
Bei der Nachkomma zahl wird mir immer nur eine 1 ausgegeben.
Ich denke das da irgendwas mit der Berechnung nicht stimmt oder das
Format falsch ist. Aber ich komm nicht drauf was falsch ist :/
Könnte mir da jmd auf die Sprünge helfen? Die die %1000 sagt doch aus
das 3 Nachkommastellen ausgegeben werden sollen oder?
Schönen Gruß
Sebastian
Wenn Data ein Wert 0xFFFF, also den größtmöglichen Wert für eine 16Bit
Variable hat, wird dir
25 * Data
einen Überlauf produzieren.
Um den zu umgehen, musst du die ganze Berechnung auf eine uint32
Berechnung hochhieven.
1
sprintf(F,"D: %u.%03u",(((25*Data)/65536)/10)),
2
(((25*Data)/65536)/10)%1000;
Rechne dir den Wert nur einmal aus.
1
uint16_tSpannung;
2
3
Spannung=(25*(uint32_t)Data)/65536;
4
5
sprintf(%u.%03u", Spannung / 10, Spannung % 10 );
Nun ist es natürlich nicht besonders sinnvoll, hier
Spannung = (25 * (uint32_t)Data) / 65536;
auf 32 Bit Arithmetik um zuschwenken, wenn dann sowieso durch 65536
dividiert wird. 25 / 65536 kannst du auch mit einem Taschenrechner
ausrechnen:
1
Spannung=Data/2621;
liefert für deine Zwecke dasselbe Ergebnis und du brauchst keine 32 Bit
Arithmetik
Hi Karl Heinz-
So ich habe mal grade das Programm umgeschrieben mit (uint16_t)Data.
Funktionieren tut es noch nicht - aber was mich stutzig macht ist das
gibt ein "002" aus
Zwischen dem "Data_test %10" von oben und unten besteht doch kein unter
schied oder?
Also es Funktioniert noch nicht ganz aber ich mach bestimmt noch nen
Fehler vieleicht fällt dir/euch ja etwas auf.
Schönen Gruß
Seb
> auf dem LCD ein "1.000 V" ausgibt aber der Code:
Mein Fehler.
Ich hab nicht aufgepasst.
Das sollte eigentlich heissen
> sprintf( E,"U= %u.%01u V",Data_test /10, Data_test %10 );
**
Du hast ja nur 1 'Nachkommastelle', wenn du den Rest mittels %10 nimmst.
>
1
>set_cursor(0,4);
2
>charOut[80];
3
>sprintf(Out,"Test= %03u.",Data_test%10);
4
>lcd_string(Out);
5
>
> gibt ein "002" aus
Das ist aber in der Tat seltsam.
Lass dir Data_test ohne Manipulationen direkt ausgeben. (Welchen
Datentyp hat Data_test eigentlich?)
Hi,
so
so siehts im moment aus: Data wird am Anfang fest mit einem Dezimalwert
von "32768" geladen also genau die hälfte von 65536.
Data und Data_test sind beides uint_16t
auf meinem Display sehe ich dann
"
U= 1.002 V
Data= 32768.
Test= 12.
"
aber das im Data_test eine 12 steht sollte ja eigentlich richtig sein
denn wenn ich die 32768 durch 2621 teile dann ergibt das ja eine 12,502
und die 502 werden ja dann nicht ins gespeichert sondern nur die 12.
Ich teste mal weiter.
Danke für deine Hilfe.
Gruß
Seb
Seb schrieb:
> "> U= 1.002 V> Data= 32768.> Test= 12.> ">> aber das im Data_test eine 12 steht sollte ja eigentlich richtig sein
Und auf dem Display sollte eigentlich "U= 1.2 V" stehen.
Ich sagte schon, ich habe in der sprintf Formatierung nicht darauf
geachtet, wieviele Kommastellen du haben willst.
Willst du 2 Nachkommastellen, dann muss in Data_test schon das 10-fache
rauskommen (also durch 262 dividieren und nicht durch 2621) und dafür
dann in der Ausgabe
Moin,
Ich glaube ich hab nen Fehler gefunden und zwar wollte mich mir einfach
mal eine uint_32t test; Zahl auf dem LCD ausgegeben.
Ich habe Dafür einfach mal ins test register eine 0xFFFFFFFF
reingeschoben und dann am LCD ausgegeben aber da kommt dann einfach ein
0xFFFF raus also nur 65535 also sollte das uint_16t die grötmögliche
Zahl sein die die Sprintf Funktion verarbeiten kann
Deinn wenn ich in dem test register mit der Dezimalzahl 70000 Lade und
dann in der sprintf zeile "test / 2" schreibe dann wird korrekt 35000
angezeigt.
ich muss noch mal weiter testen =)
schöne grüße
Seb
Seb schrieb:
> Ich habe Dafür einfach mal ins test register eine 0xFFFFFFFF> reingeschoben und dann am LCD ausgegeben aber da kommt dann einfach ein> 0xFFFF raus also nur 65535 also sollte das uint_16t die grötmögliche> Zahl sein die die Sprintf Funktion verarbeiten kann
Das ist Unsinn und ergibt auch logisch gesehen keinen Sinn. Wenn in
einer Sprache ein Datentyp standardmässig existiert, muss es auch
Ein/Ausgabefunktionen dafür geben. Alles andere wäre ein
Schildbürgerstreich.
Viel wahrscheinlicher ist es, dass du ganz einfach den falschen
Formatspezifizierer für einen uint32_t genommen hast.
Womit wir wieder mal beim Thema wären:
Eine Sprache wie C in den Details mittels 'Versuch und Irrtum' erlernen
zu wollen, funktioniert einfach nicht. -> Unterlagen müssen her.
Und auch ein 2-tes Thema, das auch immer wieder auftritt:
Es reicht einfach nicht, bei der Fehlersuche nur ein paar ausführbare
Anweisungen zu präsentieren. Mindestens genauso wichtig sind die
Datentypen der beteiligten Variablen, weil sie die genau Funktion der
Codesequenz modifizieren bzw. erst im Detail festlegen.
bekomme ich auf dem LCD "Uist= 1. 000" angezeigt
Aber nur noch mal für mich zum verständniss ich lade das AD_math mit
1024 und im sprintf befehl teile ich AD_math mit 1000 das ergibt dann
1,024 und die nachkomma zahl fällt weg und dann kommt der Modulo
Operator mit AD_math /1000 und gibt nur die Nachkomma stelle 024 aus
oder ?
denn wenn ich den gleichen Code wie oben nur die sprintf zeile ist
anders eingebe:
1
sprintf(A,"Uist= %03u",AD_math%1000);
erhalte ich wie gewünscht meine "Uist= 024" auf dem Display.
Irgendwie scheint das dem sprintf befehl "zuviel" arbeit zu sein.
ich forsche mal weiter :P
Hallo Karl Heinz,
Ich kann den ganzen Code gerne posten, das sollte bei der "normalen"
Fehlersuche auch üblich sein aber ich fühle mich eigentlich schon so
sicher das wenn ich am Anfang bei meinen Datentyp Deklarationen:
1
uint8_tfoo;
2
uint16_tAD_wert;
3
uint32_tAD_math;
4
uint8_tsw_old;
5
uint8_tsw_new;
6
uint8_tsw_comp;
7
int8_tsw_test;
eigentlich davon ausgegangen bin das AD_math halt den Datentyp uint32_t
hat. wenn ich den nämlich auf uint8_t setzte dann ist die maximal
ausgabe auch nur 256.
so mal grade eingeloggt damit ich die antworten auch bearbeiten kann.
Ich lese mir auch grade den befehl sprintf mal hier durch. Das sieht
eigentlich sehr ausführlich aus.
http://www.cplusplus.com/reference/clibrary/cstdio/sprintf/
Vielen Dank aber schonmal für die bisherigen Bemühungen ;).
Gruß
Seb
//EDIT Fehler gefunden
sprintf
%[flags][width][.precision][length]specifier
Seb schrieb:
> eigentlich davon ausgegangen bin das AD_math halt den Datentyp uint32_t> hat.
Das weißt du, weil du vor deinem Montior sitzt bzw. du das geschrieben
hast. Ich weiß es aber nicht. Ich sehe von deinem Programm nur das, was
du postest. Trotzdem versuche ich dir zu helfen. Je unvollständiger die
Informationen die du mir gibst aber sind, desto mehr muss ich Wissen
durch Raten ersetzen. Bis irgendwann der Punkt erreicht ist, an dem
meine Hilfe genauso zuverlässig wie das tagliche Horoskop in der Bild
ist.