Forum: HF, Funk und Felder AD9951 reagiert nicht


von Makob (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

Ich sitzte jetzt schon mehrere Tage daran einen AD9951 DDS-Chip zum 
laufen zu bekommen und bin am Verzweifeln.

Mein Ziel ist recht einfach: Die gewünschte Frequenz am IOUT Pin des DDS 
Chips zu erzeugen.
Um das zu erreichen mache ich folgendes:

Zum programmieren des DDS-Chips benutze ich einen USART-Port an einem 
XMega, den ich im SPI Master Mode betriebe. Sprich der DDS-Chip wird 
über SDIO und SCLK angesprochen.
Mit folgenden Schritten beschriebe ich den DDS:

1. Adresse auf SDIO schreiben (z.B. CFR2: 0x01)
2. Alle bytes (je nach länge des Registers) schreiben (e.g. CFR2: 
<23:16><15:8>,<7:0>)
3. Schritt 1 & 2 wiederholen um jedes Register zu beschrieben
4. Anschließend warte ich 200 us um sicher zu gehen, dass die 
Übertragung abgeschlossen ist.
5. Danach schreibe ich ein High auf meine IO Update Leitung. Die Länge 
des High entsrpicht etwa 6 steigenden Flanken der SYNC_CLK.

Den REFCLK vom DDS fütter ich mit einem 20 MHz MEMS Oszillator. Wie im 
Datenblatt beschrieben kann ich am SYNC_CLK Pin vom DDS 1/4 von REFCLK 
messen. Also 5 MHz. Für mich ist das ein Zeichen, dass der DDS mit dem 
REFCLK Eingang einverstanden ist und generell funktioniert.

Jedoch reagiert er auf keinen meiner Programmierversuche.

Egal ob ich über FTW und PLL eine Frequenz am IOUT erzeugen möchte, oder 
den SYNC_CLK PIN über CFR1<1> = 1 ausschalte.

Ich messe immer nur 5 MHz am SYNC_CLK und ein leises Rauschen am IOUT.

Mein SCLK und SDIO sehen auch vernünftig aus (Falls auf der steigenden 
Flanke gelesen wird).

Ist meine Programmierlogik falsch? Oder habe ich generell den 
Aufbau/Funktion des DDS falsch verstanden?

Ich hoffe mir kann jemand weiterhelfen. Im Anhang ist noch die 
Beschaltung des DDS und die DDS_Init.

Vielen Dank

von nachtmix (Gast)


Lesenswert?

Makob schrieb:
> Mein Ziel ist recht einfach: Die gewünschte Frequenz am IOUT Pin des DDS
> Chips zu erzeugen.

Wo ist dein Schaltpan?
Beachte: Der Pin heisst I_out und nicht etwa U_out.

von Arduinoquäler (Gast)


Lesenswert?

Makob schrieb:
> Ich hoffe mir kann jemand weiterhelfen.

Deine Angaben sind zu unvollständig.

Wir brauchen:

- Einen Schaltplan
- Die vollständige Initialisierung
  a) vom DDS
  b) des SPI

... und wie MachtNix schon geschrieben hat, haben DDSe
meist einen Stromquellen-Ausgang den man mit externer
Beschaltung erst zu einer nutzbaren Signalquelle
"verwandeln" darf, muss.

von Makob (Gast)


Lesenswert?

Ich habe im Moment noch keinen Eagle Schaltplan erstellt. Bin ja noch 
dabei den DDS zum laufen zu bekommen. Aber im oben angehängten PDF 
circuit steht wie ich welchen PIN auf meinem Testboard beschalten habe.
Wenn er funktioniert, wird natürlich ein Eagle Schaltplan erstellt. Kann 
ich dann auch gerne posten.

nachtmix schrieb:
> Beachte: Der Pin heisst I_out und nicht etwa U_out.

Ich habe doch IOUT geschrieben oder?

von Makob (Gast)


