C Atmega8 und AD9850 DDS

flecralf

Mitglied
25. Juli 2013
194
2
18
Sprachen
  1. ANSI C
Moin moin,
mit viel Verspätung erstmal ein frohes neues Jahr ! :)
Seit einer Woche versuche ich ein AD9850 Funktionsgenerator mit einem ATmega8 zum
Arbeiten zu bewegen. Um dem "Ding" den Lebensgeist einzuhauchen, ist nötig ein Frequenztuningbyte zu übermitteln. Im Anhang befindet sich ein Liniendiagramm. Dies kann seriell oder parallel geschehen. Ich versuche mich gerade an der seriellen Variante. Um das Tuningbyte (eigentlich ist ein WORD, oder?) habe ich folgende Gleichung: f_tuning=f_soll*2^32/125*10^6;
f_tuning=der zu schiebende Datenwert
f_soll=Wunschfrequenz
125*10^6=Taktfrequenz
Für die Frequenz sind lediglich die Bits 0 bis 31 entscheidend, der Rest ist für höhere Bestimmungen.
Frage:
f_soll=1kHz....
da komme ich mit meinem Taschenrechner auf: 1000011000110111
Nun habe ich beide Richtungen zum Schieben versucht, ohne Erfolg.
Eine ShiftOut-Funktion habe ich nicht..... gibts wohl nur beim Ardiuno.....


CodeBox C
uint32_t tuning  =  0b 00000000 00000000 10000110 00110111; // die ersten 16 Bits habe ich mit 0 //aufgefüllt, bei höheren Frequenzen stehen da entsprechende Werte

uint32_t temp;
uint32_t i; // Zähler in der For-Next-Schleife
uint16_t test;
while(i>=0)
{
//Dann schiebe ich das Ganze mit
temp = tuning >> i;
//Prüfen ob Bit 1 gesetzt:
test = (temp & 1);
//Dann 1 oder 0 an AD senden:
Den W_Clck sowie die _delay_ms habe ich mal hier weggelassen....
if(test)
{
PORTC |=  (1  << DATA);
}
else
{
PORTC &= ~(1  << DATA);
}
}


Hat jemand Erfahrungen mit den AD-Dingern?
 

Anhänge

  • 123.png
    123.png
    42,1 KB · Aufrufe: 7
Hallo,

ich habe mir zunächst nur mal dein Programmauschnitt angesehen. Hier ist mir aufgefallen, dass du
  • die Zählvariable i nicht initialisierst
  • i innerhalb der while Schleife nicht änderst
  • und die Bedienung für uint32_t (i>=0) eigentlich immer wahr ist.
wenn du ein WORD schieben möchtest, kannst du es zum Beispiel so lösen...




CodeBox C
uint8_t i = 16;
while (i>0)
{

   // Hier das Bit schieben (Datenbit und Clock)

   i--;
}


Dirk :ciao:
 
Hallo,

ich habe mir zunächst nur mal dein Programmauschnitt angesehen. Hier ist mir aufgefallen, dass du
  • die Zählvariable i nicht initialisierst
  • i innerhalb der while Schleife nicht änderst
  • und die Bedienung für uint32_t (i>=0) eigentlich immer wahr ist.
wenn du ein WORD schieben möchtest, kannst du es zum Beispiel so lösen...




CodeBox C
uint8_t i = 16;
while (i>0)
{

   // Hier das Bit schieben (Datenbit und Clock)

   i--;
}


Dirk :ciao:

Hi Dirk,
Danke, stimmt, da fehlte das Dekrementierren i---.
Hab den Code mal im Dos-C mit printf gedebugt, da stimmt es soweit....
Mir macht das Bitmuster und der AD9850 selbst Probleme....
Gruß
Ralf
 
parallel ... seriell... quasi isses beides...

Der AD9850 wird durch übertragen von 40 Bits eingestellt/umgestellt. Diese können entweder über einen 8bit, oder einen 1bit breiten Bus übertragen werden, letztlich bleiben es eben 40 bits. Oder 5 Bytes. Oder 10 Nibbles...
Der AD... kann mit drei Pins entweder auf den 8bit oder den 1bit-Bus beim Startup eingestellt werden, aus dem 8bit-Modus kann auf den 1bit-Modus umgeschaltet werden (Figure10).
Im Prinzip wird (serieller Mode) das LSB first "von Links" in das Schieberegister (Data Input Register) reingeclockt.

