Hi. Ich bin gerade ein bisschen am Testen mit nem ATmega32 und wollte jetzt mal nen Sinus mit variabler Frequenz erzeugen, um schöne Töne ausgeben zu können und später vielleicht auch mehrere Töne gleichzeitig ausgeben zu können (Überlagerung). Ich hab mir beim Programmstart ne Sinus-Tabelle mit 64 Einträgen angelegt: for (i = 0; i < 64; i++) sintab[i] = (127. * sin(2 PI i /64)) + 127.; Im weiteren Verlauf des Programms nehm ich immer einen Wert davon, geb ihn über eine 8-Bit-PWM (Timer 2) aus und erhöhe den Zähler, der auf eine Stelle in der Tabelle zeigt. Über nen Tiefpass am Ausgangs-Pin ergibt sich dann auch ein schöner Sinus mit ca. 1 Hz bei Taktfrequenz 1 MHz. Wie kann ich diese Frequenz jetzt zur Laufzeit ändern? Danke schon mal.
> Wie kann ich diese Frequenz jetzt zur Laufzeit ändern? Vielleicht durch Ändern der PWM-Frequenz? > Danke schon mal. Keine Ursache...
Moin, mach z.B. das Holen des nächsten Tabellenwertes in der Interruptroutine eines anderen Timers. Die Änderung des Interruptzyklus dieses Timers ändert dann die Frequenz des Sinus.
@johnny.m: Eben nicht! @kernel: Du mußt die Frequenz ändern, mit der Du die Schleife aufrufst, die einen Wert aus der Tabelle holt, ihn ins PWM-Register schreibt und den Zähler erhöht. Dabei solltest Du daran denken, daß die maximale Frequenz, die Du über einen PWM-Ausgang ausgeben kannst um ein vielfaches unter der PWM-Frequenz liegt. Schließlich ist der PWM ein Tiefpass nachgeschaltet, daß die Aufgabe hat, die eigentlich PWM-Frequenz rauszufiltern. Je nachdem wie steil Dein Filter ist und wie sauber Du das Signal haben möchtest, mußt Du den Abstand von PWM-Frequenz und maximaler Ausgabefrequenz wählen. Mit welcher Frequenz arbeitet denn Deine PWM? Allgemein kann man aber sagen, daß PWM eine schlechte Methode ist, ein Audiosignal mit einem µC zu erzeugen. Da würde ich eher so einen ganz simplen D/A-Wandler, bestehend aus ein paar Widerständen an einem acht-bit-Port verwenden - mal vorausgesetzt, Du hast noch sowas frei. Markus_8051
Das ist eine normale "DDS"-Sinuserzeugung. Um die Frequenz zu ändern variiert man die Sprungweite in der Tabelle, die Zeit zwischen den Tabellenwertausgaben bleibt konstant.
> Eben nicht!
Stimmt natürlich. Man müsste dann ja auch die Tabellenwerte entsprechend
skalieren. Und dabei ginge die ganze Auflösung den Bach runter...
Christoph damit verlierst du aber an auflösung, wenn möglich ist es besser die timer frequenz mit der die neuen werte geladen werden zu erhöhen.
Ja sicher, jeder DDS hat Jitter. Je höher die Frequenz desto schlimmer, die Stufen sind ja ab der niedrigsten Frequenz gleich. Die Sinustabelle muß möglichst groß sein, so dass die niedrigste Frequenz gerade jeden Tabellenwert einmal aufruft. Mit PWM wird die Auflösung nochmal verschlechtert, denn die muß in der Frequenz noch deutlich über dem Tabellenauslesetakt liegen.
Bei Verwendung des 16Bit Timers bekommt man mit einem 3,68640MHz Quarz eine Auflösung von delta_f=56,25Hz. Bei einer Periode des Sinus mit 8Bit ist die max. Frequenz f_max=13,619kHz. delta_f = 3.68640MHz / 2^16 f_max = 2^8 * 3,68640MHz / 2^16 init = f_soll * 2^16 / 3.6864MHz Ich weiß jetzt nur nicht ob man den Timer auch mehr als "eins" erhöhen kann. for (;;) TEMP = TEMP + init; u_sin = sintab[TEMP(15:8)];
> Ich weiß jetzt nur nicht ob man den Timer auch mehr als "eins" > erhöhen kann. Das nicht. Aber mit dem CTC Modus kannst du dir sehr einfach fast nach jeder beliebigen Taktzyklenzahl einen Interrupt auslösen lassen.
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.