Also ich möchte ein Interrupt in bestimmten Intervallen haben (z.B. alle
60ms), dazu berechne ich mir (zur Laufzeit) welchen Prescaler ich
brauche, und wie weit der 16-bit Counter laufen soll (mega16).
Den Wert wie weit der Counter laufen sol, lade ich in ein
Compare-Register.
Soweit klappt das auch, nur kann ich beim mega16 wohl nicht sagen, er
soll bei einem CompareMatch den Counter wieder auf 0 setzen, wohl weil
es zwei Compare-Register gibt.
Da hab ich mir folgendes ausgedacht (C-Code, geht aber ums Prinzip):
1
uint16_tintervall=xxx;// interrupt immer wenn der counter xxx mal gezählt hat
2
3
voidtimer_init(/*...*/){
4
/* der ganze andere initalisierungskrempel */
5
// set compare value
6
OCR1A=0;
7
}
8
9
ISR(TIMER1_COMPA_vect){
10
// wirte new comparevalue
11
OCR1A+=intervall;
12
}
Anstatt den Counter jedes mal auf 0 zu setzen, schreibe ich als einen
neuen Compare-Wert.
Geht das so?
Gruß
Thomas
Thomas wrote:
> Soweit klappt das auch, nur kann ich beim mega16 wohl nicht sagen, er> soll bei einem CompareMatch den Counter wieder auf 0 setzen, wohl weil> es zwei Compare-Register gibt.
Doch, das geht, und zwar mit OCR1A im CTC Modus.
geht so, aber es gibt den CTC-Mode, da brauchst du gar nichts nachladen.
Beim Compare-Ereignis wird der Zähler per Hardware wieder auf 0 gesetzt.
Empfiehlt sich eigentlich immer für solche Aufgaben, kleinere
Interruptlaufzeit, keine Jitter, wenn der MC gerade mal in einer anderen
ISR beschäftigt ist.
Danke für den Tip, dachte zunächst das geht nicht, weil es kein eigenes
Bit gibt, wo man das setzen kann, aber hab nun mal gesucht.
Kannst du mir bitte noch sagen ob das hier dann stimmt so:
TCCR1A = (1<<WGM12);
Er setzt dann den Counter wieder auf 0, wenn es ein Compare Match mit
OCR1A oder OCR1B gibt - richtig? Muss ich dann OCR1B auf einen
größeren Wert als OCR1A setzen? Könnte ich ja einfach auf 0xffff
stellen.
Danke schonmal
Thomas wrote:
> Er setzt dann den Counter wieder auf 0, wenn es ein Compare Match mit> OCR1A oder OCR1B gibt - richtig?
falsch.
< Muss ich dann OCR1B auf einen
> größeren Wert als OCR1A setzen? Könnte ich ja einfach auf 0xffff> stellen.
Bitte schau noch mal ins Datenblatt.
Dort gibt es eine Tabelle über die einzelnen Modi des Timers1.
In dieser Tabelle steht auch, welches Register (wenn überhaupt)
den Max-Wert des Timers liefert.
>Kannst du mir bitte noch sagen ob das hier dann stimmt so:>TCCR1A = (1<<WGM12);
Ja, das ist der CTC Mode mit OCR1A als Match-Register.
>Er setzt dann den Counter wieder auf 0, wenn es ein Compare Match mit>OCR1A oder OCR1B gibt - richtig?
Nein, nur OCR1A. OCR1B hat im CTC Mode keine Bedeutung.
>Muss ich dann OCR1B auf einen größeren Wert als OCR1A setzen? Könnte ich ja >einfach auf 0xffff stellen.
Der Wert von OCR1B ist völlig egal, weil dieses Register im CTC Mode
nicht ausgewertet wird.
All diese Informationen findest Du übrigens auch im Datenblatt.
Ok Entschuldigung, dachte da gibts gar nicht viel Möglichkeiten und habe
wirklich nicht nachgeschaut.
PS: Grund der anfänglichen Verwirrung war, dass in dem GCC-Tutorial mit
CTC1 gearbeitet wird, und das nun wohl WGM13,WGM12,WGM11,WGM10 geht.
Gruß & Danke
Thomas
>dass in dem GCC-Tutorial mit>CTC1 gearbeitet wird, und das nun wohl WGM13,WGM12,WGM11,WGM10 geht.
Ah, verstehe. Ja, die Bit-Namen CTC1 sowie PWM11 und PWM10 sind
veraltet, aber aus Kompatibilitätsgründen weiterhin definiert. Für neue
Anwendungen sollte man nur mit WGM13, WGM12, WGM11, WGM10 arbeiten.
Um einen repetitiven timer interrupt zu bekommen kann man's einfacher
haben. Nur den Timer mit Overflow-Zahl laden und den Overflow interrupt
enablen, den Rest braucht man dazu nicht. siehe auch
http://www.ibrtses.com/embedded/avrasmuartint.html
ren wrote:
> Um einen repetitiven timer interrupt zu bekommen kann man's einfacher> haben.
Was ist an einem Timer Preload einfacher?
Ausser der ständigen Schererei, dass du nicht weist wieviele
Takte vom Auslösen des Interrupts bis zum Aufruf der ISR
vergangen sind; dass du ständig alle Takte vom Beginn der
ISR bis zum eigentlichen Reload zählen musst und im Reload
Wert berücksichtigen musst.
Alles Dinge, die im CTC Modus keinen Menschen interessieren
und auch nicht zu interessieren brauchen, weil die Hardware
das Rücksetzen des Timers ganz von alleine macht. Und zwar
auf den Takt genau!
Das einzige was anders ist: Es wird ein anderer Interrupt
aufgerufen, die Initialisierungssequenz ist ein klein
wenig anders und man muss nicht grossartig rumrechnen
um den Preload Wert zu kriegen. Ich will alle 200 Takte
einen Interrupt, also schreib ich diesen Wert (OK: 199)
in das OCR Register. Fertig!