Hallo zusammen, ich habe mal meinen Code zur Ansteuerung eines AD9833 angehängt. Er verwendet bewusst nicht SPI sondern kann an einen belibigen Port angeschlossen werden. Lg Christian / DF1CWQ
Hallo, Vielen Dank für den tollen Code! Ich hab den DDS-Chip sofort zum Laufen bekommen. Nun möchte ich jedoch auch ein Rampen- und Rechtecksignal erzeugen. Leider finde ich nicht heraus, wo sich die Steuerbits im Code befinden. Könntest du mir bitte sagen, wie ich das D1 (Mode) und das D5 (OPBITEN) Bit umschalte. Schöne Grüße, Florian
leiche Ausgrab Nutz einfach seine void DDS_WriteWord(int16_t wValue) und bastel die in meine Library ein: http://www.fritzler-avr.de/HP/Librarys/AD9833_his.php
Mein Webserver Log sagt mir, dass die Nachfrage recht hoch ist. Daher habe ich die Library erweitert um einen Software SPI. Link: http://www.fritzler-avr.de/HP/Librarys/AD9833_his.php
Vielen Dank für Deine Mühen, vielleicht findest Du noch Zeit, die Berechnung des FTW ohne float zu schaffen. Beitrag "Re: Frage zur C Syntax" Beitrag "Re: Rechnen mit AVR" Außerdem ist es ein leichtes, die Restriktion aufzuheben, dass die SPI-Pins auf einem Port liegen müssen: MOSIport, SSport und SCKport definieren. Schieben für SPI (mask ist zugleich Bitzähler): mask=0x80;do if(data&mask)setData;else rstData;while((mask/=2)); hier könnte auch ein else stehen: if (reg == FREQ0){tosend |= (1<<14);} if (reg == FREQ1){tosend |= (1<<15);} und das AND braucht man bei unsigned nicht, schieben allein reicht: tosend = (regist & ~16383)>>14;
>Schieben für SPI (mask ist zugleich Bitzähler): >mask=0x80;do if(data&mask)setData;else rstData;while((mask/=2)); Kannste das mal in C highlighten? Mir verknoten grade die Augen. Wollts erst mit uint32_t machen, aber der AVR GCC mag wohl das Multiplizieren von 2 32bit Variablen nicht. Jedenfals kam nur Mumpitz bei raus. Natürlich ist die Restriktion aufzuheben, wird nur nicht oft vorkomen, dass der AD9833 an 2 - 3 Ports hängt. Hm ja das und ist da sinnfrei, schieb die nicht ausgewählten bits ja eh raus. Danke für die Kritik, wenn du mir die Knoten aus den Augen nimmst, wird das umgesetzt.
dem PI2 würde ich ein paar Stellen mehr genehmigen: #define pi2 6,2831853 > Wollts erst mit uint32_t machen, aber der AVR GCC mag wohl > das Multiplizieren von 2 32bit Variablen nicht. > Jedenfals kam nur Mumpitz bei raus. Kann sein, dass man die 64-bit erst aktivieren muss. Suche mal danach, ich weiß es nicht auswendig. Damals habe ich es in Asm gelöst. Aber Du kannst zumindest die Division wegsparen, da konst/MCLK konstant ist und zur Compiletime berechnet werden kann. Also: #define konst1 ((double)konst/(double)MCLK) void DDS_freq(uint32_t freq, uint8_t reg){ uint32_t regist = freq * konst1; Da stellt sich die Frage, ob man freq nicht mit einem Bruchteil eines Hz angeben will, z.B. 1/8 Hz, d.b. konst1 muss dann noch mit 8 multipliziert werden. void DDS_write(uint16_t data){ SPIPORT &= ~(1<<SS); DDS_writebyte((uint8_t)(data>>8)); DDS_writebyte((uint8_t)(data & 255)); SPIPORT |= (1<<SS); } wird zu #define SPIssPORT PORTB #define SPImoPORT PORTB #define SPIscPORT PORTB void DDS_write(uint16_t data){ uint16_t mask = 0x8000; //Maske und Bytezähler in einem SPIssPORT &= ~(1<<SS); //SSEL low do{ if(data&mask)SPImoPORT |= (1<<MOSI); //SDATA high else SPImoPORT &= ~(1<<MOSI); //SDATA low SPIscPORT &= ~(1<<SCK); //CLK low SPIscPORT |= (1<<SCK); //CLK high }while((mask/=2)!=0); SPIssPORT |= (1<<SS); //SSEL high } (data&mask) ist eine Kurzform für ((data&mask)!=0) und writebyte entfällt ganz. und noch was wichtiges: void DDS_phase(uint16_t phase, uint8_t reg){ uint16_t regist = (uint16_t) (phase*konst2)/pi2; tosend |= (1<<15) | (1<<14); if (reg == PHASE1){tosend |= (1<<13);} DDS_write(tosend | regist); } Das kann falsch sein, wenn vorher in der globalen Variable tosend etwas drinsteht! also entweder tosend = (1<<15) | (1<<14); (ohne |= ) oder kürzer tosend = (uint16_t) (phase*konst2)/pi2; tosend |= (1<<15) | (1<<14); if (reg == PHASE1){tosend |= (1<<13);} DDS_write(tosend);
Sicher, dass ers dann schon zusammenfasst? Der Vorcompiler setzt doch nur den Text ein.
> Der Vorcompiler setzt doch nur den Text ein.
Richtig.
Und der Compiler berechnet den Quotienten, da beide Operanden bekannt
und konstant sind. Das #define ändert an der Berechnung nichts, Du
könntest genauso gut direkt hinschreiben und richtig klammern.
Oder eine echte Konstante deklarieren.
Das Zusammenfassen gilt übrigens auch beim Berechnen der Phasen:
tosend = (uint16_t) (phase*konst2)/pi2;
besser:
tosend = (uint16_t) phase*(konst2/pi2);
Bitte sei so gut und verbessere den Code auf Deiner Seite, damit
zumindest der Fehler bei der Berechnung der Phase berichtigt ist, bevor
sich der Code zu stark verbreitet.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.