www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AD9833 mit Hardware-Spi ansteuern 8051


Autor: M. D. (derdiek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo..

Ich habe vor, einen AD9833 DDS Baustein mit einem AT89C5131A-UM 
anzusteuern.
Nur leider kommt aus dem AD9833 nichts brauchbares heraus.

Hat jemand vielleicht nen Beispielcode wie man die Daten in den AD9833 
schicken muss?

Ich habs jetzt so gemacht:
void SetzeFrequenz(long int Steuerwort)
{
   long int steuerwort;
   SPCON = 0x92; //Initialisierung SPI, SPIEn = 0, Baudrate Flc/128; Master=1;
   SPCON |= 0x40; //SPIEn=1

   //Reset durchführen nach einschalten
   fsync = 0;
   Warte10Us(100);
   steuerwort = 0x0100; //0000 0001 0000 0000
   SendeDatenSPI(steuerwort); //Sende 16Bit Steuerwort
   fsync = 1;
   Warte10Us(10);
   
      //Controlword: Register einstellen, 28 Bit Modus (14 Bit Low und 14 Bit High senden) Reset aktiv
   fsync = 0;
   Warte10Us(100);
   steuerwort = 0x2100;  //0010 0001 0000 0000
   SendeDatenSPI(steuerwort); //Sende 16Bit Steuerwort
   fsync = 1;
   Warte10Us(10); 
   
      //Sende LSB zu Freq 0 Register
   fsync = 0;
   Warte10Us(100);
   steuerwort = (codewort & 0x00003FFF); //LSB maskieren
   steuerwort |= 0x4000;  //Steuerregister maskieren -> FREQ0 Register schreiben 
   SendeDatenSPI(steuerwort); //Sende untere 14 Bit des Codeworts + Steuerbit
   fsync = 1;
   Warte10Us(10);

      //Sende MSB zu Freq0 Register
   fsync = 0;
   Warte10Us(100);
   codewort >>=14; 
   steuerwort = (codewort & 0x00003FFF); //MSB maskieren
   steuerwort |= 0x4000; // Steuerregister maskieren -> FREQ0 Register schreiben 
   SendeDatenSPI(steuerwort); //Sende obere 14 Bit des Codeworts + Steuerbit
   fsync = 1;
   Warte10Us(10); 

      //Phase Register
   fsync = 0;
   Warte10Us(100); 
   steuerwort = 0xC000; //1100 0000 0000 0000 
   SendeDatenSPI(steuerwort); //Sende obere 14 Bit des Codeworts + Steuerbit
   fsync = 1;
   Warte10Us(10); 

      //Reset = 0
   fsync = 0;
   Warte10Us(100);
   steuerwort = 0x0000; //0000 0000 0000 0000
   SendeDatenSPI(steuerwort); //Sende 16Bit Steuerwort
   fsync = 1;
   Warte10Us(10);
}

void SendeDatenSPI(long int spi_wort) //Sende Daten per Hardware-SPI-Schnittstelle
{
    //Variablen
  int spi_wort_high, spi_wort_low, spsta_temp; 
  //Zuweisungen
  spi_wort_high = spi_wort >> 8; //SPI-Wort 8 Bits nach rechts schieben HByte -> LByte
  spi_wort_high &= 0x00FF; //Datenwort maskieren mit 0000 0000 1111 1111
  spi_wort_low = (spi_wort & 0x00FF);  //Datenwort maskieren mit 0000 0000 1111 1111


  //Senden
  
     //Sende High-Byte in SPDAT-Register  
     SPDAT=spi_wort_high; 
     do 
     {
        spsta_temp = (SPSTA & 0x80); //Maskiere SPSTA-Register auf Bit 7(SPIF)
     }while (spsta_temp != 0x80); //Frage SPSTA-Register auf SPFI Flag ab
     Warte10Us(200);
     
     //Sende Low-Byte in SPDAT-Register
     SPDAT=spi_wort_low;
     do 
     {
        spsta_temp = (SPSTA & 0x80); //Maskiere SPSTA-Register auf Bit 7(SPIF)
     }while (spsta_temp != 0x80); //Frage SPSTA-Register auf SPFI Flag ab 
}

Es kommt jedoch nur ein unbrauchbares Signal aus dem Vout heraus..
Hab ich was falsch programmiert oder kann das an der Hardware liegen?

MfG

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du den richtigen SPI-Mode: ist CPOL und CHPA korrekt eingestellt?
Wer steuert den SlaveSelect an?

Autor: M. D. (derdiek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habs sonst nichts weiter eingestellt.
CPOL und CHPA ist alles auf Standartwerten.

Werd ich mir mal anschauen ob das kompatibel ist.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. D. schrieb:
> CPOL und CHPA ist alles auf Standartwerten.
> Werd ich mir mal anschauen ob das kompatibel ist.
Du mußt aus den 4 SPI-Modi den richtigen ermitteln und im uC einstellen
http://www.lothar-miller.de/s9y/categories/17-SPI

Und dann noch kontrollieren, ob der SS (=FSYNC) schon vom uC angesteuert 
wird, oder ob du das selber machen mußt (das ist üblich)...

Autor: M. D. (derdiek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok danke,
also hab mir das mal angeschaut, aber im Datenblatt des AD9833 finde ich 
nur ein Timing-Diagramm, aus dem werde ich aber nicht richtig schlau, 
bzw ich weiß nicht wie ich das auf den SPI-Modus umsetzen muss.

Fsync habe ich auf den Ausgang P1.0 vom Controller gelegt.

Autor: SPI (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja Das Timing Diagramm hilft dir da schonmal. Du schaust einfach wann 
die Daten in deinem Controller übernommen werden, steigende oder 
fallende Flanke.
Danach suchst du bei deinem Controller im Datenblatt welcher Modus für 
steigende und welcher für fallende Flanke ist und stellst diesen dann 
ein.
Damit kannst du diesen Fehlerfall mal ausschließen.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
M. D. schrieb:
> aus dem werde ich aber nicht richtig schlau,
> bzw ich weiß nicht wie ich das auf den SPI-Modus umsetzen muss.
Dann mach Pattern-Matching. Sieh dir die Beziehungen der 3 Signale im 
Datenblatt vom uC an und sieh dir die Beziehungen der Signale im DB vom 
Signalgenerator an. Und dann stellst du CPOL und CPHA im uC so ein, dass 
die beiden zusammenpassen...

Oder du nimmst das Timing-Diagramm und liest daraus ab:
Wenn FSYNC aktiv wird (fallende Flanke) muß SCLK high sein --> CPOL = 1
Daten werden bei der fallenden Flanke von SCLK übernommen  --> CPHA = 0
Daraus folgt: SPI Mode 2

Und: die Defaulteinstellungen des uC (CPOL=CPHA=0) passen da nicht.

> Fsync habe ich auf den Ausgang P1.0 vom Controller gelegt.
Dann mußt du den in deiner Senderoutine natürlich auch noch ansteuern...

Autor: M. D. (derdiek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super, vielen Dank für die Hilfe.
Werd die Register jetzt mal entsprechend einstellen und dann probieren.

Reicht es nicht wenn ich die Fsync-Leitung schon vor der Senderoutine 
auf 0 setze?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. D. schrieb:
> Reicht es nicht wenn ich die Fsync-Leitung schon vor der Senderoutine
> auf 0 setze?
Doch passt. Das hatte ich übersehen... ;-)

Autor: M. D. (derdiek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So hab das ganze jetzt eingestellt..
SPCON = 0x9A;

Funktioniert leider trotzdem noch nicht.
Er gibt zwar eine Sinuskurve am Ausgang aus, aber die ist immer gleich, 
egal wie das Datenwort aussieht.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde aber die Ansteuerung von FSYNC auch mit in die Senderoutine 
packen, denn dort gehört sie ja dazu...
   :
   :
   SendeDatenSPI(0x0000); // Reset
}

void SendeDatenSPI(long int spi_wort) //Sende Daten per Hardware-SPI-Schnittstelle
{
    //Variablen
  int spi_wort_high, spi_wort_low; 
  //Zuweisungen
  spi_wort_high = spi_wort >> 8; //SPI-Wort 8 Bits nach rechts schieben HByte -> LByte
  spi_wort_high &= 0x00FF; //Datenwort maskieren mit 0000 0000 1111 1111
  spi_wort_low = (spi_wort & 0x00FF);  //Datenwort maskieren mit 0000 0000 1111 1111

     //Senden
     fsync = 0;

     //Sende High-Byte in SPDAT-Register  
     SPDAT = spi_wort_high; 
     while (!(SPSTA & 0x80)); 
     
     //Sende Low-Byte in SPDAT-Register
     SPDAT = spi_wort_low;
     while (!(SPSTA & 0x80)); 

     fsync = 1;
}

BTW:
    steuerwort = (codewort & 0x00003FFF); //MSB maskieren
Woher kommt das codewort ?

Autor: M. D. (derdiek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok auch geändert, danke für den Tipp mit der While-Schleife ;)

Das Codewort wird in einer anderen Funktion errechnet.
Das ist der Wert, den man per Formel heraus bekommt.

Das Codewort lasse ich mir auch immer mit ausgeben, und das passt 
soweit.
Ist ja Faktor 10,7 in etwa zur eingegebenen Frequenz.

8 Hz -> 85 Codewort

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier wird der Baustein mit nur 3 SPI-Worten initialisiert:
Beitrag "Beispielprogramm AD9833 (DDS) mit atmega8"
Warum brauchst du so viel mehr?

>>>  M. D. schrieb:
>>>> Nur leider kommt aus dem AD9833 nichts brauchbares heraus.
M. D. schrieb:
> Funktioniert leider trotzdem noch nicht.
> Er gibt zwar eine Sinuskurve am Ausgang aus,
Ist das jetzt schon eine Verbesserung? Oder hat sich nichts geändert?

Autor: M. D. (derdiek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann gut sein das 3 Datenwörter reichen, das ist im Datenblatt für mich 
schwer zu erkennen.

Einmal wird beispielhaft mit 3 Datenwörtern geschrieben, und darunter 
steht im Flussdiagramm dann, das man erst resetten soll, und den Reset 
so lange aktiv halten muss bis die Frequenzwörter übertragen wurden.
Also wären es dann schonmal 6 Wörter:

Reset an (0x0100)
Register (0x4100)
Datenwort LSB (0x4xxx + Datenwort)
Datenwort MSB (0x4xxx + Datenwort)
Phase (0xC000)
Reset aus (0)

Aber ich bin mir nicht wirklich sicher dass das richtig ist.

Lasse ich den Reset weg, funktioniert der AD überhaupt nicht mehr.
Was ich jetzt probiert habe, ist ein Datenwort (10Khz) direkt in das 
Register zu schreiben.
10Khz = 0x29F1 + Register (0x4000)
Also:
Reset an (0x0100)
Register (0x4100)
Datenwort LSB (0x69F1)
Datenwort MSB (0x4000)
Phase (0xC000)
Reset aus (0)

Aber alles was aus dem AD kommt, ist ein Sinus mit ca. 85 Hz.
Und das ist auch so, wenn ich ein anderes Frequenzwort nehme.

Denke mal mit der Reset-Routine funktioniert noch irgendwas nicht 
richtig.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. D. schrieb:
> Lasse ich den Reset weg, funktioniert der AD überhaupt nicht mehr.
> :
> Aber alles was aus dem AD kommt, ist ein Sinus mit ca. 85 Hz.
D.h. er reagiert schon mal auf deine Kommunikation...

Autor: M. D. (derdiek)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, er reagiert mit den 85 Hz.

Auch erst dann, wenn ich was sende.

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.