Hallo,
ich benötige zwei timer interrupts. Einen mit ca. 800Hz, einen mit 1Hz.
Timer1 hat ja zwei compare register, kann ich also auch zwei interrupts
ausführen lassen, die mit den gewünschten Frequenzen ausgelöst werden?
so sieht es derzeit aus:
Der Atmega läuft mit 16Mhz
So, wie es ist, laufen beide interrupt Routinen (COMPA und COMPB) bei
1Hz. Ich muss vermutlich CTC noch ausschalten, damit nicht mit 800Hz der
Counter zurückgesetzt wird, schließlich erreiche ich sonst nie die
15624+1 Takte, die ich für 1Hz brauche. Ich wundere mich aber, dass
nicht zumindest beide mit 800Hz laufen.
Danke im Voraus
Adrian
Ja das ginge, ich könnte ja auch noch Timer2 benutzen, ich frage mich
nur, wozu ich dann zwei compare register habe? Man kann sie ja für PWM
benutzen, vielleicht ja auch für normale interrupts
Adrian Figueroa schrieb:> Ja das ginge, ich könnte ja auch noch Timer2 benutzen, ich frage mich> nur, wozu ich dann zwei compare register habe? Man kann sie ja für PWM> benutzen, vielleicht ja auch für normale interrupts
Wenn du eine Uhr mit Sekundenzeiger hast (das ist der Timer), dann
kannst du dir ein Signal generieren lassen, wenn der Sekundenzeiger bei
28 ist (das ist das eine Compare-Register) und du kannst dir ein Signal
generieren lassen, wenn der Timer bei 43 ist (das ist das andere Compare
Register).
Aber: der zeitliche Abstand, in denen sowohl Signal 1, als auch Signal 2
ausgelöst werden, von einer Runde des Sekundenzählers zur nächsten ist
immer 60 Sekunden. Denn solange dauert es nun mal, bis der
Sekundenzähler von der Stellung 28 das nächste mal in Stellung 28 ist.
Und dasselbe gilt natürlich auch für die Stellung 43: Von einer Runde
des Sekundenzählers zur nächsten dauert es immer 60 Sekunden.
D.h. mit den beiden Compare-Registern kannst du dir 2 Signale generieren
lassen, die zueinander zeitlich versetzt sind. Aber die Frequenz, mit
der die beiden Signale auftreten kannst du nur für beide gemeinsam
festlegen. Denn diese Frequenz ist nicht davon abhängig, an welchem
Zählerstand du den Compare-Match auslösen lässt, sondern einzig und
alleine davon, wie weit der Zähler zählt, bis er einen Überlauf hat und
wieder bei 0 zu zählen anfängt.
Aber: du kannst ja bei 43 immer die Schreibtischlampe in den jeweils
anderen Zustand schalten, während du die Küchenbeleuchtung nur bei jedem
2.ten, 3.ten, 4.ten, 5.ten mal (etc) umschaltest. Dann schaltest du die
Küchenbeleuchtung nur mit der halben, drittel, viertel, fünftel, etc.
Frequenz, mit der du die Schreibtischlampe schaltest.
>Aber die Frequenz, mit der die beiden Signale auftreten kannst du nur für>beide gemeinsam festlegen.
Nicht grundsätzlich! Du gehst davon aus, dass sich die Inhalte von OCRA
und OCRB während der Laufzeit nicht (oder höchstens "gelegentlich")
ändern - unter dieser Bedingung ist Deine Aussage richtig. Falsch wird
sie, wenn man "böse" ist und z. B. den Inhalt von OCRB ständig ändert,
etwa indem man ihn in jedem OCRB-Interrupt um 20 inkrementiert. Das ist
ja nicht verboten.
Bin mal gespannt, ob's beim TE Klick macht... ;-)
Karl Heinz Buchegger schrieb:> Denn diese Frequenz ist nicht davon abhängig, an welchem> Zählerstand du den Compare-Match auslösen lässt, sondern einzig und> alleine davon, wie weit der Zähler zählt, bis er einen Überlauf hat und> wieder bei 0 zu zählen anfängt.
Gut, das ist logisch, sofern der CTC-Modus ausgeschaltet ist. Angenommen
er ist eingeschaltet, ist dann der kleinere Wert der beiden compare
register relevant? Offenbar nicht, denn ich bekomme immer den
Sekundentakt, oder, ich kann das nicht präzise bestimmen, einen Überlauf
der 16Bit counter-Zahl (ist ja dem Sekundentakt sehr ähnlich).
/edit: das stimmt ja gar nicht! Der Überlauf kommt erst bei ~65000
Ich meinte das mit dem ausgeschalteteten CTC oben so, dass man den
Counter manuell zurücksetzt, aber auch das hat ja keinen Sinn, es sei
denn, wie schon von dir erwähnt, das längere Zeitintervall ist von
seiner Länge ein Vielfaches des kürzeren.
Zum letzten Codeabschnitt:
Zu Beginn sind doch beide compare register genullt, werden bei jedem
erfolgreichen Vergleich aber um die Zahl erhöht, bis zu der vom jetzigen
Zählerstand gezählt werden müsste, damit die Periodendauer wie gewünscht
ausfällt. Anfangs also direkt beim ersten Takt, oder beim ersten
Überlauf.
Überläufe sind ja unkritisch, weil die Zahlen nicht vorzeichenbehaftet
sind?
Das scheint mir eine sehr elegante Lösung zu sein, die hat es direkt in
den Code geschafft! Danke :)
Eine andere Frage:
Am Ende wird aus dem Ding eine Uhr, man kann mit einem Drehimpulsgeber
nach rechts drehend die Minuten erhöhen, nach links die Stunden.
Ich will eine eigene Funktion schreiben, mir der ich ihn auslesen kann
und habe das hier dabei erzeugt:
Es funktioniert leider nicht, im Folgenden der Code:
Es werden nur Drehungen im Uhrzeigersinn erkannt... Ich fürchte auch,
der Code ist ein bisschen umständlich.
Die Pins werden mit 8kHz abgefragt.
> if (currentState > lastState) {return rising;}> else if (lastState < currentState) {return falling;}
In der ersten Zeile c > l und in der zweiten l < c?
Vuvuzelatus schrieb:> In der ersten Zeile c > l und in der zweiten l < c?
Oh ja das war falsch, danke!
Es läuft jetzt, ich hatte einen Denkfehler. Ich nehme mal an, es geht
auch hübscher (platzsparender), als mit Arrays, so ist es aber recht
übersichtlich.
Ich habe noch mal ausprobiert, wie es mit dem eleganteren Weg von Peter
Dannegger aus dem wiki funktioniert, mit folgendem code kann ich die
Richtung irgendwie nicht erkennen...
Ich habe mir eine Wahrheitstabelle geschrieben:
PIN 21 |BIN
00 |00 :Pin1 off/Pin2 off -> 0
10 |01 :Pin1 off/Pin2 on -> 1
11 |10 :Pin1 on/Pin2 on -> 2
01 |11 :Pin1 on/Pin2 off -> 3
Das Setzen der "3", sobald Pin1 angeschaltet ist und dem Umschalten des
unteren bits, sobald der andere Pin an ist, habe ich so nachvollzogen.
Die Differenz der Zustände ist bei einem um 1 kleineren currentState als
lastState negativ, also eine -1 im Zweierkomplement (entspricht 11111111
bin). Das niedrigste Bit ist immer 1, sofern die Zahlen sich um eins
unterscheiden, das zweitniedrigste ist dann eins, wenn currentState
kleiner war als lastState. Habe ich das richtig verstanden?
damit ist
1
int8_tdirection=(diff&2)-1;
entweder 1 (diff & 2 = 2) oder -1 (diff & 2 = 0).
im unteren code togglet "beep();" einen pieper. wenn ich einen
rastschritt drehe, schaltet sich der pieper an und wieder aus,
unabhängig von der Richtung!