Forum: Mikrocontroller und Digitale Elektronik AVR - Beide OC-Register eines Timers verwenden?


von Bernd E. (niro)


Lesenswert?

Hallo zusammen,

ich möchte gerne beim Timer1 (ATmega328, 4MHz) beide 
OutputCompare-Register verwenden, um unterschiedliche Routinen auzurufen 
(Routine A alle 1ms ; Routine B alle 100ms).
Routine A geht, aber irgendwie schaffe ich nicht, daß auch der IRQ für 
Routine B (100ms) ausgelöst wird.
Habe ich irgend ein Register übersehen oder kann man gar nicht beide 
Register gleichzeitig benutzen?

Ich habe die Register folgendermaßen konfiguriert:

Routine A, alle 1ms:
TCCR1A = 0x00; //  arbeitet als normaler Timer, PWM aus, PinAusgang 
deaktiviert
TCCR1B = 1<<CS11 ;  //Prescaler auf 8
TIMSK1 |= 1<<OCIE1A;
OCR1A = 499; // Compare-Wert für 1ms-adjust (aus AVR TimerCalculator)
TCNT1 = 0; // Timmer startet mit 0
sei(); //globale IR Schalter EIN

Routine B, alle 100ms:
TIMSK1 |= 1<<OCIE1B;
OCR1B = 49999; // Copmare-Wert für 100ms-adjust
TCNT1 = 0; // Timmer startet mit 0
sei(); //globale IR Schalter EIN

Vielen Dank!

von Pink S. (pinkshell)


Lesenswert?

Bernd E. schrieb:
> kann man gar nicht beide
> Register gleichzeitig benutzen?

Kann man schon, aber nicht so wie du das vorhast.

Der Timerwert wird alle 1 ms wieder auf Null gesetzt, und wird die 49999 
nie erreichen. Die beiden OC-Register vergleichen sich mit dem gleichen 
Timer.

Mit zwei verschiedenen Timern würde es gehen.

von Falk B. (falk)


Lesenswert?

@  Bernd E. (niro)

>OutputCompare-Register verwenden, um unterschiedliche Routinen auzurufen
>(Routine A alle 1ms ; Routine B alle 100ms).

Dazu bruacht man keine zwei Interrupts, einer reicht. Dort zählt man bis 
100 (einmal pro aufruf!) und ruft dann die Routine auf. Bei 100ms kann 
man das wahrscheinlich auch in die Hauptschleife verlagern, siehe 
Interupt.

Aber wenn man es so machen will, dann so.

>OCR1A = 499; // Compare-Wert für 1ms-adjust (aus AVR TimerCalculator)
>TCNT1 = 0; // Timmer startet mit 0
>sei(); //globale IR Schalter EIN

Macht man nicht so. Der Startwert ist egal, der "Trick" ist, den OCR 
Wert in der ISR jeweils zu erhöhen. Der Interrupt kommt also nicht immer 
beim gleichen Timerwert, der zeitliche Abstand passt trotzdem immer!

ISR(OCR1A) [
  OCR1A += 500;
}

ISR(OCR1B) [
  OCR1B += 50000;
}

MfG
Falk

P S Ok, die Startwerte kann man nutzen, um beide Interrupt optimal zu 
verschachteln, damit sie sich nicht gegenseitg ausbremsen.

TCNT1 = 0;
OCR1A = 499;
OCR1A = 49999+250;

Damit fällt der 100ms Interrupt immer genau zwischen zwei 1ms Interrupt. 
Das nütz aber nur was, wenn der max. 0,5ms braucht.

von Bernd E. (niro)


Lesenswert?

Ok, danke erstmal für die schnellen Antworten!
Ich werde das nacher mal probieren...

Grüße,
Bernd

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
Noch kein Account? Hier anmelden.