Zu C kann ich Dir nicht helfen, aber warum muß es unbedingt Software sein? Sollte man das nicht auch über das HW-SPI jagen können? Irgendeinen Controllerpin legt zu Beginn des Transfers der 5 Bytes FQ_UD auf Gnd, und danach auf Vcc (was dort die eingetakteten Bits latcht - quasi ein /CS). MOSI auf D7(MSB), SCK auf W_CLK.
 
Zu C kann ich Dir nicht helfen, aber warum muß es unbedingt Software sein? Sollte man das nicht auch über das HW-SPI jagen können?

Also HardwareSPI hilft doch hier überhaupt nicht weiter, es bringt soch nur das Konzept durcheinander, bzw. bringt Ralf durcheinander.

Im Moment möchte Ralf die einzelnen Bits via SoftwareSPI schieben, da hat er ein paar grundsätzliche Fehler gemacht (hatte ich drauf hingewiesen), die muss er nur beseitigen.

@flecralf: Falls du nicht weiter kommst, schreib ich kurz die Funktion.

Dirk :ciao:
 
Hmm...
Also ich konnte dem ersten Beitrag nicht entnehmen, daß es unbedingt (!) in Software umgesetzt werden muß. Und da Du Dich bereits der Software-Lösung (und insbesondere deren Umsetzung in C) bereits angenommen hast (und das eh nicht mein Gebiet wäre), habe ich lediglich darauf hinweisen wollen, daß man das eigentlich auch über die vorhandene Hardware-Schnittstelle machen können sollte...
 
Hmm...
Also ich konnte dem ersten Beitrag nicht entnehmen, daß es unbedingt (!) in Software umgesetzt werden muß. Und da Du Dich bereits der Software-Lösung (und insbesondere deren Umsetzung in C) bereits angenommen hast (und das eh nicht mein Gebiet wäre), habe ich lediglich darauf hinweisen wollen, daß man das eigentlich auch über die vorhandene Hardware-Schnittstelle machen können sollte

"Unbedingt" natürlich nicht, aber er hat bereits mit der SoftwareSPI Lösung angefangen. Eigentlich ist es auch recht einfach. Vorteil an SoftwareSPI ist dass, es mit beliebigen freien IO Pins funktioniert, eigentlich auf jedem Mikrocontroller und nicht nur auf AVR.

Ich mach einfach mal ein Beispielprogramm, damit kann Ralf "spielen". Ins Datenblatt reinzuschauen, wie sich der notwendige Frequenzwert errechnet, werde ich aber leider heute nicht mehr dazu kommen.

Dirk :ciao:
 
Hier ein Beispiel, wie man Daten seriell Daten an den AD9850 senden kann. Soweit ich verstanden habe, muss der SerialMode erst enabled werden, das mache ich in der Init Routine. In der Routine SendFrequency übertrage ich die 32Bit für die Frequenz und weitere 8Bit für ControlDaten (diese setze ich hier auf 0).

In der Funktion main() zunächst AD9850_Init() aufrufen und dann bei Bedarf innerhalb while(1) einen Frequenzwert übertragen: AD9850_SendFrequency (uint32_t freq)

Ich sende jeweils 1 Byte, mann kann die Funktion AD9850_SendByte (uint8_t data) also recht einfach durch HardwareSPI ersetzen, wenn man möchte.

Die Pin/Port Definitionen müssen noch angepasst werden.

Der Code ist nicht getestet, da mir die Hardware fehlt.

Dirk :ciao:



CodeBox C

// Die folgenden Definitionen anpassen. Die Ziffern sind Portpin-Nummern.
// Die Signale befinden sich alle auf einem Port.

#define AD9850_PORT     PORTB
#define AD9850_DIR     DDRB
#define AD9850_CLK     0  // CLK
#define AD9850_FQ_UD   1  // Frequency Update
#define AD9850_DATA     2  // Serial Data
#define AD9850_RESET   3   // Reset

void AD9850_Init (void);
void AD9850_SendByte (uint8_t data);
void AD9850_SendFrequency (uint32_t freq);


int main (void)
{
   uint32_t frequency;
 
   // Initialisierungen
   AD9850_Init();
 
   while(1)
   {
   
     // ...
   
   
   
     AD9850_SendFrequency (frequency);
   
   
   
   }
   
}