Angehängte Dateien:

Lesenswert?

Also ich habe mal auf die schnelle einen Schaltplan erstellt. Außerdem 
sind noch meine Inits im Anhang.

von nachtmix (Gast)


Lesenswert?

Makob schrieb:
> nachtmix schrieb:
>> Beachte: Der Pin heisst I_out und nicht etwa U_out.
>
> Ich habe doch IOUT geschrieben oder?

Aber ob du ihn so beschaltet hat, wissen wir nicht.
Eagle um den Plan anzusehen habe ich momentan hier nicht zur Verfügung.

Aus dem Pin kommt jedenfalls ein Strom I heraus, und deshalb musst du 
ihn mit einem Widerstand -irgend etwas zwischen 50 und 200 Ohm- 
belasten, bevor du auf dem Oszi eine Wechselspannung U zu sehen 
bekommst.

von Makob (Gast)


Lesenswert?

nachtmix schrieb:
> Aus dem Pin kommt jedenfalls ein Strom I heraus, und deshalb musst du
> ihn mit einem Widerstand -irgend etwas zwischen 50 und 200 Ohm-
> belasten, bevor du auf dem Oszi eine Wechselspannung U zu sehen
> bekommst.

Ja das habe ich gemacht. Mit einem 50 Ohm Widerstand gegen 1V8.

von Arduinoquäler (Gast)


Lesenswert?

Makob schrieb:
> Also ich habe mal auf die schnelle einen Schaltplan erstellt.

Sollen wir alle die dir helfen wollen erst mal Eagle installieren?

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Makob schrieb:
> Ich habe im Moment noch keinen Eagle Schaltplan erstellt.

Aha...

> Ich habe doch IOUT geschrieben oder?

Ja, genau das hast Du getan. Wie genau ist denn dieser Pin beschaltet? 
Anhand des Schaltplans könnte man dies sofort erkennen.

von Arduinoquäler (Gast)


Lesenswert?

Makob schrieb:
> Jedoch reagiert er auf keinen meiner Programmierversuche.

Ich habe das Datenblatt kurz überflogen: jegliche Kommunikation
erfordert das Aktivieren und Dekativieren des Chip Selects,
was ich als Steuerelement in deinen Sourcen vermisse.

Beitrag #5007339 wurde von einem Moderator gelöscht.
von Arduinoquäler (Gast)


Lesenswert?

Alte Leier schrieb im Beitrag #5007339:
> Ich bin schon fertig damit.

So blöd müsste ich mal sein: für jeden Sch.... schnell mal
extra den eigenen Rechner zumüllen, hätt' ja sonst nichts
zu tun weil mir langweilig ist.

Beitrag #5007348 wurde von einem Moderator gelöscht.
von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Ich habe auch eine ganze Weile gebraucht, bis der AD9952 lief. Wenn man 
etwas falsch macht, gibt es keinerlei Reaktion, die mit dem Oszilloskop 
zu sehen wäre. Schließlich habe ich einen Pin gefunden, den man 
umschalten kann, damit hatte ich ein erstes Lebenszeichen.

Ein Fehler im Datenblatt ist, dass die Reihenfolge der Bytes in der 
Tabelle falsch herum ist, man muss MSBit und MSByte first schieben. In 
der Tabelle ist das LSByte zuerst gelistet. Beim 9954 war es soweit ich 
noch weiß richtig herum.

Beitrag #5007355 wurde von einem Moderator gelöscht.
von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Ich meine, es war crystal-out, den kann man ein oder ausschalten.
Und alle Register stehen in der Tabelle zuerst für [7:0] usw. müssen 
aber umgekehrt kommen, z.B. [31:24] zuerst.

von Arduinoquäler (Gast)


Lesenswert?

Fehler im Schaltplan:

- CS statisch auf Masse

- an jeden AVdd und DVdd Pin fehlt ein Abblock Kondensator
(die Präsenz der Cs ist bei DDSen extrem wichtig)

- Refclk ist vermutlich übersteuert (maximal 3 dBm sind erlaubt)
Ich kenne die Spec des Oszillators aber nicht ...

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

/CS auf GND ist kein Fehler, solange der SPI nur ein Bauteil bedient. 
IO-Update ist wichtig, aber ein Impuls ganz am Ende aller seriellen 
Registerübertragungen reicht aus.

von (º°)·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.·´¯`·.¸¸.· (Gast)


Lesenswert?

Bei der Initialisierung der SPI-Pins darauf achten, dass keine
"unerwuenschten" Takte enstehen.
Notfalls die entsprechenden GPIOs statisch "richtig" vorbelegen.
Analogs DDSse reagieren sonst verschnupft und treten in den Streik.

von Arduinoquäler (Gast)


Lesenswert?

Christoph K. schrieb:
> /CS auf GND ist kein Fehler, solange der SPI nur ein Bauteil bedient.

Das mag sein.

Christoph K. schrieb:
> IO-Update ist wichtig, aber ein Impuls ganz am Ende aller seriellen
> Registerübertragungen reicht aus.

Das reicht nicht aus, denn das serielle Input Register ist
sicherlich nicht 10000 Byte lang sondern warscheinlich nur 32 Bit.
Daher muss jeder Schreibvorgang auf ein einzelnes Register mit
einem IO Update abgeschlossen werden, und nicht ein Impuls für alle.

Beitrag #5007433 wurde von einem Moderator gelöscht.
von Purzel H. (hacky)


Lesenswert?

Analog Devices hat teilweise nicht-standard SPI Interfaces. Dies 
erfordert, jedes Signal, jede Flanke nachzumessen und mit dem Datenblatt 
zu vergleichen. Am Sinnvollsten macht man zu Beginn daher den SPI von 
Hand per Bitbang. Speziell.. wenn Analog Devices den CS verwendet um die 
Instruktion einzuleiten, sollte man es nicht besser wissen wollen, und 
es auch so machen. Exakt wie im Datenblatt.

: Bearbeitet durch User
von Makob (Gast)


Angehängte Dateien:

Lesenswert?

Arduinoquäler schrieb:
> Das reicht nicht aus, denn das serielle Input Register ist
> sicherlich nicht 10000 Byte lang sondern warscheinlich nur 32 Bit.
> Daher muss jeder Schreibvorgang auf ein einzelnes Register mit
> einem IO Update abgeschlossen werden, und nicht ein Impuls für alle.


Doch Christoph K. hat schon Recht. Ein IO-Update genügt nachdem alle 
Register beschrieben sind. Der Buffer ist groß genug um die Datenworte 
aller Register "zwischenzuspeichern". Das sind maximal 22 byte.

Christoph K. schrieb:
> Ein Fehler im Datenblatt ist, dass die Reihenfolge der Bytes in der
> Tabelle falsch herum ist, man muss MSBit und MSByte first schieben. In
> der Tabelle ist das LSByte zuerst gelistet.

Das man MSbyte zuerst schreiben muss habe ich inzwischen auch 
festgestellt. Das ist echt verwirrend dargestellt im Datenblatt. Aber 
selbst wenn es beim AD9951 anders wäre, kann ich das als Fehler 
ausschließen, weil ich schon beides versucht habe.

Arduinoquäler schrieb:
> Fehler im Schaltplan:
>
> - CS statisch auf Masse

Beim ChipSelect Pin bin ich mir tatsächlich nicht ganz sicher ob ich ihn 
fest auf GND ziehen darf. Aber da ich eh nur einen Slave am SPI habe ist 
alles andere in meinen Augen unlogisch.

Christoph K. schrieb:
> Ich meine, es war crystal-out, den kann man ein oder ausschalten.

Man kann den SYNC_CLK ein oder ausschalten, indem man CFR1<1> = 1 setzt. 
Habe ich zu testzwecken auch schon probiert. -> erfolglos

Mein SCLK und SDIO passen auch wunderbar zueinander.

Arduinoquäler schrieb:
> - Refclk ist vermutlich übersteuert (maximal 3 dBm sind erlaubt)
> Ich kenne die Spec des Oszillators aber nicht ...

Dem könnte ich nochmal auf die Spur gehen.
Allerdings spricht dagegen, dass ich am SYNC_CLK 1/4 von der REFCLK sehe 
(so soll es sein). Wenn ich am SYNC_CLK 5 MHz messen kann, ist das doch 
ein Indiz dafür, dass der Chip an sich noch funktioniert oder?

von Frank F. (frank_f49)


Lesenswert?

CS immer auf Ground:  woher soll die SPI Schnittstelle feststellen wann 
das Paket vollständig übertragen ist?

CS sollte HIGH sein bevor das Paket beginnt,  und am Ende  wieder
auf HIGH gezogen werden.

von Makob (Gast)


Lesenswert?

Ist das eine Vermutung oder bist du dir sicher Frank?

Denn der DDS besteht aus 5 Registern. Jedes dieser Register hat eine 
definierte Länge, z.b. 3 Bytes. Nachdem man die Adresse des Registers 
geschrieben hat, füllt der DDS dieses Register mit den nächsten 3 Bytes. 
Jedes weitere Byte wird ignoriert, solang es keine neue Adresse ist. 
Daher weiß der DDS schon wann die Datenübertragung abgeschlossen ist.

Also wenn du dir sicher bist, ist es sicher einen Versuch Wert nochmal 
einen neuen Chip aufzulöten und mir den CS-Pin auf den Mikrocontroller 
zu legen. Aber für eine waage Vermutung ist mir der Aufwand zu schade.

von Martin O. (ossi-2)


Lesenswert?

Im Datenblatt Seite 22 steht der Satz:

"Chip select can be tied low in systems that maintain control of SCLK."

Vermutlich muss man am Anfang den Baustein per RESET in einen def. 
Zustand bringen, von dem aus der Baustein die Clocks zählt.

von Arduinoquäler (Gast)


Lesenswert?

Makob schrieb:
> Nachdem man die Adresse des Registers
> geschrieben hat, füllt der DDS dieses Register mit den nächsten 3 Bytes.
> Jedes weitere Byte wird ignoriert, solang es keine neue Adresse ist.
> Daher weiß der DDS schon wann die Datenübertragung abgeschlossen ist.

Nein.

Die Adresse kennt der DDS erst dann wenn der IO Update Strobe gekommen
ist. Dann erst wertet der DDS intern die Adressbits des Addressbytes
aus, ordnet sie die Daten dem (internen) richtigen Register zu und
macht eine Kopie des Datensatzes aus dem seriellen Input Register
(welches immer noch nur 32 Bit lang ist, behaupte ich).

Insofern ist es bei dieser Implementierung tatsächlich nicht
erforderlich (bei einem einzelnen Slave) den CS zu bedienen.

Würde ein IO Update Strobe für alle Daten/Register genügen müsste der
DDS hellseherische Fähigkeiten haben welche Adresse jetzt denn gerade
daherkommt, und man müsste immer alle Register auf einmal
beschreiben. Diesen Wahnsinn der Implementierung halte ich für
undenkbar.

von Arduinoquäler (Gast)


Lesenswert?

Makob schrieb:
> Wenn ich am SYNC_CLK 5 MHz messen kann, ist das doch
> ein Indiz dafür, dass der Chip an sich noch funktioniert oder?

Ja.

Aber gibst du bei deinen 5 Volt-Schaltungen auch auf Dauer
bedenkenlos 6V Signale auf einen Eingang der nur 5.5V
"verträgt"?

Kannst du sicher sein dass der DDS unter diesen Umständen
immer zuverlässig funktioniert?

von Arduinoquäler (Gast)


Lesenswert?

Frank F. schrieb:
> woher soll die SPI Schnittstelle feststellen wann
> das Paket vollständig übertragen ist?

Also nochmals in anderen Worten:

Es gibt ein serielles Input-Register dem man nach Belieben
Bits hineinshiften kann, egal wieviel. Das was an Bits zuviel
(Länge des Input-Registers) hineingeschoben wird fällt einfach
weg, fällt hinten raus. Wird nach einer beliebigen Anzahl von
Bits der IO Update Strobe betätigt, werden die Bits an der
Position des Adress-Bytes ausgewertet und das entsprechende
(adressierte) interne Register gezielt mit den anliegenden
Daten beschrieben.

Der CS dient hier nur dazu die Daten bzw den Clock zu enablen,
damit nicht alle Slaves (wenn mehr vorhanden) den Datenstrom
bekommen.

von Makob (Gast)


Lesenswert?

Ich habe das Mysterium endlich gelöst.

Zunächst mal kann man tatsächlich alle Register beschreiben bevor man 
das IO Update aktiviert. Habe ich eben erfolgreich gemacht.

Mein Fehler war, dass ich dem Chip vor dem programmieren keinen Reset 
verpasst habe. Dazu steht aber auch nichts im Datenblatt, dass der Chip 
einen Reset vor dem programmieren brauch.

Dazu habe ich jetzt aber eine Frage. Der Reset Pin liegt bei mir auf dem 
USART Pin TX. Die Kommunikation findet ja ausschließlich über den XCK 
Pin (erzeugt SCLK) und den RX Pin (SDIO) statt. Der USART TX Pin auf dem 
mein Reset liegt ist dauerhaft low und wird nicht verwendet im SPI 
Master Mode.

Kann ich mir diesen Pin irgendwie auf High oder Low ziehen?
Mit PORTD.OUT = (1<<Pin3) funktioniert es leider nicht.
Ich benutze einen XMega A3

von B e r n d W. (smiley46)


Lesenswert?

>> Kann ich mir diesen Pin irgendwie auf High oder Low ziehen?

Beim Xmega (und anderen) geht das ungefähr so:
PORTD.OUT |= (1<<Pin3);
PORTD.OUT &= ~(1<<Pin3);

Der Xmega gestattet auch Zugriff auf einzelne Pins. Dies ist schneller, 
weil das Port-Register vorher nicht ausgelesen werden muss:
PORTD.OUTSET = PIN3_bm;
PORTD.OUTCLR = PIN3_bm;

von Martin O. (ossi-2)


Lesenswert?

Kann ich mir diesen Pin irgendwie auf High oder Low ziehen?

Eventuell indem Du ein entsprechendes Byte via TX rausschickst ?

von B e r n d W. (smiley46)


Lesenswert?

The USART Transmitter:
When the transmitter has been enabled, the normal port operation of the 
TxD pin is overridden by the USART and given the function as the 
transmitter's serial output. The direction of the pin must be set as 
output using the direction register for the corresponding port.

Disabling the Transmitter
When the transmitter is disabled, it will no longer override the TxDn 
pin

Also im Register CTRLB das Bit3, TXEN auf Null rücksetzen, dann kann 
dieser Pin normal verwendet werden. Soll wieder gesendet werden, TXEN 
vorher wieder auf 1 setzen.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?

Beitrag "Re: DDS-Chip mit einem AVR ansprechen"
Da hatte ich mein funktionierendes Arduino-Programm ja schon gepostet.
Das Schieberegister im DDS ist tatsächlich so lang, dass alle Register 
reinpassen.

von Makob (Gast)


Lesenswert?

B e r n d W. schrieb:
> CTRLB das Bit3, TXEN auf Null rücksetzen, dann kann
> dieser Pin normal verwendet werden

Funktioniert. Vielen Dank für den Tipp Bernd!

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.