AVR Integer-Arithmetik

OP (Firma: Brainit GmbH) #3946528
Lesenswert?

Hallo allerseits,

folgende Berechnung:
1
value = freq * 2^32 / 50MHz

würde ich gerne in uint32 durchführen. freq liegt im  Bereich 0..25MHz

2^32 / 50E6 ist zwar konstant, aber gebrochen (85.899...)

irgendwie stehe ich gerade wieder mal auf dem Schlauch, wie ich das so 
umschreibe, das alles möglichst gut in uint32 Platz findet....


guten Rutsch!
Gast #3946544
Lesenswert?

1
value = freq * 86 - ( (freq * 103) >> 10);

wäre mit 85,899414063 anstatt 85,89934592 schon recht nahe dran, 0.8ppm 
Fehler.


1
value = freq * 86 - ( (freq * 103) >> 10) - ( (freq * 143) >> 21);

Hier sind es 85,899345875 und somit nur noch 0,005ppm Fehler.
OP (Firma: Brainit GmbH) #3946558
Lesenswert?

Uwe S. schrieb:
> Stichwort: das erste Argument auf den Zieldatentyp casten.

Da kann ich grad nicht folgen...

> ZZ. Du möchtest das FTW für einen DDS berechnen..
ich weiss zwar nicht was das FTW ist, aber DDS ist heiss: Es geht um 
einen AD9835

Dispol schrieb:
> value = freq * 86 - ( (freq * 103) >> 10) - ( (freq * 143) >> 21);

Sieht sehr vielversprechend aus!

Nur - wie kommt man darauf? Wie leitet man das her? Ich brauch das zwar 
konkret nicht, aber was ist wenn die 50 MHz mal nicht 50 MHz sind? (wäre 
aber auf jeden Fall eine Konstante die zur Compile-Time bekannt ist)
Gast #3946563
Lesenswert?

>Nur - wie kommt man darauf?
85,89934592 sollen's sein.
Dann nimmst Du 86 und ziehst wieder (86-85,89934592) = 0,10065408 ab.

0,10065408 nehm ich jetzt so viele Mal x2, bis "fast" wieder ein Integer 
raus kommt.
103,06977792 (also 0,10065408 * 1024) ist nahe an 103.

Das ist die erste Zeile.
Leider ist dass auch noch etwas zu groß, deshalb macht ich das dann 
nochmals mit dem Rest vom Rest.

Immer natürlich aufpassen, dass die Zahl nie größer als 170 
(32Bit/25MHz) wird, damit es keinen Überlauf gibt.
#3946565
Lesenswert?

Hallo Michael,
1
FTW = freq * 2^32 /50^6 = freq * 86,8993..
Das wird zu nächsten größeren ganzen Zahl aufgerundet und der Fehler 
wieder abgezogen.
1
86 -0,1007..

Der Fehlerwert -0,1007 lässt sich durch einen Faktor 1024 auf eine ganze 
Zahl aus /Z skalieren.
1
K1 = -0,1007 * 1024 = -103
Den Skalierungsfaktor 1024 = 2^10 muss man später wieder herausrechnen.

Also ist der aktuelle Näherungswert:
1
86 - 103/1024

Der nächste Korrekturterm wäre dann
f2 = 2^21
K2 - (86 - 103/1024) * f2
K2 = (2^32 /50^6) - (86 - 103/1024) * f2
K2 = -142,9052 = -143

Somit gilt
1
FTW = freq * (86 -(103 >> 10) -(143 >> 21))
OP (Firma: Brainit GmbH) #3946578
Lesenswert?

Ich danke euch! (unglaublich zu welchen Zeitpunkten man hier Hilfe 
bekommt!)

ich glaube ich habe verstanden....

Aber eine Folge-Frage: Angenommen, ich wollte den "input-parameter" 
verhundertfachen, um "centiHertz" (Hundertstel Hz) abbilden zu können.

also maximal 25E8, was sich gerade noch in 32bit abbilden lässt

Der Faktor 85.irgendwas verkleinert sich damit auf 0.85

allerdings hab ich bei der Multiplikation keinen "Headroom" mehr, oder

ginbge das auch?
Gast #3946636
Lesenswert?

Ginge auch.
Angenommen, es wäre 0.75, dann wäre es ja:

1
value = freq - frq >> 2;


jetzt ist's halt etwas (sehr langes) in der Art:
1
value = freq +- frq >> 1 +- frq >> 2 +- frq >> 3 +- frq >> 4 +- frq >> 5 ...;

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren