Hallo,
ich habe ein Problem mit, wie im Titel schon erwähnt, mit Fikommazahlen.
Ich verwende das Luminary LMS38962 Microcontroller Board von TI. Dabei
verwende ich die miteglieferte DriverLib. In dieser ist eine Funktion
für den Sinus definiert. Allerdings wird für die Berechnung dieser ein
Fixkommawert des Datentyps unsigned long benötigt (0.32). Dieser gibt
den Winkel in Prozent an, also 2*pi = 100% = 0.999999999...
Soviel ich aber weiß (vielleicht ist dieses vermeintliche Wissen falsch)
werden die Werte aber als Gleitkomma (also mit Mantisse und Exponent)
abgespeichert.
Leider bin ich nicht in der Lage den Gleitkommawert in einen
Fixkommawert umzuwandeln, oder direkt einen solchen zu erzeugen (wär
noch viel besser). Habe schon die ganze Allwissende Müllhalde
abgeklappert, jedoch ohne Erfolg.
Ich hoffe ihr könnt mir weiterhhelfen.
mfg Graph Oszillo
Graph Oszillo schrieb:> Leider bin ich nicht in der Lage den Gleitkommawert in einen> Fixkommawert umzuwandeln
Woran scheitert es denn?
Auf einem µC ist es oft vorteilhaft Fixkommazahlen auf Basis vom
2er-System zu verwenden. Welche Auflösung brauchst du für deine
Fixkommazahlen?
Uh, Ernsthaft?
Also, nehmen wir mal das Dezimalsystem. Was ergibt sich aus:
0,09 + 0,01?
Und nun mal das Hexadezimalsystem. Was ergibt sich aus:
0x0F + 0x01?
Da der Wertbereich deiner Angabe nach sich auf 0,0 - 0,999~ erstreckt,
sagen wir mal bis 1,0, und Du nun 32 Bit hast... Wenn die 32 Bit nun die
Nachkommastellen angeben, so ist das 0xFFFFFFFF was dann 0.999~
entsprechen soll. Dieser Hex-Wert entspricht dezimal 4.294.967.295. Die
1,0 wäre dann 4.294.967.296 oder in Hex 100000000. Klickt es nun?
Anders ausgedrückt: Du dividierst den Fixed-Point von "0,32" Bit ganz
einfach durch 4.294.967.296 um einen Fließkommawert im Bereich 0,0 -
0,999~ zu erhalten. Wenn Du aber den Wertbereich 0,0 - 1,0 haben willst,
dann dividierst Du ganz einfach durch 4.294.967.295.
Grüße,
Chris
Edit: Oder wenn Du den 32-Bit Fixed-Point Wert haben willst dann
dividierst Du die 4.294.967.296 oder 4,294,967,295 einfach durch den
Fließkommawert (der den Bereich 0,0 bis 0,999~ oder 1,0 haben muss).
Das ist genau das Gleiche wie beim Ergebnis eines AD-Wandlers. Da ist
die Zahl nur nicht so groß.
10-Bit-ADC skaliert auf Uref:
U = Uref * ADC_Value / 2^10 (=1024)
Dein Sinus skaliert auf 1:
sin = (1 * )Value / 2^32 (= s.o.)
Oder auf 255 zur Ausgabe auf einen 8-Bit DA-Wandler
DA-Value = 255 * Value / 2^32
mfg.
Wieso braucht man eigentlich eine Tabelle mit dem Typ unsigned long,
wenn man Zahlen aus dem Bereich 0,000 .. 0,999 - also drei Stellen im
Dezimalsystem - als Fixkommawerte ablegen möchte. Um die Zahlen
darzustellen, reichen 10-Bit, d.h. 22-Bit sind völlig nutzlos.
Welche Genauigkeit muß denn die Tabelle nun wirklich haben, d.h. wie
sauber muß der Sinus sein?
Werner schrieb:> Welche Genauigkeit muß denn die Tabelle nun wirklich haben, d.h. wie> sauber muß der Sinus sein?
So sauber wie möglich. Also unendlich viele Werte. Wie bei Analog.
Das geht aber digital nicht. Das ist immer endlich. Also rechnet man auf
einem 32-Bit-Rechner auch mit 32 Bit. Damit rechnet er sowieso.
Und zwar solange wie möglich. Das Umrechnen in eine Dezimalzahl ist
erst der letzte Schritt und nur für uns. Rechnen kann der Controller
besser binär. Und die Rundungsfehler bleiben bei 32 Bit klein.
Auf einem 8-Bitter, wo das zum zeitaufwendigen K(r)ampf wird, überlegt
man sich, ob man so viele Werte wirklich braucht, wenn man sie z.B. auf
einen 10-Bit DAC ausgeben will.
mfg.
Thomas Eckmann schrieb:> Auf einem 8-Bitter, wo das zum zeitaufwendigen K(r)ampf wird, überlegt> man sich, ob man so viele Werte wirklich braucht, wenn man sie z.B. auf> einen 10-Bit DAC ausgeben will.>> mfg.
Wobei man auch da beachten muss das es in gewissen Situationen ein paar
gute Tricks gibt. Viele µC haben einen Hardware-Multiplier, also eine
Einheit die in meistens einem Takt eine Multiplikation machen kann.
Damit kann man aber auch auch eine Division machen. Natürlich nur unter
gewissen Bedingungen.
Grüße,
Chris
Werner schrieb:> Wieso braucht man eigentlich eine Tabelle mit dem Typ unsigned long,> wenn man Zahlen aus dem Bereich 0,000 .. 0,999 - also drei Stellen im> Dezimalsystem - als Fixkommawerte ablegen möchte. Um die Zahlen> darzustellen, reichen 10-Bit, d.h. 22-Bit sind völlig nutzlos.>> Welche Genauigkeit muß denn die Tabelle nun wirklich haben, d.h. wie> sauber muß der Sinus sein?
Falls Du dich damit auf mein Beispiel beziehst dann beachte bitte das
ich nicht drei Nachkommastellen angegeben habe, sondern z.B. 0,999~,
wobei das ~ dann "unendlich" repräsentiert.
Grüße,
Chris
Thomas Eckmann schrieb:> So sauber wie möglich. Also unendlich viele Werte. Wie bei Analog.
"So sauber wie möglich" kann kein Mensch bezahlen und ist meistens nicht
wirklich nötig.
Was hat die Sauberkeit des Sinus mit "Analog" und "unendlich viele
Werte" zu tun. Als Kriterium würde man eher sowas wie SNR oder Dämpfung
der Oberwellen erwarten. Aber vielleicht kann sich unser Graph mal zu
seinem Problem äußern.
Vielen Dank an alle!
Von mir aus müsste der Wert nicht mal auf drei Nachkommastellen genau
sein, da ich diesen nur auf dem 128x96 Pixel großen Display zeichnen
werde. Allerdings rechnet diese Sinusfunktion sowieso keine Werte selbst
aus. Sie hat die Werte eines viertel Sinus (90°) in einem Array als 0.16
Fixpoint unsigned short gespeichert, und legt diese Kurve mehrmals
aneinander. Ausgegeben wird ein 16.16 Fixpoint Long.
Bezüglich der Umwandlung hätte ich noch eine Frage: Wenn ich einen 16.16
Fixpoint wieder auf Floatingpoint umwandeln will, muss ich dann einfach
durch 2^16 dividieren?