AD9834 Frequenzberechnung Frage

  • Hallo,
    Auf der Seite von AD http://designtools.analog.com/dt/ad98334/ad9834.html kann man sich die Codewörter für die Frequenzen sehr schön ausgeben lassen.
    Was mir nicht gelingt ist die umgekehrte Rechnung, ich habe einen Teilerwert und will daraus die Frequenz berechnen, die Formel laut AD Datenblatt ist Quarzfrequenz/2^28*Teilerfactor.
    Kann mir jemand sagen wo der Trick bei diesem IC ist?
    Der Hintergrund ist der, das ich vermeiden will Floatingpoint-Arithmetik in AVR zu benutzen und in einem DDS nur die Teilerfaktoren ändern will bei der Abstimmung.



    Danke im voraus
    72 de Wolf, DL2WRJ

  • Kennst Du http://roland.cordesses.free.fr/dds5.htm? Dort ist ein Link auf ein C-Programm. Dort findest Du die Funktion dds_set_frequency(), die nicht sonderlich kompliziert aussieht. Das sollte "leicht" umzukehren sein.


    Übrigens: für 2^28 (oder irgendwas wie 2^x) brauchst Du kein Real-Arithmetik, da reicht die "schiebe nach links" Operation: 2^4 = 1 SHL 4 = 16. Mit 32 Bit unsigned kannst Du 0 .. 4294967295 darstellen. Das wären dann über 4 GHz. Daher solltest Du mit Ganzzahl-Arithmentik bzw. Festkomma-Artithmetik auskommen.

  • Hallo Holger,
    Vielen Dank für den Link, den kannt ich wirklich noch nicht. Mir ist es bisher nur nicht gelungen mit Hilfe der oben erwähnten Formel die Frequenz aus dem Teilerverhältnis zurück zu rechnen. Daran tüftle ich zur Zeit.


    BSP:
    75Mhz Quarz Freq: 10 Mhz = LSB 6222 MSB 4888 = (ohne ctrl-Bits) 222 8888 (alles Hex)
    Nun die Frage wie errechne ich aus dem Wert 222 8888 wieder die 10MHz?


    72 de Wolf, DL2WRJ

  • Du startest mit http://www.analog.com/static/i…es/data_sheets/AD9834.pdf. Dort findest Du gleich auf Seite 1 das Blockschaltbild.


    Dann mußt Du wissen, welche Werte bei dir Fselect, Pselect etc haben. Und natürlich was bei Dir an f_in anliegt.


    Dann siehst Du, daß vom seriellen Eingang diverse Register gesetzt werden: 16 Bit Control, 2x 12 Bit Phase, 2x24 Bit Freq Req. Auch hier mußt Du wissen, wie die Register stehen. Das Muster "222 8888" ist höchstwahrscheinlich nicht die komplette Programmierung. das sind ja erst 28 Bits.


    Mit den Wissen des Inhaltes des Control-Registers gehst Du nun auf Seite 18 und wurstelst Dich durch.


    Auf Seite 1 oben rechts steht noch, daß bei f_in 75 MHz die Auflösung 0.28 Hz ist. Und siehe da, 2^28 = 268,435,456. Und 75 MHz / 2^28 = 0.279396772385. Nennen wir das mal "f". Das bedingt aber, daß diverse Muxe passend geschaltet sind.


    Dann wären Deine 2228888 zur Basis 16 dezimal 35,817,608. Und das mal "f" wäre 10,007,324.0697, also rund 10 MHz.



    Übrigens erscheint mir Deine Frage so spezifisch, das Du entweder Glück hast, und jemand hat sowas schon mal gemacht oder ... du bekommst nur so dumme Antworten wie meine, die den Tenor "finde es doch selbst heraus" beinhalten :) Ich habe mit ADS9834 Chip keine Erfahrungen, habe aber ein Programm, um das bei ICS307-2 (das Teil im Harzburg II) zu berechnen. Das geht dort konzeptionell genauso, allerdings erscheint mir auf den ersten Block der ADS9834 komplexer. Dein Chip kann ja FM und PM!


    Ich hatte übrigens ein reziprokes Problem: im PDF vom ICS307-2 ist der von Dir benötigte Rechenweg genauestens beschrieben (wie komme ich vom Bitmuster zu f_out). Allerdings brauchte ich das umgekehrte "Welches Bitmuster braucht ich für eine gewünschte f_out". Dafür gibt's nur eine Webseite. Aber ich hab dann eine mögliche Lösung herausgefunden, die allerdings wohl nicht optimal ist.

  • Hallo Holger,
    Genau so habe ich bisher auch gerechnet, keine Ahnung warum ich immer ein abweichendes Ergebnis bekommen hatte. Nun habe ich einfach die von dir aufgezeigten Schritte nachvollzogen und es geht. Vielen Dank, du hast mir sehr geholfen.


    72 de Wolf, DL2WRJ
    PS: Nachträglich noch Herzlichen Glückwunsch zu bestandenen Lizenz.

  • Nochwas: hier eine Berechnung mit 64-Bit Arithmetik, also ohne Real. Keine Ahnung, ob Dein PIC/AVR-Compiler sowas kann:


    Code
    int main(void)
    {
        	long long f_in = 75000000; 
        	long long div = 0x2228888;
        	long long out = div * f_in;
        	out = out >> 28;
        	printf("sizeof(out)=%d, out %lld\n", sizeof(out), out);
        	return 0;
    }


    Das sizeof(out) = 8 ist, zeigt mir, daß hier mit 64 Bit gerechnet wird. Dadurch kann kein Überlauf bei "div * f_in" stattfinden.


    Ausgabe:


    Code
    sizeof(out)=8, out 10007324
  • 75Mhz Quarz Freq: 10 Mhz = LSB 6222 MSB 4888 = (ohne ctrl-Bits) 222 8888 (alles Hex)
    Nun die Frage wie errechne ich aus dem Wert 222 8888 wieder die 10MHz?

    Ich habe etwas übersehen, der Teiler lautet 2222 0888 (hex) und damit kommt mein falsches Ergebnis raus. Wenn man LSB und MSB dann dreht wie es sein muß wäre das Teilerwort 8882222.
    Nun bin ich wieder am Anfang.


    72 de Wolf, DL2WRJ

  • Ich antworte mir mal selbst, ich habe die Lösung gefunden. Ich muß natürlich das MSB noch richtig schieben, es werden ja vom LSB nur 14bit benutzt also müßen die fehlenden Bits aus dem MSB ins LSB geschoben werden. Und voila schon gehts


    72 de Wolf, DL2WRJ

  • Tscha, ich nehme mal an, das bei 2222 0888 wir 12 bits von "unten" haben und 16 Bits "von oben". Macht 28 Bits. Das kann man dann so zusammenpfriemeln:



    Wenn Du gaaaanz sicher bist, daß in "div2" nur jeweils 12 Bits gesetzt sind, kannst Du Dir das "& 0xfff" auch sparen.


    Ausgabe nun:


    Code
    div hex: 0x2222888, div dec 35793032, out 10000457
  • Hallo Holger,


    Hier der hoffentlich korrekte Code


    Code
    div hex: 0x2222222, div dec 35791394, out 9999999 ganz nah an den 10MHz


    Nochmals Vielen Dank fürs "Auf die Sprünge helfen"


    72 de Wolf, DL2WRJ