Forum: Compiler & IDEs #define berechnen


von Daniel (Gast)


Lesenswert?

Hallo zusammen,

ich möchte einen festen Strom mittels #define vorgeben.
Da das ganze über einem Stromfühle und dem ADC gemessen wird, kommen
eben Wert wie 0x01BC raus oder so. Nun mächte ich den Strom in mA 
vorgeben, z.B. 800mA (also zb #define strom 800)
Das ganze müsste ja dann umgerechnet werden wie folgt:

[(800mA / 1000 * R) * 1024 ] / Uref = ADC-vergleichswert.

Wie gebe ich das jetzt in ein define, dass es funzt?

Ich hätte eigentlich so gedacht:
1
#define strom 800
2
#define R 0.5
3
#define Uref 5
4
#define vergleichswert ((strom/1000) * R) *1024) / Uref

Aber irgendwie nimmt das der Compiler nicht an.

Was mache ich falsch? Geht das überhaupt so wie ich mir des vorstelle?

Achja, ich arbeite mit dem AVR-Studio.

Gruß
Daniel

von Johannes M. (johnny-m)


Lesenswert?

Was heißt "der Compiler nimmt das nicht an"? Fehlermeldung?

Wenn der Compiler es schlucken würde, käme aber auch nicht raus, was Du 
vermutlich willst. Grundsätzlich werden alle Berechnungen zunächst in 
int durchgeführt, wenn nicht explizit etwas anderes angegeben ist bzw. 
wenn einer der beteiligten Operatoren nicht in int darstellbar ist. 
Bei Dir fängt es aber schon mit
1
(strom/1000)
an:
strom hat den Wert 800 -> passt in int
1000 passt auch in int
Also gibt das eine Integer-Division, und wieviel 800/1000 in int ist, 
solltest Du vielleicht mal als ersten Schritt überlegen...

Weiter geht's mit R , das bei Dir mit 0.5 definiert ist. Wenn er das 
R sieht, wird er also ab diesem Punkt in Gleitkomma weiterrechnen 
(weil das der größte Datentyp ist, der in dem Ausdruck vorkommt). Das 
Ergebnis der ganzen Geschichte ist also ein float und führt (wenn die 
restlichen Unzulänglichkeiten in der Rechnung beseitigt sind) zur 
Einbindung der Gleitkommabibliotheken, sobald der Wert irgendwo im 
Programm verwendet wird. Und das dürfte ziemlich sinnfrei sein. Gerade 
für eine popelige Multiplikation mit 0,5 ist das nicht sinnvoll. Die 
kann man eigentlich immer in Ganzzahlen machen.

von Peter (Gast)


Lesenswert?

Hm, ob der Präpozessor auch rekursive Definitionen übersetzt, bin ich 
mir nicht wirklich sicher, wo mault der Compiler denn? Ich tippe auf die 
letzte Zeile. Eventuell solltest du die Rechnung nicht in das Define, 
sondern dorthin schreiben, wo du den Wert nachher verwenden willst, das 
sollte tun.

Aber zwei andere Sachen:

> #define vergleichswert ((strom/1000) * R) *1024) / Uref

So ein Konstrukt ist prinzipiell gefährlich. Wenn du irgendwelche 
Rechnungen in ein Define packst, dann immer eine zusätzliche Klammer 
drum. Sonst kann es lustige Effekte geben. Beispiel:

#define WERT (5 * 2) + 10
int zahl = WERT * 10

-> Hier ersetzt der Präprozessor stur den "WERT" durch "(5 * 2) + 10", 
durch die verschiedenen Prioritäten der Operatoren (Punkt vor Strich...) 
wird das Ergebnis vermutlich nicht das erwartete sein.

Und zu letzt: Wenn man alle Definitionen in GROSSBUCHSTABEN schreibt, 
hat man etwas mehr Übersicht, ob man mit einer Variable oder einem 
"ersetzten Wert" rechnet.

Peter

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


Lesenswert?

Peter wrote:
> Hm, ob der Präpozessor auch rekursive Definitionen übersetzt, bin ich
> mir nicht wirklich sicher, ...

Klar macht er das.  Sonst würde von heute auf morgen die Welt stehen
bleiben. ;-)  Das heißt, wirklich rekursive natürlich nicht (du
kannst also nicht FOO definieren und dann in der Definition FOO
benutzen), aber geschachtelte Definitionen (andere Makros innerhalb
der Definition eines Makros auflösen) sehr wohl.

von Peter (Gast)


Lesenswert?

> Klar macht er das.  Sonst würde von heute auf morgen
> die Welt stehen bleiben. ;-)

Da war mir doch tatsächlich eine weltbewegende Möglichkeit völlig 
unbekannt ;-) Aber man lernt ja gern dazu, danke für die Aufklärung.

Zur Antwort von Johannes M.:
Also wenn man Float-Arithemetik vermeiden will, würde man vermutlich die 
Rechenoperationen so vertauschen, dass man die Multiplikationen zuerst 
ausführt (soweit vom Wertebereich möglich) und erst als letztes eine 
(Integer)-Division (durch das Produkt aller Divisoren) durchführt. So 
sollte doch lediglich ein Rundungsfehler von +-1 entstehen. Natürlich 
dürfen dann keine Float-Werte verwendet werden, aber das sollte sich ja 
durch Kommaverschiebung lösen lassen. Oder steckt da noch ein Denkfehler 
drin?

Peter

von Johannes M. (johnny-m)


Lesenswert?

Peter wrote:
> Oder steckt da noch ein Denkfehler
> drin?
Wie schon gesagt, ich vermute erstens, dass der OP eigentlich gar keine 
floats verwenden will und zweitens eben nicht bedenkt, dass 800/1000 
nunmal immer 0 ist...

von holger (Gast)


Lesenswert?

>Wie schon gesagt, ich vermute erstens, dass der OP eigentlich gar keine
>floats verwenden will und zweitens eben nicht bedenkt, dass 800/1000
>nunmal immer 0 ist...

Sicher alles richtig was du da sagst. Solange alles konstante
Werte sind kann man ja ruhig den Compiler (nicht den uC)
in float rechnen lassen. Anschliessend macht man ein int draus.

#define strom 800.0
#define R 0.5
#define Uref 5.0
#define vergleichswert ((unsigned int)(((strom/1000.0) * R) *1024.0) / 
Uref))

Passendes auf/abrunden noch nicht integriert.
Spricht irgend was dagegen?

von Peter (Gast)


Lesenswert?

#define vergleichswert ((strom/1000) * R) *1024) / Uref

=> Da fehlt ganz einfach eine Klammer! Richtig, bzw. besser wäre:

#define vergleichswert ((((strom/1000) * R) *1024) / Uref)

Der Complier macht dann automatisch einen int draus, falls Du das 
Resultat einem int zuweist.

von holger (Gast)


Lesenswert?

>#define vergleichswert ((((strom/1000) * R) *1024) / Uref)

>Der Complier macht dann automatisch einen int draus, falls Du das
>Resultat einem int zuweist.

strom/1000 ist und bleibt dann aber immer noch Null
bei integer Rechnung.

von Daniel (Gast)


Lesenswert?

danke euch,

mit dem Tip von Holger funktionierts.
Ich führe halt erst die Multiplikation aus, damit die Zahl erst groß 
wird.

Gruß

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.