void AD9850_Init (void)
{
 
   // CLK, FQ_UD, RESET, DATA: Low
   // CLK, FQ_UD, RESET, DATA: Output 
   AD9850_PORT &= ~((1<<AD9850_CLK) | (1<<AD9850_FQ_UD) | (1<<AD9850_RESET) | (1<<AD9850_DATA));
   AD9850_DIR |=  (1<<AD9850_CLK) | (1<<AD9850_FQ_UD) | (1<<AD9850_RESET) | (1<<AD9850_DATA);
   
   // Reset Pulse
   AD9850_PORT |= (1<<AD9850_RESET);
   AD9850_PORT &= ~(1<<AD9850_RESET); 
 
   // CLK Pulse
   AD9850_PORT |= (1<<AD9850_CLK);
   AD9850_PORT &= ~(1<<AD9850_CLK); 
 
   // FQ_UD Pulse
   AD9850_PORT |= (1<<AD9850_FQ_UD);   // Enable serial mode
   AD9850_PORT &= ~(1<<AD9850_FQ_UD); 
 
}

void AD9850_SendFrequency (uint32_t freq)
{
 
   // 32Bit Frequency
   AD9850_SendByte ((uint8_t) freq);
   AD9850_SendByte ((uint8_t) (freq>>8)); 
   AD9850_SendByte ((uint8_t) (freq>>16)); 
   AD9850_SendByte ((uint8_t) (freq>>24)); 
 
   // 8Bit Control, PowerDown, Phase
   AD9850_SendByte (0);   
 
   // FQ_UD Pulse: Update
   AD9850_PORT |= (1<<AD9850_FQ_UD);
   AD9850_PORT &= ~(1<<AD9850_FQ_UD); 
 
}


void AD9850_SendByte (uint8_t data)
{
 
   uint8_t i = 8;
 
   do
   {
   
     if (data & 1)
     {
       AD9850_PORT |= (1<<AD9850_DATA);   // Data high
     } else {
       AD9850_PORT &= ~(1<<AD9850_DATA);   // Data low
     }
   
     // Clock
     AD9850_PORT |= (1<<AD9850_CLK);
     AD9850_PORT &= ~(1<<AD9850_CLK);   
   
     i--;
     data = data>>1;
   
   } while (i>0);
   
}

 
Zuletzt bearbeitet:
So bin wieder online.....
Danke Dirk.... den Code werde ich gleich testen....
Der Befehl AD9850_SendFrequency (frequency); muss doch nur einmal ausgeführt werden, oder?
Innerhalb der while-schleife wird er so, wie in Deinem Programm ständig aktualisiert.
[...]daß man das eigentlich auch über die vorhandene Hardware-Schnittstelle machen können sollte[...]
Aber, was ist die vorhandene Hardware-Schnittstelle? SoftwareSPI ?
Da stehe ich auf dem Schlauch.... bin doch gerade im Analog-Modus. :)
Will mich in kleinen Schritt SDR annähern......
Die Umrechnung ist im Grunde einfach.... heute Abend wird es wohl aber bei mir auch nichts mehr....
Gruß & Danke !!!
Ralf
 
Soweit ich verstanden habe, muss der SerialMode erst enabled werden
Da war ich mir auch nicht sicher, ich wäre allerdings der Meinung, daß man mit den Pins 2, 3 und 4 auch den 1bit-Modus beim Startup erzwingen kann, und dann kein Init mehr braucht.
NOTE: FOR DEVICE START-UP IN SERIAL MODE, HARDWIRE PIN 2 AT 0, PIN 3 AT 1, AND PIN 4 AT 1 (SEE FIGURE 11).
Figure 11 ist im Anhang aus #1 zusehen...

Edit:
Aber, was ist die vorhandene Hardware-Schnittstelle? SoftwareSPI ?
Nein, bei Deinem Versuch (und Dirks Korrekturen) laßt ihr das Programm direkt die Beine zappeln, also jedes Bit, jedes Bein. Das Programm (Software) steuert jede einzelne Aktion direkt.

Dein Mega8 verfügt aber (wie die meisten Megas und einige Tinies) über eine Schieberegister (Hardware), wo man salopp gesagt ein Byte reinstopfen kann, und welches dann von dieser Hardware autonom rausgetaktet (-schoben) wird. Getaktet über eine Clock-Leitung, die Daten über zwei Datenleitungen (bidirektional, wovon hier aber nur eine Richtung genutzt werden würde).
Dieses Hardware-Modul ist (wie Dirk bereits sagte) an bestimmte Beine des AVR gebunden (kann ein Nachteil sein), auf der anderen Seite läuft das Modul weitgehend autonom im Hintergrund, bremst das Programm ggf weniger aus, wird durch etwaige Interrupts nicht unterbrochen (kann ein Vorteil sein).
Hinweise findest Du im Datenblatt des Mega8 unter "Serial Peripheral Interface - SPI". Ansonsten ... Fragen.

