Ich stehe irgendwie auf dem Schlauch. Ich will mit einem ATmega168 bei 16 MHz (von mir aus auch ein anderer Quarz) eine Frequenz an einem I/O Pin erzeugen. Diese soll variabel von 0 bis ca. 140.000 Hz in Ein-Herz Schritten veränderbar sein. Da ich mehrere Frequenzen gleichzeitig benötige, dachte ich an eine Lösung mit einem Zähler für die Impulse und Timer. Aber irgendwie habe ich ein Brett vor dem Kopf, wie ich das in GCC umsetzen kann. Timer sind eigentlich kein Problem. Kann mir wer einen Denkanstoß geben?
Das Zauberwort lautet DDS: https://de.wikipedia.org/wiki/Direct_Digital_Synthesis An deiner Stelle würde ich überlegen, für 5€ bei der Bucht ein AD9850-Modul zu kaufen und mit dem Controller anzusteuern. So kommst du locker bis 20 oder 30MHz in 0,1Hz-Schritten.
Ah, ihr seit schnell. Aber ich brauche keinen D/A Wandler. Ich will ein reines TTL Rechtecksignal generieren. Oder habe ich da jetzt was zu schnell überflogen?
Leif schrieb: > Ah, ihr seit schnell. Aber ich brauche keinen D/A Wandler. Ich > will ein > reines TTL Rechtecksignal generieren. Oder habe ich da jetzt was zu > schnell überflogen? Stimmt, du brauchst keinen D/A-Wandler. Der ist schon im IC drin :-) Der AD9833 macht Sinus, Rechteck und Dreieck von Haus aus. Er kann eine Frequenz von 0..12,5MHz bei einer Auflösung von 0,1Hz erzeugen. Das ist alles schon in diesem einen IC.
Für ein Rechteck würde ich es so machen, dass ich das Tastverhältnis leicht variieren würde. Soll heißen, wenn man von kleinen zu großen Frequenzen geht: Von Schritt zu Schritt immer die Onzeit verkürzen, dann die Offzeit. Dann wieder die Onzeit verkürzen und dann die Offzeit. Dadurch erhält man grob gesagt die maximal mögliche Auflösung. Das Tastverhältnis bleibt bei annähernd 50%, damit hält man die nicht 50%-rechteckgerechten Oberwellenanteile klein. Es gibt bestimmt auch eine Formel, um die optimalen On-und-Offlängen für eine gegebene Frequenz zu erhalten.
Leif schrieb: > Ah, ihr seit schnell. Aber ich brauche keinen D/A Wandler. Ich will ein > reines TTL Rechtecksignal generieren. Oder habe ich da jetzt was zu > schnell überflogen? Der AD9850 hat den AD-Wandler schon eingebaut und er hat neben dem Sinus auch einen Rechteckausgang. npn schrieb: > Stimmt, du brauchst keinen D/A-Wandler. Der ist schon im IC drin :-) > Der AD9833 macht Sinus, Rechteck und Dreieck von Haus aus. Er kann eine > Frequenz von 0..12,5MHz bei einer Auflösung von 0,1Hz erzeugen. Wenn 12,5MHz gut darstellbar sind und Dir reichen, ist das sicher eine gute Wahl.
Gerrit schrieb: > Wenn 12,5MHz gut darstellbar sind und Dir reichen, ist das sicher eine > gute Wahl. Die werden ihm reichen :-) Leif schrieb: > Diese soll variabel von 0 bis ca. 140.000 Hz in Ein-Herz > Schritten veränderbar sein.
Mit der Maximalfrequenz am T-Pin rein und am OC-Pin raus. Sind dann zwar nur 16 Bit (eigentlich brauchst ja mindestens 17) aber besser als nix.
Wo ist mein Denkfehler? Das folgende erzeugt kein Signal. Sollte doch aber oder?
1 | #include <stdint.h> |
2 | #include <avr/interrupt.h> |
3 | #include <avr/io.h> |
4 | |
5 | #define OUT1DDR DDRB
|
6 | #define OUT1PORT PORTB
|
7 | #define OUT1PIN PB1
|
8 | volatile uint16_t z=0; |
9 | |
10 | ISR (TIMER1_COMPA_vect) |
11 | {
|
12 | |
13 | z++; |
14 | if (z >= 10) |
15 | {
|
16 | OUT1PORT ^= (1 << OUT1PIN); |
17 | z = 0; |
18 | }
|
19 | |
20 | }
|
21 | |
22 | |
23 | int main (void) |
24 | {
|
25 | OUT1PORT &= ~(1 << OUT1PIN); // Aus |
26 | OUT1DDR |= (1 << OUT1PIN); // Richtung: Ausgang |
27 | |
28 | TIMSK1 |= (1 << OCIE1A); // Output Compare A Match Interrupt Enable |
29 | OCR1A = 9; |
30 | TCCR1B |= (1 << CS11); // // Prescaler: 1/8 |
31 | TCCR1B |= (1 << WGM12); // CTC |
32 | sei(); |
33 | |
34 | |
35 | while (1); |
36 | |
37 | return 0; |
38 | }
|
Wenn ich schreibe:
1 | ISR (TIMER1_COMPA_vect) |
2 | {
|
3 | OUT1PORT ^= (1 << OUT1PIN); |
4 | }
|
dann kommen immerhin 100kHz raus. Wobei ab und zu eine Flanke außerhalb der Reihe tanzt. Mit dem Zähler oben sollte doch dann 1/10 Takr raus kommen. ???
gvs schrieb: > Mit der Maximalfrequenz am T-Pin rein und am OC-Pin raus. Sind > dann zwar > nur 16 Bit (eigentlich brauchst ja mindestens 17) aber besser als nix. Der AD9833 hat aber keinen T- und OC-Pin. Und der AD9850 auch nicht. (???)
npn schrieb: > Der AD9833 hat aber keinen T- und OC-Pin. Und der AD9850 auch nicht. > (???) Leif schrieb: > Ich will mit einem ATmega168 Ohne Studium des Datenblatts behaupte ich er hätte sie.
gvs schrieb: > Ohne Studium des Datenblatts behaupte ich er hätte sie. Ich auch :-) Sorry, den Mega168 hatte ich glatt übersehen, weil die ganze Zeit von DDS die Rede war.
Leif schrieb: > Mit dem Zähler oben sollte doch dann 1/10 Takr raus > kommen. ??? Mit Prescaler 1/80 oder ?
Na ich dachte, wenn der Timer alle 0,00001s auslöst und ich darin 10 "Takte" zähle, dann produziere ich 10kHz. Muß doch irgendwie ganz simpel sein, so ein Signalgenerator mit "geringer" Frequenz ohne extra Hardware zu lösen. Aber wie gesagt: Brett vorm Kopf.
Leif schrieb: > dann kommen immerhin 100kHz raus Schon mal überlegt, dass die ISR ggf. etwas lang ist ... Probier doch mal Precaler 32 - ich wette, dann funktioniert auch die Zähl-Routine ... (halt mit dann 2,5 kHz).
Wenn der mit 100kHz laufen würde, was ich bezweifle bei Prescaler 8. Der Delay der ISR sollte nicht wirklich ins Gewicht fallen, und sich auf wenige Clocks beschränken, wenn man nicht gerade uint16 nimmt um bis 10 zu zählen.
Schon mal an den Jitter der Periodendauer und der Pulsbreite gedacht? Nehmen wir die 140,000kHz. Dazu braucht man 71.428571 Takte bei 10MHz Prozessorfrequenz. Egal wie man das macht (Software/Timer), die Periodendauer muss immer zwischen 71 und 72 Takten umgeschaltet werden um im Mittel in 1s auf 140000 Perioden zu kommen. Das sind 1,4% Jitter in der Periodendauer und 2,8% Jitter in der Pulsbreite. Damit man in der Mitte den Pegelwechsel macht muss man nach 35 oder 36 Takten den Ausgang umschalten. Da kann der Prozessor nichts anderes mehr tun, da sonst ja sofort die Zahl der Zyklen total falsch(zu groß) wird. Es gibt einen PIC der eine DDS mit 1Bit-Ausgang in Hardware eingebaut hat. Damit hat man zwar auch den Periodenjitter, aber der Prozessor wird überhaupt nicht belastet und ist somit frei für andere Aufgaben. Mit echtem DDS (ADxxxx) hat man diese Probleme überhaupt nicht.
Oder man bekommt es hin, dass ein timer die Onzeit erzeugt, dann toggle, dann der zweite Timer für die Offzeit, toggle, das ganze von vorne. dann kann man die Werte für on und off in die entsprechenden Register (OCR... oder so) laden, ohne dass der Prozessor belastet wird.
http://www.holger-klabunde.de/pll/30gen.htm Beitrag "Rechteckgenerator mit Atmega8 timer Problem" http://www.roboternetz.de/community/threads/33346-atmega-als-variabler-rechteckgenerator
Vielleicht solltet ihr alle mal richtig lesen. Hier der Wunsch des
Fragestellers.
>Diese soll variabel von 0 bis ca. 140.000 Hz in Ein-Herz Schritten veränderbar
sein.
Erzeugt mal bitte mit euren Timervorschlägen 139999Hz und 140000Hz. Die
Quarzfrequenz sei 10MHz. Ich bin gespannt.
Danke. Also doch Denk-Fehler. Fehler zu denken oder zu denken, gedacht zu haben. Ich werd's anders lösen. Besinnliche Feiertage!
Hallo Leif, schau doch mal diesen Thread an: Beitrag "Mikrocontroller als I/Q- Generator (MW bis KW)" Hier wird zwar ein PSoC3 oder 5 verwendet, aber mit dem PSoC4 (42xx), den es mittlerweile als Breakout- Board für wenige Euro auch in Deutschland gibt, sollte das Prinzip ebenso funktionieren. Die genannten Mikrocontroller von Cypress beinhalten eine PLL zur Takterzeugung. Bei der Programmierung könnte ich behilflich sein. Das Ganze könnte dann so aussehen wie auf dem Bild. Eventuell noch ein zweiter Drehgeber für verschiedene Schrittweiten, Festfrequenzen usw. Schönen Advent, Wolfgang
:
Bearbeitet durch User
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.