Forum: Mikrocontroller und Digitale Elektronik DDS AD9833 Werte aktualisieren


von Christian Z. (blup)


Lesenswert?

Hallo Zusammen,

ich habe ein Problem bezüglich der Werteübergabe an einen AD9833 DDS-IC.
In einem Menü wird der Wert der gewünschten Ausgangsfrequenz gewählt und 
anschließend soll der Wert in den AD9833 übernommen werden. Bei 
einmaliger Wertübergabe zur Initialisierung (Ist im Programmausschnitt 
nicht enthalten) klappt das super - Phase und Frequenz stimmen.
Rufe ich den unten aufgeführten Programmausschnitt jedoch mehrmals auf 
springt das Signal des AD9833 in unregelmäßigen Abständen auf andere 
Frequenzen bzw. Phasenwinkel, selbst wenn ich anstatt des veränderlichen 
Wertes FREQ_VALUE einen konstanten Wert wähle und diesen immer wieder 
ausgebe, soll heisen obwohl ich den AD9833 mit ein und demselben Wert 
neu lade ändern sich die Parameter am Ausgang.

Der unten angefügte Programmausschnitt beinhaltet nur die Frequenz, mit 
dem Phasenwinkel bin ich nach dem selben Schema verfahren.

Ich habe nun schon 3 Tage daran rumexperimentiert es klappt einfach 
nicht, bin kurz vorm verrückt werden und für jede Hilfe dankbar.

Mfg Christian

Übrigens der CS Eingang kann nach jedem Wort wieder auf High gezogen 
werden, muss aber nicht - hab ich auch schon probiert, daran liegt es 
nicht.


1
rcall SPI_INIT_5MHZ_DDS
2
3
cbi PORTB, CS_DDS1  ;CS auf Low
4
5
;Reset + FREG0 wählen + Befehl nur die unteren 14Bit des FREQ0 Registers ändern die oberen 14Bit sind definiert und werden nicht verändert
6
7
ldi temp_0, 0x01
8
out SPDR, temp_0
9
rcall WAIT_SPI
10
ldi temp_0, 0x00
11
out SPDR, temp_0
12
rcall WAIT_SPI
13
14
;unteres Wort laden z.B. 0x746D für 50Hz darin enthalten ist die
15
;Bitkombi 01 am Anfang um FREG0 anzusprechen
16
17
ldi XL, LOW(FREQ_VALUE_L)
18
ldi XH, HIGH(FREQ_VALUE_L)
19
ld temp_0, X+  ;LOW Byte des Frequenzwortes z.B. 0x6D
20
ld temp_1, X  ;HIGH Byte des Frequenzwortes z.B. 0x74
21
22
;Daten an DDS IC senden
23
          
24
out SPDR, temp_1
25
rcall WAIT_SPI
26
out SPDR, temp_0
27
rcall WAIT_SPI
28
29
;Reset aufheben
30
31
ldi temp_0, 0x00
32
out SPDR, temp_0
33
rcall WAIT_SPI
34
ldi temp_0, 0x00
35
out SPDR, temp_0
36
rcall WAIT_SPI
37
sbi PORTB, CS_DDS1
38
39
40
41
SPI_INIT_5MHZ_DDS:  push temp_0
42
      ldi temp_0, (0<<SPI2X)
43
      out SPSR, temp_0
44
      ldi temp_0, (0<<SPIE)|(1<<SPE)|(0<<DORD)|(1<<MSTR)|(1<<CPOL)|(0<<CPHA)|(0<<SPR1)|(0<<SPR0)
45
      out SPCR, temp_0
46
      pop temp_0
47
ret
48
49
50
WAIT_SPI:  in temp_2, SPSR
51
    bst temp_2,7
52
    brts END_WAIT
53
    jmp WAIT_SPI
54
END_WAIT:  ret

von Joe (Gast)


Lesenswert?

So ganz kann ich nicht erkennen wo du die entsprechende Reihenfolge 
einhälts !?

Die Ansteuerung sollte wie folgt sein:

-1 framesync=1 /frame start
-2 framesync=0 /chip enable
-3 Signalform (8 BIT) hier Rechteck, Dreieck, Sinus
-4 LSW_H 6 BIT
-5 LSW_L 8 BIT // in Summe also 6+8=14 BIT
-6 MSW_H 6 BIT
-7 MSW_L 8 BIT //6+8=14 BIT => 14+14=28 BIT
-8 framesync=1 /frame end

so in etwa sollte der Ablauf aussehen.

von Christian Z. (Gast)


Lesenswert?

Hallo Joe, vielen Dank für deine Antwort aber genau in dieser 
Reihenfolge läuft es eigentlich ab...

