Forum: Mikrocontroller und Digitale Elektronik XC8 Compiler - Rechnung mit 64 bit


von Michael S. (rbs_phoenix)


Lesenswert?

Hallo zusammen. Ich will mit Hilfe eines PICs (via SPI) einen DDS 
(AD9834) ansprechen. Dieser bekommt am Takteingang ca. 20MHz (vielleicht 
auch ein bisschen mehr) und kann Frequenzen ausgeben, die mit Hilfe 
eines 28bit Registers bestimmt werden können.

Mein Ziel ist es einen PIC zu haben, der über den SPI/I²C eine Frequenz 
bekommt (in Hz), diese dann umrechnet und über SPI an den AD9834 sendet.
Wenn ich nun die Frequenz umrechnen will, muss ich ja die Formel aus dem 
Datenblatt vom AD9834 (fout = fMCLK/2^28 * FreqRegister) umstellen und 
bekomme FreqRegister = fout * 2^28 / fMCLK.

FreqRegister (temporär im PIC) und fout sind vom typ uint32, damit z.b. 
20.000.000 Hz in fout und die 28 bit in das FreqRegister passen.

Wenn ich jetzt aber 2^28/20.000.000 Teile, bekomme ich 13,4217728 raus, 
das ja als int gerundet wird (auf 13). Dann hab ich aber ein Problem, 
wenn z.B. 10MHz ausgeben will. Statt den 10MHz kommen nur 9,68MHz.

Also habe ich gedacht, ich rechne das fout * 2^28 zuerst und teile erst 
danach. Dann bekomme ich ganz genau 10MHz raus. Doch da 10MHz * 2^28 = 
2.684.354.560.000.000 ist (irgendwas bei 40 bit), wird das bei einer 
32bit-Rechnung ja einen Overflow geben (oder schafft der XC8-Compiler 
das, auch wenn er keinen 64bit int anbietet?).

Meine erste Planung war ein Mini-PIC (PIC12[8pin]/PIC16[14pin]) zu 
nehmen. Intern mit 32MHz getaktet, diese Rechnung eigentlich nur 
einmalig (max. alle 5 Sekunden), sollte eigentlich kein Problem sein. 
Dafür viel schneller zu programmieren als ein dsPIC, zumal Dieser größer 
ist und nur mit 3.3V läuft (die ich weder habe, noch sonstwo brauche).

Hat jemand einen Vorschlag, wie diese Rechnung noch gehen könnte (ohne 
gleich nen dsPIC zu nehmen)?
Kann ich nich sogar das 2^28/20.000.000 als double casten? Doch der 
Compiler behandelt die in der Rechnung vorhandenen Zahlen als double, 
der aber nich bis 20.000.000 geht (oder verwechle ich das)

Ich hab auch schon gedacht, ich könnte auch einen 16.777.216 MHz Quarz 
nehmen. Dann kann ich den Speicher von fout einfach ein paar mal shiften 
und fertig. Doch ich hab soeinen nur bei digikey gefunden und kostet 
ohne Versand 15-16€.


Nicht falsch verstehen. Ich bin sonst auch der Meinung, dass man nicht 
jeden µC bis zum letzten ausreizen muss, doch da mir das SOIC8 Gehäuse 
entgegen kommt und es ja ansich nich an der Rechenleistung hapert, würde 
ich erstmal versuchen, es mit dem 8bitter hinzubekommen.

von hele (Gast)


Lesenswert?

Du könntest kürzen, also vorher Zähler und Nenner skalieren. evtl. 2 
hoch n also 2^20/(Frequenz/2^8) oder besser mit float rechnen wenn die 
Möglichkeit besteht.

von Fabian O. (xfr)


Lesenswert?

Michael Skropski schrieb:
> Kann ich nich sogar das 2^28/20.000.000 als double casten? Doch der
> Compiler behandelt die in der Rechnung vorhandenen Zahlen als double,
> der aber nich bis 20.000.000 geht (oder verwechle ich das)

Schon ein normaler float geht bis 3,4 * 10^34. Deine Zahlen passen da 
lockerst rein. Wenn Du die Berechnung nicht oft brauchst, dann nimm 
einfach einen float oder double.

von W.S. (Gast)


Lesenswert?

Fabian O. schrieb:
> Schon ein normaler float geht bis

Denkfehler. Ein normaler Float hat mal gerade 24 Bit Mantisse und ist 
damit noch 4 Bit von der nötigen Bitanzahl entfernt.

Michael Skropski schrieb:
> Also habe ich gedacht, ich rechne das fout...

Tja, du müßtest eben mit double rechnen - wegen der 
Mantissenstellenzahl. Aber abgesehen davon scheinst du mir noch ein 
bissel unbeholfen zu sein.
Also denk doch mal nach:

Frequenz = Steuerwort * (FTakt / 2E28);

oder umgekehrt

Steuerwort = Frequenz * (2E28 / FTakt);

Fällt dir denn da nix auf? Wirklich nix?
Nun, den 2. Term kann man sich vorab per Taschenrechner ausrechnen und 
als Konstante einsetzen. Da fehlen dir beim Benutzen von float zwar 
immer noch 4 Bit bis zur vollen Stellenzahl von 28 Bit, aber du kannst 
wenigstens einigermaßen deine Frequenz einstellen.

Ansonsten solltest du dich mal etwas in Assembler üben. Schau mal dort: 
"http://www.mikrocontroller.net/attachment/168357/Fanet2.zip";

Dort rechne ich mit 40 Bit, um für einen AD9951 das 32 bittige 
Steuerwort zu erzeugen und obendrein noch ein paar Bit zum Runden zu 
haben.


W.S.

von Michael S. (rbs_phoenix)


Lesenswert?

Tut mir leid, dass ich jetzt erst Antworte. Ich hatte etwas viel um die 
Ohren.

W.S. schrieb:
> Ein normaler Float hat mal gerade 24 Bit Mantisse und ist
> damit noch 4 Bit von der nötigen Bitanzahl entfernt.

Das dachte ich mir auch und auch double hat nur 32bit insgesamt.

Das mit dem Vorher ausrechnen habe ich mir auch schon gedacht, ich war 
mir auch sicher, das geschrieben zu haben, doch anscheinend hab ichs 
nich geschrieben.

Michael Skropski schrieb:
> Wenn ich jetzt aber 2^28/20.000.000 Teile, bekomme ich 13,4217728 raus

Ich werde wohl dann einfach den "PIC24F32KA302" nehmen. Der XC16 hat 
64bit Datentypen (long long, long double) und läuft auch mit 5V. XLP und 
28lead QFN. Passt. Kleiner wär zwar schön, aber so scheint es doch 
einfacher.

Ich gucke aber nochmal nach einer Möglichkeit, einen wirklichen double 
in den XC8 zu bekommen. Verstehe nicht, warum das nicht schon drin ist, 
sondern float, double und long double gleich setzen.

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.