AD9850 braucht Hilfe

OP #5141026
Lesenswert?

Hallo,
ich wollte mir einen Frequenzgenerator mit dem AD9850 Modul bauen.
Leider stimmt wohl noch etwas mit der Software oder Hardware nicht.
Auf jeden Fall zappelt das Oszi in einem Bereich von ca. 80-110mV Vpp 
munter umher.
Klare Sinuskurven sind nicht erkennbar.

Anbei die main.c mit der Ansteuerung.

Das ganze ist auf Experimentierplatine aufgebaut und wird mit einem 9V 
Netzteil sowie einem TL780-05C Linearregler versorgt.

Hardware: 8Mhz Atmega328, AD9850 Modul, 2x16 LCD, ALPS Drehencoder.
Verschaltung: siehe main.c Listing
Angehängte Dateien:
Moderator Persönliche Seite #5141121
Lesenswert?

Pete K. schrieb:
> Aber nach Sinus sieht das immer noch nicht aus.

Ist ja auch keiner, ist ja eine Treppe. ;-)

Damit die annähernd nach Sinus aussieht, darf die Frequenz nicht zu
hoch sein.  Bei höheren Frequenzen entsteht der Sinus erst nach dem
Antialiasing-Filter.

Warum machst du die Ansteuerung im Bitbang-Modus?  Kannst du denn den
normalen SPI-Port nicht benutzen?

Hier mal ein Codeschnipsel, welches ich bei einem AD9850-Projekt mal
benutzt habe:
1
static void
2
init_ad9850(void)
3
{
4
  /*
5
   * Disable SPI, and reset the DDS circuitry.
6
   */
7
  SPCR = 0;
8
  PORTC |= _BV(0);
9
  PORTC &= ~_BV(0);
10

11
  /*
12
   * After reset, initiate one W_CLK pulse followed by one FQ_UD pulse
13
   * to activate the serial configuration control word.
14
   */
15
  PORTB |= _BV(7);
16
  PORTB &= ~_BV(7);
17
  PORTC |= _BV(1);
18
  PORTC &= ~_BV(1);
19

20
  /*
21
   * Now, we're ready to hand over the data transmission to SPI.
22
   */
23
  SPCR = _BV(SPE) | _BV(DORD) | _BV(MSTR);
24
  SPSR = _BV(SPI2X);
25
}
26

27
static void
28
fq_ud(uint32_t fq)
29
{
30
  union
31
  {
32
    uint32_t l;
33
    uint8_t b[5];
34
  }
35
  u;
36
  uint8_t i;
37

38
  u.l = fq;
39
  /*
40
   * W32..W39: no phase angle, no power-down, control bits = 0
41
   */
42
  u.b[4] = 0;
43

44
  for (i = 0; i < 5; i++)
45
    {
46
      SPDR = u.b[i];
47
      while ((SPSR & _BV(SPIF)) == 0)
48
        /* wait */;
49
    }
50

51
  /* Update now. */
52
  PORTC |= _BV(1);
53
  PORTC &= ~_BV(1);
54
}

Ist nicht sehr gut abstrahiert, gebe ich zu. ;-)
(Firma: Flk Consulting UG) #5141122
Lesenswert?

Hallo,
dann schau Dir mal Dein Bit geschubse an, das kann so auch nicht 
stimmen.
1
for (int i=0; i<8; i++, data>>=1) {
2
  if ((data & 0x01)==0) {Port(D7_PORT) &= ~(1<<i);} //clear
3
  if ((data & 0x01)==1) {Port(D7_PORT) |= (1<<i);} //set

Entweder Du setzt ein Bit oder Du löscht es. Aber das komische ~(1<<i) 
ist komplett überflüssig.

Gruß
Frank
OP #5141173
Lesenswert?

Jörg W. schrieb:
> Ist ja auch keiner, ist ja eine Treppe. ;-)

Aktuell teste ich mit 100Hz - 10kHz. Das sollte noch gehen.

Der Abschnitt oben sieht jetzt so aus:
for (int i=0; i<8; i++) {
  if ((data & 0x01)==0) {Port(D7_PORT) &= ~(1<<D7_PIN);} //clear
  if ((data & 0x01)==1) {Port(D7_PORT) |= (1<<D7_PIN);} //set
        data>>=1;

Der Ausgang bleibt auf 1,08V mit einem "Ripple" von ca. 80-100mVpp
#5141217
Lesenswert?

Gast #5142027
Lesenswert?

Jörg W. schrieb:
> dort kommt
> ein (kurzer) FQUD-Puls nach dem Schreiben des Datenworts.

In der von mir erwähnten Vorlage auch:
1
#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
2

3
...
4

5
// frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
6
void sendFrequency(double frequency) {  
7
  if (GoIF == 1){frequency=frequency-iffreq;}; //If pin = low, subtract the IF frequency.
8
  int32_t freq = frequency * 4294967295/125000000;  // note 125 MHz clock on 9850.  You can make 'slight' tuning variations here by adjusting the clock frequency.
9
  for (int b=0; b<4; b++, freq>>=8) {
10
    tfr_byte(freq & 0xFF);
11
  }
12
  tfr_byte(0x000);   // Final control byte, all 0 for 9850 chip
13
  pulseHigh(FQ_UD);  // Done!  Should see output
14
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren