Hallo zusammen,
ich versuche mich gerade am Timer meines ATmega88. Ich möchte ein
Clock-Signal erzeugen, welches dann auf einen Pin ausgegeben werden
soll. Die Frequenz sollte so bei 350kHz liegen.
Der Timer an sich läuft, aber irgendwie komme ich mit den erforderlichen
Einstellungen nicht ganz zu recht, genauer gesagt, ich komme nicht auf
die gewünschte Frequenz. Ich habe im Moment etwa 125kHz, d.h. eine
Periodendauer von etwa 8µs, Mit Oszi angesehen.
Der ATmega läuft mit 8MHz.
Den Timer wollte ich im CTC Modus laufen lassen.
Unten ist mein Code dazu.
Wäre klasse, wenn mir da jemand aufzeigen könnte, was isch da falsch
mache oder wo ich da einen Denkfehler drin habe.
Gruß und schon einmal vielen Dank!
Mein Code sieht bisher mal so aus:
Marco schrieb:> Mein Code sieht bisher mal so aus:
Wirklich? Ich sehe keine Funktion port(), und das Aufrufen von cli(),
d.h. das Deaktivieren von Interrupts macht auch nicht wirklich Sinn,
wenn diese zuvor nie eingeschaltet worden sind (sei()).
In welchem Modus möchtest du den Timer denn betreiben? Das reine
Ausgeben eines PWM-Signals kann mittels Output Compares direkt in
Hardware geschehen. Oder willst du es in Software lösen?
Übrigens: Da du mit jedem Interrupt das Signal nur toggelst, musst du
deinen Timer so einstellen, dass er mit der doppelten Frequenz, d.h. 700
kHz Interrupts auslöst.
Mit freundlichen Grüßen,
Karol Babioch
In Software mit Interrupts gibts aber nett Jitter.
Guck dir doch mal die Output Compare Units im datenblatt an und erledige
das Ganze in reiner Hardware.
Hallo,
vielleicht noch als Hinweis. Werde mir die Output Compare Units wie
geschrieben einmal anschauen und ausprobieren, aber wenn ich diesen Weg
schon einmal angefangen habe, wäre es nicht schlecht, auch das ans
Laufen zu bekommen, auch wenn es nicht der Beste Weg ist.
Vielen Dank!
Grüße
Marco schrieb:> Hallo,>> vielleicht noch als Hinweis. Werde mir die Output Compare Units wie> geschrieben einmal anschauen und ausprobieren, aber wenn ich diesen Weg> schon einmal angefangen habe, wäre es nicht schlecht, auch das ans> Laufen zu bekommen, auch wenn es nicht der Beste Weg ist.
Das ist überhaupt kein Weg.
Mit einem Interrupt alle 6 Taktzyklen wird das nichts. Alleine bis der
AVR die Bearbeitung des Interrupt Vektors aufnimmt vergehen schon einige
Taktzyklen (wenn mich mein Gedächtnis nicht trügt dann sind das 3, je
nachdem welcher Befehl durch den Interrupt unterbrochen wird). Den
unvermeidlichen reti noch dazu. Sichern des Statusregisters und Port
toggeln und du bist schon über den 6 Taktzklen draussen. Sprich: die
Interrupts werden schneller generiert, als sie abgearbeitet werden
können. Mit Assembler könnte man das gerade noch so retten, indem man
den Porttoggler direkt in die Vektortabelle einschreibt.
Nimm die Hardware. Dafür ist sie gemacht worden.
Hinweis. Auch mit einem Timer im PWM Modus kann man prima Schwingungen
erzeugen. Dann allerdings wirklich runter bis auf 2 Takzyklen pro
Schwingung. Also 4Mhz bei 8Mhz Taktfrequenz.
> Mit Assembler könnte man das gerade noch so retten
Nicht wirklich: bis zu 10 für OCR0A ändert sich gar nichts, man bekommt
ca. 364 kHz, ab 11 sind es dann 333 kHz, also völlig unbrauchbar. Es
bleibt folglich nur
> Nimm die Hardware
Wie berechnest du eigentlich deinen OCRA-Wert?
Wenn ich das richtig sehe, hast du CTC Mode mit OCRA als TOP-Wert und
Prescaler=1 / no prescaling.
Damit zählt der Counter alle 0,125 µs einen hoch. Mit dem Wert "6" (also
zählen von 0...6) wird der Interrupt alle 0,875 µs aufgerufen.
Entsprechende Frequenz wären c.a 1,14 MHz.
Ich komme auf 8MHz/350kHz = 22,86....
Nur theoretisch angenommen die ISR würde keine Rechenzeit benötigen
müsstest du diesen Wert halbieren und 1 abziehen um den richtigen Wert
für OCRA in deiner Lösung zu bekommen...
Das ist bei mir nicht 6.
Hallo,
vielen Dank. Das mit der Abarbeitungszeit des Interrupts ist
verständlich.
Werde mir dann mal die anderen Möglichkeiten ansehen!
Vielen Dank für de schnelle Hilfe!
Grüße