P.S.: wollte Dich aber nicht damit verwirren...
 
Zuletzt bearbeitet:
Da war ich mir auch nicht sicher, ich wäre allerdings der Meinung, daß man mit den Pins 2, 3 und 4 auch den 1bit-Modus beim Startup erzwingen kann, und dann kein Init mehr braucht.Figure 11 ist im Anhang aus #1 zusehen...

Hi LotadaC,
zumindest ein Jumper muss dazu umgesteckt werden.
 
Hallo Ralf,
Der Befehl AD9850_SendFrequency (frequency); muss doch nur einmal ausgeführt werden, oder?
Innerhalb der while-schleife wird er so, wie in Deinem Programm ständig aktualisiert.

du rufst die Funktion nicht permanent auf, ich hatte auch geschrieben "bei Bedarf". Wann du da etwas überträgst, hängt natürlich von deiner Anwendung ab.

Dirk :ciao:
 
Hallo Ralf,


du rufst die Funktion nicht permanent auf, ich hatte auch geschrieben "bei Bedarf". Wann du da etwas überträgst, hängt natürlich von deiner Anwendung ab.

Dirk :ciao:

Moin Dirk,
hatte ich übersehen.
Dein Programm, oder genauer ausgedrückt die Kompilierung, läuft ohne jegliche Fehlermeldung.... Respekt ! ;-)
An die Berechnung des Tuningswertes mache ich mich später.
Ich melde mich heute Abend wieder..... bin jetzt mal weg.
Gruß
Ralf
 
Hallo Ralf,

bei der Init Routine habe ich in der ersten Zeile ein "~" vergessen, so ist es richtig ...


CodeBox C
AD9850_PORT &= ~((1<<AD9850_CLK) | (1<<AD9850_FQ_UD) | (1<<AD9850_RESET) | (1<<AD9850_DATA));


Dirk :ciao:
 
Hallo Dirk,
in dem von Dir geschrieben Code werden 4x8Byte also 32 Bit geschoben.
Dann müssen doch noch 8 Bit nachgeschoben werden?
Das Register ist doch 40-Bit breit?!?



CodeBox C
  // 32Bit Frequency
  AD9850_SendByte((uint8_t) freq);
  AD9850_SendByte((uint8_t) (freq>>8)); 
  AD9850_SendByte((uint8_t) (freq>>16)); 
  AD9850_SendByte((uint8_t) (freq>>24)); 
  AD9850_SendByte((uint8_t) (0)); 

Wobei ich immer noch an dieser Stelle festhänge.....
Wenn ich von links nach rechts schiebe dann komme ich auf folgenden Ablauf....
AD9850_SendByte((uint8_t) (0)); // Bit Bit 32 bis 39
AD9850_SendByte((uint8_t) (freq>>24)); // Bit 24 bis 31
AD9850_SendByte((uint8_t) (freq>>16)); // Bit 16 bis 23
AD9850_SendByte((uint8_t) (freq>>8)); // Bit 8 bis 15
AD9850_SendByte((uint8_t) freq); //bit 0 bis 7


Das Tuning Word errechnet sich so:


CodeBox C
  unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK;
//DDS_CLOCK= 125000000


Weiter kam ich noch nicht......
 
Hallo Dirk,
in dem von Dir geschrieben Code werden 4x8Byte also 32 Bit geschoben.
Dann müssen doch noch 8 Bit nachgeschoben werden?
Das Register ist doch 40-Bit breit?!?...
In den Zeilen 66 bis 69 werden die vier Frequenz-bytes (32 Bit) gesendet (bzw an die Senderoutine weitergereicht), in Zeile 72 folgt das Phasen-/Controlbyte (8 bit). Zusammen die 40 Bit.

