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
Hallo, schau Dir mal das Ergebnis dieser Rechnung im LCD an. Meiner Meinung fehlt hier ein Cast.
1 | int32_t freq = frequency * 4294967295UL/125000000UL; |
1 | int32_t freq = (int32_t)(frequency * 4294967295UL/125000000UL); |
gruß Frank
Ok, die Werte von freq stimmen jetzt. Aber nach Sinus sieht das immer noch nicht aus. Ist die Ansteuerung des AD9850 denn ok? Wäre prima, wenn da jemand mal draufschauen könnte. Ich sehe hier den Wald vor lauter Bäumen nicht mehr...
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. ;-)
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
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
Hast keinen LA? Zu geizig für Sechs Euro Fuffzich? Sollen nun alle die main.c auf ihren 9859 loslassen und dann mit ihrem LA nach dem Fehler suchen? Fragen über Fragen.
--- schrieb: > Hast keinen LA? > Zu geizig für Sechs Euro Fuffzich? Nicht der Wahrheit entsprechend. Beim Ali aktuell für 4,58$ inkl. Versand was ca. 3,80 EUR sind. https://www.aliexpress.com/item/Free-Shipping-10sets-100-New-Arrival-USB-Logic-Analyze-24M-8CH-MCU-ARM-FPGA-DSP-debug/32234091842.html?ws_ab_test=searchweb0_0,searchweb201602_3_10152_10065_10151_5490020_10068_10193_10194_10304_10307_10137_10060_10302_10155_10154_10056_10055_10054_5470020_10059_100031_10099_5460020_10338_10339_10103_10102_440_10052_10053_10107_10050_10142_10051_10320_10321_10322_5380020_10326_10084_10083_10080_10082_10081_10177_10110_10111_10112_10113_10114_143_10180_10312_10313_10314_10184_10319_10078_10079_10073_5550011_10186-10112,searchweb201603_23,ppcSwitch_2&btsid=fcd45083-ec2f-4568-a109-a5b5b1537287&algo_expid=dff5323b-fa26-43e4-951d-fa1ec4514f3d-2&algo_pvid=dff5323b-fa26-43e4-951d-fa1ec4514f3d
Sag mal woher Du es kopiert hast (Link), dann kann man es zumindest mit dem Original vregleichen. War das Original für einen anderen AVR-MC geschrieben - oder ggf. für den Arduino?
Hallo Schau nochmal ins Handbuch Seite 10 Timing Diagramm für Fq_ud dort steht eindeutig Low vor dem schieben, dann einmal High und dann wieder Low. Dann werden die Daten übernommen. Gruß Frank
:
Bearbeitet durch User
Pete K. schrieb: > Der Abschnitt oben sieht jetzt so aus: Nochmal die Frage: warum keine Hardware-SPI? Der von mir gepostete Code ist “known to work”.
Bei Analog Devices ist man oft im Bitbang Mode weil das Hardware SPI Timing nicht ganz passt. Dann kann man's auch gleich so lassen. Zudem ist Hardware SPI nicht sonderlich effizient. Weder mit Interrupts, noch mit Pollen.
:
Bearbeitet durch User
Sapperlot W. schrieb: > Bei Analog Devices ist man oft im Bitbang Mode weil das Hardware SPI > Timing nicht ganz passt. Dann kann man's auch gleich so lassen. Zudem > ist Hardware SPI nicht sonderlich effizient. Weder mit Interrupts, noch > mit Pollen. Fakenews? Gruß, Holm
Sapperlot W. schrieb: > weil das Hardware SPI Timing nicht ganz passt. Das schlechte SPI Timing sitzt dann wie üblich vor der Tastatur.
Sapperlot W. schrieb: > Bei Analog Devices ist man oft im Bitbang Mode weil das Hardware SPI > Timing nicht ganz passt. Nochmal ganz langsam: das da oben ist ein Codeschnipsel aus einem AD9850-Projekt von mir, welches nachweislich funktioniert. An Einfachheit und Geschwindigkeit ist es durch manuelle Bitbangerei sowieso nicht zu übertreffen.
Dieter F. schrieb: > Sag mal woher Du es kopiert hast (Link) Nicht mehr nötig, habe es - glaube ich - gefunden. Eine Portierung eines Arduino-Programms. http://www.ad7c.com/projects/ad9850-dds-vfo/
Hatte mich eher hier orientiert: https://electronicfreakblog.wordpress.com/2014/01/29/dds-signalgenerator-mit-ad9850/ @Jörg: Für Hardware-SPI müsste ich das neu verkabeln. Daher möchte ich das gerne erst einmal mit bit banging versuchen.
Pete K. schrieb: > Daher möchte ich das gerne erst einmal mit bit banging versuchen. Spätestens jetzt ist allerdings wirklich der Zeitpunkt gekommen, wo du einen LA benutzen solltest.
Pete K. schrieb: > Hatte mich eher hier orientiert: > https://electronicfreakblog.wordpress.com/2014/01/29/dds-signalgenerator-mit-ad9850/ Wenn Du es schreibst :-) merkwürdige Korrealtion der Kommentare ...
Darüber solltest du wohl nochmal nachdenken:
1 | // set FQUP low
|
2 | Port(FQUP_PORT) |= (1<<FQUP_PIN); |
3 | |
4 | // ...
|
5 | |
6 | // set FQUP high and take new frequency
|
7 | Port(FQUP_PORT) &= ~(1<<FQUP_PIN); |
Ganz davon abgesehen, vergleich' das mal mit meinem Code: dort kommt ein (kurzer) FQUD-Puls nach dem Schreiben des Datenworts.
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 | }
|
Ihr seit die Besten! Jetzt funktioniert es. Ich hatte noch einen dicken Bug in der init/reset Routine drin. Man sollte so etwas nicht spät abends programmieren ;-) Anbei das aktuelle Ergebnis. Danke!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.