1. /CS auf High zum Programmstart (hab ich oben vergessen gehabt)
1
sbi PORTB, CS_DDS1
2. /CS auf Low
1
cbi PORTB, CS_DDS1
3. Die Signalform enthält ja mein 16Bit Befehl bei dem ich auch festlege 
das ich nur 14Bit übertragen möchte und das höherwertige Wort 
unangetastet bleibt
1
ldi temp_0, 0x01
2
out SPDR, temp_0
3
rcall WAIT_SPI
4
ldi temp_0, 0x00
5
out SPDR, temp_0
6
rcall WAIT_SPI
4+5. Die niederwertigen 14Bit übertragen
1
ldi XL, LOW(FREQ_VALUE_L)
2
ldi XH, HIGH(FREQ_VALUE_L)
3
ld temp_0, X+  ;LOW Byte des Frequenzwortes z.B. 0x6D
4
ld temp_1, X  ;HIGH Byte des Frequenzwortes z.B. 0x74
5
6
;Daten an DDS IC senden
7
          
8
out SPDR, temp_1
9
rcall WAIT_SPI
10
out SPDR, temp_0
11
rcall WAIT_SPI

6.Reset aufheben
1
ldi temp_0, 0x00
2
out SPDR, temp_0
3
rcall WAIT_SPI
4
ldi temp_0, 0x00
5
out SPDR, temp_0
6
rcall WAIT_SPI
7
sbi PORTB, CS_DDS1

7./CS auf High
1
sbi PORTB, CS_DDS1

von Joe (Gast)


Lesenswert?

Zu meinem Verständnis Problem ;-)) Ich progamiere die AVR's nur in C, 
ich habe das Ganze vor etwa 2 Jahren in 8x51 Assembler mal gemacht. Ich 
verwende aber keine SPI sondern erzeuge mir das Ansteuersignal auf 
beliebeigen Pins.

Ich kann zwar deinen ASM Code lesen aber das Verhalten der SPI nicht 
beurteilen. Mit anderen Worten ich sehe keinen Fehler.

Kommt den die übermittelte Frequenz und Signalform heraus ?

>> springt das Signal des AD9833 in unregelmäßigen Abständen auf andere
>> Frequenzen bzw. Phasenwinkel

Obwohl du immer das gleiche sendest ? In diesem Fall schreib doch mal ne 
eigene Senderoutine und verwende nicht die SPI.

von Christian Z. (Gast)


Lesenswert?

Das eigenartige ist das ich das Ausgangssignal über einen Audiverstärker 
verstärke der die Verstärkung ebenfalls über den SPI Bus bekommt 
verstärke. Bloß die Initialisierungssequenz ist an den Audioverstärker 
angepasst, wenn ich dort nach dem selben Schema die Daten übermittle 
funktioniert alles tadellos und die SPI Einstellung für den DDS IC sind 
nach dem Datenblatt vorgenommen (alle anderen Varianten habe ich 
ebenfalls ausprobiert) und somit MUSS es doch auch über die Standard SPI 
Schnittstelle funktionieren??? Bin auch noch grün hinter den Ohren was 
Assembler Programmierung angeht, daher schreckt es mich etwas ab das 
über eine Software SPI zu realisieren.
Wie gesagt wenn ich beim Programmstart vordefinierte Werte in den DDS IC 
lade stimmt alles bis ich die Werte ein paarmal überschreibe ob sie sich 
geändert haben oder nicht. In dem Fall ändert sich die Frequenz oder die 
Phasenlage auf total sinnfreie Art und Weise.

von Joe (Gast)


Lesenswert?

Software SPI ist im Prinzip recht einfach. Du übermittelst ja jeweils 8 
Bit mit entsprechenden Takt. Wenn also im Accu irgendein Wert steht und 
du den Inhalt schiebst z.B. rlc a (hoffe du weist was ich meine, das ist 
8x51 Asm code) dann kannst du den Wert im carry einfach an den Datenpin 
legen, dann Taktsignal erzeugen, nächstes BIT raus.

Also, recht einfach.

von Christian Z. (Gast)


Lesenswert?

Ich danke Dir soweit erst einmal und werde es demnächst wohl mal 
ausprobieren, da ich ja wie gesagt auch am Ende bin mit meinem Latein.
Werde dann noch mal posten ob ich erfolgreich war oder nicht.

von Christian Z. (Gast)


Lesenswert?

Das Problem ist erkannt, nachdem ich laut der Application Note 151 von 
Atmel in Reihe zu den SPI Pins je einen 1kOhm Widerstand geschalten habe 
um den Strom zu begrenzen und somit einen Latch up zu verhindern war die 
Flankensteilheit des Signals für die AD´s nicht mehr ausreichend und 
somit ist es zu den Fehlern gekommen.

Freude...

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.