Im KNX-Protokoll werden Leistungen als 4 Byte Gleitkommazahl übertragen.
Mir ist allerdings nicht ganz klar, wie ich eine Zahl (z.B. Integer) in
eine (KNX-)Gleitkommazahl mit 4 Byte umrechnen muß.
Ein Quellcode in C wäre super. Ich habe gegoogelt, aber nicht wirklich
gute Treffer gelandet.
Matthias schrieb:> Im KNX-Protokoll werden Leistungen als 4 Byte Gleitkommazahl> übertragen.> Mir ist allerdings nicht ganz klar, wie ich eine Zahl (z.B. Integer) in> eine (KNX-)Gleitkommazahl mit 4 Byte umrechnen muß.>> Ein Quellcode in C wäre super. Ich habe gegoogelt, aber nicht wirklich> gute Treffer gelandet.
die frage ist, wie werden gleitkommazahlen in KNX repräsentiert?
Wenn es einfach nur das IEEE754 gleitkommaformat ist, dann solltest du
einfach mal auf wikipedia nachlesen. Du musst einen Exponenten, Mantisse
und Vorzeichenbit setzen. Wie lange diese Felder sind, regelt der
Standard.
https://www.inf.hs-flensburg.de/lang/informatik/ieee-format.htm
Poste mal eine Beispielkommazahl und die zugehörigen Bits. Dann kann man
vielleicht auf das Format schließen.
sonst gibt es doch
http://www.knx-gebaeudesysteme.de/sto_g/_All/MANUALS/ABAS_121/FR/05_function_elements/ConverterElement/index.html
?
Matthias schrieb:> Jetzt muß ich> nur noch einen Quellcode in C dazu finden.
Nö. Du solltest lieber das Prinzip verstehen lernen.
Also, zumeist besteht eine Gleitkommazahl aus dem Vorzeichen (1 Bit),
dem Exponenten (8 Bit) und der Mantisse (23 Bit). Jetzt fragst du dich
vielleicht, warum nicht 24 Bit Mantisse? Nun, das hängt an der
Normierung der Mantisse, die solange linksverschoben wird, bis das MSB
gesetzt ist. Der Exponent wird dabei angepaßt. Je nach Implementation
kann die Mantisse damit
- von 0.5 bis 1 (- 1 LSB)
oder
- von 1.0 bis 2 (- 1 LSB)
gehen. Rein rechentechnisch ist das egal. Es hat nur mit dem Wert des
Exponenten zu tun.
Da nun das MSB immer gesetzt ist, braucht man es nicht in der Zahl zu
merken, sondern kann an dessen Stelle das Vorzeichen setzen.
W.S.
Moin,
W.S. schrieb:> Du solltest lieber das Prinzip verstehen lernen.
Yupp. Und das Prinzip ist: Bloss nicht selber in
Floatingpointverarbeitung rumruehren, wenns nicht unbedingt sein muss.
Das den Compiler machen lassen. Einfach aussenrum casten.
Die printfs in meinem Code sind nur dazu da, dass man "was sieht" in der
console. Mit der eigentlichen Wandlung haben die nix zu tun.
Gruss
WK
Lothar M. schrieb:> Bei passender Bytereihenfolge/Endian reicht es auch, einen Pointer auf> das erste Element zu setzen und den auf (float) zu casten:
Habe nun eine Funktion für das Wandeln geschrieben. Geht sehr einfach.
So einfach geht es doch nicht. Meine Funktion zur KNX-Übertragung
verwendet für die 4 Datenbyte grundsätzlich unsigned long. Daher wird
das Format vom Compiler wieder zurück gewandelt. Anstelle der 0x447A0000
(1000 als float32) werden 0x000003E8 (1000 als unsigned long)
übertragen.
Wie kann ich 0x447A0000 float in 0x447A0000 unsigned long wandeln?
Habe schon versucht, den Float32 Wert in 4 einzelne Bytes zu zerlegen,
um die dann wieder als unsigned long Wert wieder zusammen zu bauen. Aber
der Compiler will das Zerlegen nicht machen:
1
floatfTemp;
2
charelement[4];
3
element[0]=(fTemp&0x000000FF)>>0;
4
element[1]=(fTemp&0x0000FF00)>>8;
5
element[2]=(fTemp&0x0000FF00)>>16;
6
element[3]=(fTemp&0x0000FF00)>>24;
Die Profi-Programmierer werden schon die Kriese bei der Frage
bekommen...
Lothar M. schrieb:> Bei passender Bytereihenfolge/Endian reicht es auch, einen Pointer auf> das erste Element zu setzen und den auf (float) zu casten:char cval[4];> :> :> float fval = *(float*)cval;
Lothar M. schrieb:> Bei passender Bytereihenfolge/Endian reicht es auch, einen Pointer> auf> das erste Element zu setzen und den auf (float) zu casten:char cval[4];> :> :> float fval = *(float*)cval;
Äußerst unsportlich, dabei nicht auf den Haken mit strict aliasing
hizuweisen.
Dergute W. schrieb:> Yupp. Und das Prinzip ist: Bloss nicht selber in> Floatingpointverarbeitung rumruehren, wenns nicht unbedingt sein muss.
Und das verstehst du als "Verstehen des Prinzips"?
Hmm..
Naja, wenn ich mir all die z.T. abstrusen Verrenkungen anschaue, die
diverse C-Programmierer hier gepostet haben, um irgendwelche int oder
long Zahlen nach float zu wandeln (ohne das anscheinend spezielle
KNX-Gleitkommaformat zu kennen), dann graust es mich.
Ich hätte hier noch eine selbstgeschriebene kleine GK-Arithmetik incl.
Ausgabekonverter für die PIC16 auf Lager - selbstverständlich in
Assembler geschrieben, aber die habe ich bereits vor Zeiten hier mal in
einem anderen Projekt gepostet.
W.S.
Moin,
W.S. schrieb:> (ohne das anscheinend spezielle> KNX-Gleitkommaformat zu kennen), dann graust es mich.
Was ist denn daran speziell? Wenn ich nach KNX und 32bit float google,
dann springt mich von ueberall IEEE754 an...
Gruss
WK
Dergute W. schrieb:> Was ist denn daran speziell?
Weiß ich nicht, hab mich dafür noch nicht interessiert.
Ansonsten ist das IEEE754 Format recht einfach zu verstehen, siehe Bild.
Was mich damals bei den PIC16 daran gestört hatte, war die notwendige
Schieberei mit dem Exponenten, die sich bei den PICs nicht besonders gut
macht - und die für Konvertierungen auf dem PIC16 ungünstige
Mantissengröße 1.0 bis 1.999usw. Von daher hatte ich das Vorzeichenbit
direkt an die Stelle des MSB der Mantisse gesetzt und den Wertebereich
der Mantisse auf 0.5 bis 0.999usw. gesetzt.
W.S.
Dergute W. schrieb:> Moin,>> Matthias schrieb:>> So einfach geht es doch nicht.> Ach.> memcpy(element, &float, 4);> :-)>> Gruss> WK
tja, wenn man nur von vorne rein wüsste was der TO machen will^^