in den Zeilen 75, 76 dann der Latch.
...
Wobei ich immer noch an dieser Stelle festhänge.....
Wenn ich von links nach rechts schiebe dann komme ich auf folgenden Ablauf....
AD9850_SendByte((uint8_t) (0)); // Bit Bit 32 bis 39
AD9850_SendByte((uint8_t) (freq>>24)); // Bit 24 bis 31
AD9850_SendByte((uint8_t) (freq>>16)); // Bit 16 bis 23
AD9850_SendByte((uint8_t) (freq>>8)); // Bit 8 bis 15
AD9850_SendByte((uint8_t) freq); //bit 0 bis 7...
MSB=Bit39, Bit38, Bit37, ... Bit2, Bit1, Bit0=LSB
Wenn Du von links nach rechts schiebst, fällt das LSB raus (ins Carry, aber das interessiert Dich nicht), links wird 'ne 0 reingeschoben (=neues MSB).
Im AD... kommen die Bits dann von LINKS an, das erste ankommende Bit (eigentlich das LSB) landet also erstmal als MSB. Dann wird das ganze Bit für Bit nach rechts durchgeschoben.
In Zeile 66 werden die untersten 8 Bits des 32Bit-Frequenz-Wortes zum Senden übergeben,
In Zeile 67 Bit15..Bit8 usw usw
 
Hi Ralf,

in dem von Dir geschrieben Code werden 4x8Byte also 32 Bit geschoben.
Dann müssen doch noch 8 Bit nachgeschoben werden?
Das Register ist doch 40-Bit breit?!?

ja, das mache ich doch. Ich sende 4 Byte für die Frequenz + 1 Byte Control = 5 Byte = 40 Bit

In deiner veränderten Form sendest du das höchswertige Byte (Control Byte) zuerst, danach MSB byte der Frequenz. Und da immer LSB von jedem Byte zuerst.

Das geht garnicht!

Deine Version:

AD9850_SendByte((uint8_t) (0)); // Bit Bit 32 bis 39
AD9850_SendByte((uint8_t) (freq>>24)); // Bit 24 bis 31
AD9850_SendByte((uint8_t) (freq>>16)); // Bit 16 bis 23
AD9850_SendByte((uint8_t) (freq>>8)); // Bit 8 bis 15
AD9850_SendByte((uint8_t) freq); //bit 0 bis 7

Soweit ich im Datenblatt gesehen habe, wird mit LSB angefangen. Es werden 40 Bit gesendet. Zuerst 32 Bit (0..31) diese Frequenz, das sind 4 Byte und dann noch ein Byte Control (32..39).

Also erstes Bit ist Bit0 und letztes Bit ist Bit 39.


Das macht meine Version:


CodeBox C
void AD9850_SendFrequency (uint32_t freq)
{
// 32Bit Frequency
AD9850_SendByte ((uint8_t) freq);
AD9850_SendByte ((uint8_t) (freq>>8));
AD9850_SendByte ((uint8_t) (freq>>16));
AD9850_SendByte ((uint8_t) (freq>>24));
// 8Bit Control, PowerDown, Phase
AD9850_SendByte (0);
// FQ_UD Pulse: Update
AD9850_PORT |= (1<<AD9850_FQ_UD);
AD9850_PORT &= ~(1<<AD9850_FQ_UD);
}

AD9850_SendByte sendet dann immer LSB zuerst. Es werden also 40 Bit von LSB nach MSB heraus-"geshiftet". Das letzte Byte ist das Controlbyte ( einschließlich PowerDown Bit + Phase Bits). Das sende ich grundsätzlich erst mal mit 0x00.

Ich sende also ...


CodeBox C
// 32Bit Frequency
AD9850_SendByte((uint8_t) freq);         // 0...7 Freq
AD9850_SendByte((uint8_t) (freq>>8));  // 8..15 Freq
AD9850_SendByte((uint8_t) (freq>>16));  // 16..23 Freq
AD9850_SendByte((uint8_t) (freq>>24));  // 24..31 Freq
AD9850_SendByte((uint8_t) (0));  // 32..39 Control


Warum hast du die Zeilen verdreht? Vielleicht stellst du auch mal mehr von deinem Code ins Forum, eventuell fällt uns noch was auf. Heute Abend ist es mir leider schon zu spät noch mal in das Datenblatt zu schauen, mir erscheint aber die Übertragung der Daten recht einfach zu sein, eventuell hast du dich auch beim Anschluss der Signale "hardwaremäßig" vertan.

Bei der Initialisierungs- und Übertragungsroutine verwende auch testweise mal Delays.

Delay kannst du zB so erzeugen:



CodeBox C
#define F_CPU 16000000UL  // Deine Systemfrequenz
#include <util/delay.h>

// ...

void meine_funktion (void)
{
  // ...

  _delay_us(10);  // 10us delay

  _delay_ms(10); // 10ms delay
}



Dirk :ciao:
 
Hi Ralf,



ja, das mache ich doch. Ich sende 4 Byte für die Frequenz + 1 Byte Control = 5 Byte = 40 Bit

In deiner veränderten Form sendest du das höchswertige Byte (Control Byte) zuerst, danach MSB byte der Frequenz. Und da immer LSB von jedem Byte zuerst.

Das geht garnicht!

Deine Version:



Soweit ich im Datenblatt gesehen habe, wird mit LSB angefangen. Es werden 40 Bit gesendet. Zuerst 32 Bit (0..31) diese Frequenz, das sind 4 Byte und dann noch ein Byte Control (32..39).

Also erstes Bit ist Bit0 und letztes Bit ist Bit 39.


Das macht meine Version:


CodeBox C
void AD9850_SendFrequency (uint32_t freq)
{
// 32Bit Frequency
AD9850_SendByte ((uint8_t) freq);
AD9850_SendByte ((uint8_t) (freq>>8));
AD9850_SendByte ((uint8_t) (freq>>16));
AD9850_SendByte ((uint8_t) (freq>>24));
// 8Bit Control, PowerDown, Phase
AD9850_SendByte (0);
// FQ_UD Pulse: Update
AD9850_PORT |= (1<<AD9850_FQ_UD);
AD9850_PORT &= ~(1<<AD9850_FQ_UD);
}

AD9850_SendByte sendet dann immer LSB zuerst. Es werden also 40 Bit von LSB nach MSB heraus-"geshiftet". Das letzte Byte ist das Controlbyte ( einschließlich PowerDown Bit + Phase Bits). Das sende ich grundsätzlich erst mal mit 0x00.

Ich sende also ...


CodeBox C
// 32Bit Frequency
AD9850_SendByte((uint8_t) freq);         // 0...7 Freq
AD9850_SendByte((uint8_t) (freq>>8));  // 8..15 Freq
AD9850_SendByte((uint8_t) (freq>>16));  // 16..23 Freq
AD9850_SendByte((uint8_t) (freq>>24));  // 24..31 Freq
AD9850_SendByte((uint8_t) (0));  // 32..39 Control


Warum hast du die Zeilen verdreht? Vielleicht stellst du auch mal mehr von deinem Code ins Forum, eventuell fällt uns noch was auf. Heute Abend ist es mir leider schon zu spät noch mal in das Datenblatt zu schauen, mir erscheint aber die Übertragung der Daten recht einfach zu sein, eventuell hast du dich auch beim Anschluss der Signale "hardwaremäßig" vertan.

Bei der Initialisierungs- und Übertragungsroutine verwende auch testweise mal Delays.

Delay kannst du zB so erzeugen:



CodeBox C
#define F_CPU 16000000UL  // Deine Systemfrequenz
#include <util/delay.h>

// ...

void meine_funktion (void)
{
  // ...

  _delay_us(10);  // 10us delay

  _delay_ms(10); // 10ms delay
}



Dirk :ciao:

Hi Dirk,
die Verzögerungen hatte ich schon drin mit _delay_us(10); Außer beim Setzen des Datenbits, welches mit der Clock übernommen wird (oder? ). Den Rest lade ich morgen mal hoch. Gruß Ralf





CodeBox C
#include <avr/io.h>
#define F_CPU 1000000UL // 1 MHz


#include <util/delay.h>
#include <avr/interrupt.h>




#define AD9850_PORT     PORTC
#define AD9850_DIR     DDRC

#define AD9850_DATA    PC0     //   Gelb     - connect to serial data load pin (DATA)
#define AD9850_CLK     PC1     //   Orange   - connect to AD9850 module word load clock pin (CLK)
#define AD9850_FQ_UD   PC2       //   Grün     - connect to freq update pin (FQ)
#define AD9850_RESET   PC3      //   Blau
#define AD9850_IR     PC4       //   Braun



void AD9850_Init (void);
void AD9850_SendByte (uint8_t data);
void AD9850_SendFrequency (uint32_t freq);



void AD9850_wait(void)
{
_delay_us(5);
}

void AD9850_Init (void)
{
  
  // CLK, FQ_UD, RESET, DATA: Low
  // CLK, FQ_UD, RESET, DATA: Output  
  AD9850_PORT &= ~((1<<AD9850_CLK) | (1<<AD9850_FQ_UD) | (1<<AD9850_RESET) | (1<<AD9850_DATA));
  AD9850_DIR |=  (1<<AD9850_CLK) | (1<<AD9850_FQ_UD) | (1<<AD9850_RESET) | (1<<AD9850_DATA);
  AD9850_wait();
  
  // Reset Pulse
  AD9850_PORT |= (1<<AD9850_RESET);
AD9850_wait();

  AD9850_PORT &= ~(1<<AD9850_RESET);  
AD9850_wait();
  
  // CLK Pulse
  AD9850_PORT |= (1<<AD9850_CLK);
AD9850_wait();

  AD9850_PORT &= ~(1<<AD9850_CLK);  
AD9850_wait();
  
  // FQ_UD Pulse
  AD9850_PORT |= (1<<AD9850_FQ_UD);  // Enable serial mode
AD9850_wait();
  AD9850_PORT &= ~(1<<AD9850_FQ_UD);  
AD9850_wait();
}




void AD9850_SendFrequency(uint32_t freq)
{


  
  
  // 32Bit Frequency

  AD9850_SendByte((uint8_t) freq);
  AD9850_SendByte((uint8_t) (freq>>8));  
  AD9850_SendByte((uint8_t) (freq>>16));  
  AD9850_SendByte((uint8_t) (freq>>24));  
  AD9850_SendByte((uint8_t) (0b00000000));  


  
  // 8Bit Control, PowerDown, Phase
AD9850_wait();
  
  // FQ_UD Pulse: Update
  AD9850_PORT |= (1<<AD9850_FQ_UD);
AD9850_wait();
  AD9850_PORT &= ~(1<<AD9850_FQ_UD);  
AD9850_wait();
  
}



void AD9850_SendByte (uint8_t data)
{
  
  uint8_t i = 8;
  
  do
  {
  
  if (data & 1)
  {
  AD9850_PORT |= (1<<AD9850_DATA);  // Data high
  } else {
  AD9850_PORT &= ~(1<<AD9850_DATA);  // Data low
  }
  
  // Clock
//AD9850_wait();

  AD9850_PORT |= (1<<AD9850_CLK);
AD9850_wait();
  AD9850_PORT &= ~(1<<AD9850_CLK);  
AD9850_wait();

  
  i--;
  data>>1;
  
  } while (i>0);
  
}













int main (void)
{
  
  
    
  // Initialisierungen
  
AD9850_Init();
/*
* TuningWert = f_soll * 2^32/125*10^6
* f_soll = 1kHz
*
//freq=freq*2^32/125000000;
//  unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK;

* TuningWert = 1*10^3 *2^32/125*10^6 = 2^32/125*10^3=34359,7 = 34360
*
* */

AD9850_SendFrequency(34360);


  
  while(1)
  {
  
  
  
  }
  
}




Hallo Dirk,
hier der Versuch.... ohne Erfolg.....
 
Zuletzt bearbeitet:
In den Zeilen 66 bis 69 werden die vier Frequenz-bytes (32 Bit) gesendet (bzw an die Senderoutine weitergereicht), in Zeile 72 folgt das Phasen-/Controlbyte (8 bit). Zusammen die 40 Bit.

in den Zeilen 75, 76 dann der Latch.

MSB=Bit39, Bit38, Bit37, ... Bit2, Bit1, Bit0=LSB
Wenn Du von links nach rechts schiebst, fällt das LSB raus (ins Carry, aber das interessiert Dich nicht), links wird 'ne 0 reingeschoben (=neues MSB).
Im AD... kommen die Bits dann von LINKS an, das erste ankommende Bit (eigentlich das LSB) landet also erstmal als MSB. Dann wird das ganze Bit für Bit nach rechts durchgeschoben.
In Zeile 66 werden die untersten 8 Bits des 32Bit-Frequenz-Wortes zum Senden übergeben,
In Zeile 67 Bit15..Bit8 usw usw

Hi LotadaC,
Danke ! Das hatte sich mir nicht gleich erschlossen. Hab gerade den kompletten Code hochgeladen.... funktioniert aber noch nicht..... Gruß Ralf
 
Hallo Ralf,

mir ist noch was aufgefallen.

Mach mal in der SendByte Funktion aus


CodeBox C
data>>1;

dies


CodeBox C
data = data>>1;


Dirk :ciao:
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)