Forum: Compiler & IDEs rechnen ohne float


von Sven (Gast)


Lesenswert?

Hallo,

ich habe das vergangene Wochenende an meinem Problem getüftelt, bin
aber nicht so recht weiter gekommen. Bestimmt kann mir jemand helfen,
damit ich nicht noch ein Wochenende über mein Problem brüte.

Also, ich habe an einen ATMega32 einen 24-Bit ADC (LTC2400)
angeschlossen, das funktioniert auch alles soweit. Nun möchte ich die
gemessene Spannung auf ein LED-Display ausgeben (das LED-Display wird
von einem MAX7221 angesteuert / acht 7-Segment Anzeigen). Die
Referenzspannung für den ADC beträgt genau 5 Volt. Also muss ich
folgende Berechnung durchführen: Referenzspannung geteilt durch 1677216
(Auflösung 24-Bit) mal gelieferte Bits von ADC. Oder auch
(5/16777216)*Bits vom ADC. Das möchte ich ohne Float Operationen
programmieren, ich benötige auch nur 4 Stellen hinter dem Komma.

Kann mir jemand helfen, hat jemand eine Idee ...

Vielen Dank für eine Antwort

von A.K. (Gast)


Lesenswert?

Daumenregel für solche Rechnungen, wenn per Integer: Erst
multiplizieren, dann dividieren. Sonst kommt meist 0 raus. Aber
Wertebereich beachten, gibt gerne Überlauf.

Erster Ansatz: (ADC-Wert-24bit  5  10000) / 1677216 => 0..49999.
Problem: Produkt passt nicht in 32 Bits. Entweder 64-Bit-Rechnung,
oder:

Zweiter Ansatz: Vom ADC-Wert das letzte Byte weglassen, weil bei 4
Nachkommastellen allenfalls für die Rundung der letzten Stelle von
Belang. Dann also: (ADC-Wert-16bit  5  10000) / 65536. Das geht nun
mit 32-Bit-Rechnung.

von Alexander (Gast)


Lesenswert?

Das dividieren eventuell noch durch Schiebeoperationen ersetzen.

/65536
>>16

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Und hast du dir den generierten Code mal angeguckt?

Der ist identisch.

von MSE (Gast)


Lesenswert?

@Jörg:
Ist das immer so oder 'nur' wenn man Optimierungen einschaltet?

Gruß, Michael

von A.K. (Gast)


Lesenswert?

Ich neige auch dazu, solche Feinheiten den Compilern zu überlassen. Aber
ich dachte bis vor Kurzem auch, dass schon die Compiler vor 20 Jahren
diesen Trick beherrschten, das müsste heute also selbstverständlich
sein. Ist jedoch leider nicht immer so. Der IAR/ARM Compiler entblödet
sich nicht, sowas (% mit 2-er-Potenz, unsigned, also nix anderes als
AND) allen Ernstes per Laufzeit-Division abzuwickeln.

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

>Der IAR/ARM Compiler...

Deswegen sind wir ja hier auch im GCC-Forum g

von Sven (Gast)


Lesenswert?

Vielen Dank für die Hilfe, ich bin jetzt allerdings auf das
"Folgeproblem" gestossen. Beim Compilieren gibt mir der Compiler
(WinAVR) die Warnmeldung aus: warning: integer overflow in expression,
und das Ergebnis stimmt auch nicht.

qword = (6711445*5*10000)/16777216; // Berechnung Volt

Die Variable qword ist mit uint64_t als 64 Bit-Zahl deklariert, also
kann man Ganzzahlen zwischen 0 und 18446744073709551615 in dieser
Variable dastellen (mein ich zumindest). Das Produkt der Multiplikation
ligt aber unterhalb deieser Grenze. Warum funktioniert das nicht, kann
mir vielleicht jemand einen Tipp geben.

Vielen Dank

von A.K. (Gast)


Lesenswert?

Das Produkt von Zahlen, die alle in 32 Bits passen, ist in C ein 32 Bit
Typ, egal ob's der Compiler berechnet, oder der Prozessor zur
Laufzeit. Und egal was links von der Zuweisung steht. Abhilfe: "LL"
an die Zahlen dranhängen, damit es 64 Bit Werte werden.

von Sven (Gast)


Lesenswert?

Jetzt geht es, vielen Dank A.K.

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.