AVR: 16-bit-Counter Verwendung so ok?

Gast #729929
Lesenswert?

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_t intervall = xxx; // interrupt immer wenn der counter xxx mal gezählt hat
2

3
void timer_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
Gast #729935
Lesenswert?

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.
Gast #729949
Lesenswert?

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
#729958
Lesenswert?

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.
Gast #729962
Lesenswert?

>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.
Gast #729971
Lesenswert?

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
Gast #730059
Lesenswert?

>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.
#730109
Lesenswert?

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!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren