www.mikrocontroller.net

Forum: Projekte & Code AD9833 DDS in c ohne SPI


Autor: Christian (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Florian L.s (jesus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Mw En (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Mw En (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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;

Autor: Mw En (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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);

Autor: mojtaba (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
pleas: SPI COMMUNICATION DRIVER FOR AD9833 DDS WITH FRAME SYNC

Autor: Mw En (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sicher, dass ers dann schon zusammenfasst?
Der Vorcompiler setzt doch nur den Text ein.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Mw En (Firma: fritzler-avr.de) (fritzler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sitz ja schon drann, muss nurnoch das Gerät zum Testen finden...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.