Forum: Mikrocontroller und Digitale Elektronik PIC C18 float -> int


von Edi _. (edi_2k)


Lesenswert?

Hallo.

ich habe vor aus 4 Integerwerten (16bit) den Mittelwert zu bilden und 
diesen dann per rs232 zu senden.

vorgehensweise:

float avg = 0;
avg += Wert[1...4]
avg = avg / 4;

da die rs232 schnittstelle natürlich keine float werte senden kann caste 
ich auf integer, da der mittelwert den wertebereich nie überschreiten 
kann.

int avg_send = (int)avg;

danach sende ich high- und lowbyte getrennt. der empfangene wert ist 
jedoch falsch. gibt es beim casten irgendeine sache, die ich übersehen 
habe?

danke

von Karl heinz B. (kbucheg)


Lesenswert?

Nein.
Was bedeutet denn 'falsch'?
Nenn doch mal ein paar konkrete Zahlen und zeig
den tatsächlichen Code.

von Bernhard (Gast)


Lesenswert?

Hast du bei avg_int vielleicht einen Überlauf?
Setzt du die beiden Bytes auch richtig zusammen (beide in HEX, danach 
die beiden HEX-Bytes zusammen in int)?

von Edi _. (edi_2k)


Lesenswert?

folgendes problem hatte ich.

ich verwendete zuerst einen PIC16F877A mit dem Sourceboost C2C 
Compliler.
dessen größter datentyp war ein 'int' mit 16 bit.

ich muss jedoch den mittelwert aus 4 'int' Werten ermitteln. dazu teilte 
ich die einzelnen werte vorher durch 4 und addierte sie anschließend.

a/4 + b/4 + c/4 + d/4 = avg

statt

(a + b + c + d)/4 = avg

das ist nach dem assoziativgesetz erlaubt. man erhält jedoch eine 
ungenauigkeit von 2 bit, da man die letzten beiden bit jedes messwerten 
raus shiftet.

um dies zu ändern stieg ich auf PIC18F4550 um und verwende den C18 
Compiler von Microchip, der sowohl 'double' als auch 'float' beherrscht.

unsigned int val_0 ... val_4, sum_val;
unsigned int AVG_1,AVG_2;
float temp;

...

...     temp = (float)(val_0 + val_1 + val_2 + val_3);
        AVG_2 = temp/4;
        // diese version funktioniert nicht
        // messwert unten (22892) erscheint hier als 6508

        // vier zu mittlende messwerte (int)
        val_0 = val_0 >> 2;      //val_0 = val_0/4
        val_1 = val_1 >> 2;
        val_2 = val_2 >> 2;
        val_3 = val_3 >> 2;
        sum_val = val_0 + val_1 + val_2 + val_3;
        // diese version funktioniert
        // messwert z.b. sum_val = 22892



alle variablen werden vor jedem aufruf der funktion, die die messwerte 
abholt zu 0 gesetzt.

es sieht so aus, als würden die zwei MSBs fehlen.


von Mike (Gast)


Lesenswert?

Versuche mal

temp = (float)val_0 + (float)val_1 + (float)val_2 + (float)val_3;

von Edi _. (edi_2k)


Lesenswert?

das wars! im nachhinein auch logisch, da beim addieren von 4 mal 0xFFFF 
ein 18 bit wert entsteht, bei dem dann die beiden MSBs fehlen.

danke!

von Bernhard (Gast)


Lesenswert?

Vorsicht, alle Zahlen als float zu verarbeiten ist sehr 
Ressourcenfressend. Wenn du
temp = (floatval_0 + val_1 + val_2 + )((unsigned long)val_3);
schreibst, dann sollte deine Rechnung wesentlich schneller gehen und 
weniger Speicherplatz verbrauchen.

von Karl heinz B. (kbucheg)


Lesenswert?

@bernhard:

Lies mal weiter oben.
Auf seinem PIC hat er kein long.
Wenn er eines hätte, wäre der ganze Umstieg auf float
gar nicht nötig.

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.