Interrupt/Timer Problem: Nur einmalige Ausführung

Gast #1736867
Lesenswert?

Hallo,

ich habe ein Problem mit dem Verständnis von Interrupts. Mein Ziel war 
einen Timer zu erstellen der einmal in der Sekunde einen Interrupt 
erzeugt. Dazu habe ich den Timer1B (16Bit)
im CTC-Mode, Clock ist 16MHz, durch Prescaler auf 15625. Dann habe ich 
als Compare-Wert passend 15625 gewählt. So müsste das gewünschte 
Verhalten eintreten. Ein erster Interrupt wird mit dem Programm auch 
ausgelöst...danach passiert jedoch nichts mehr?! Wieso? Muss ich in der 
ISR etwas zurücksetzen oder ähnliches?

// Interrupt service routine for timer
ISR(TIMER1_COMPB_vect){
  switch_led(LED_DISPLAY,1);
  wait_ms(10);
  switch_led(LED_DISPLAY,0);
}

int main(){
  // PORTC for LEDs
  PORTC = 0xFF;
  DDRC = 0xFF;

  // Configure a timer
  // Clock: 16000000HZ
  // Prescaler: 1024=>15625 is the clock, CTC Mode
  TCCR1B = (1<<CS12) | (1<<CS10) | (1<<WGM12);
  OCR1B = 0x3D09; // Compare value is 15625
  // Activate Interrupts
  TIMSK1 = (1<<OCIE1B);
  sei();
  while(1){
  }
  return 0;
}
#1736927
Lesenswert?

Dein Verständnis von dem, was passieren sollte, ist schon richtig.  Ich 
sehe auch keinen Fehler im Programm (was nicht heißt, dass keiner drin 
ist - irgendwas muss faul sein).

Ein beliebter Fallstrick, wenn ein Interrupt nicht tut, was er soll, ist 
auch, dass der Prozessortyp im Studio und/oder Makefile falsch angegeben 
ist (nur als Tipp, wo Du noch suchen könntest).
Gast #1736944
Lesenswert?

Stefan Ernst schrieb:
> OCR1A legt den Top-Wert beim CTC-Mode fest, nicht OCR1B.

Auch an dich Danken! Warum zählt der Timer bis zu dem in OCR1B 
definierten Wert hoch und löst den Interrupt aus? Irgendeine Verbindung 
muss doch bestehen. Ich dachte ich muss OCR1B verwenden da ich auch das 
TCCR1B beschreibe.
#1736950
Lesenswert?

Tobi schrieb:

> Warum zählt der Timer bis zu dem in OCR1B
> definierten Wert hoch und löst den Interrupt aus?

Tut er sehr wahrscheinlich nicht. Ich wette dieser erste Interrupt wird 
bereits beim Freigeben der Interrupts ausgelöst, weil zu diesem 
Zeitpunkt das Compare-Flag gesetzt ist (weil zu dem Zeitpunkt, wo der 
Timer gestartet wird, in OCR1B der Wert 0 steht).

> Ich dachte ich muss OCR1B verwenden da ich auch das
> TCCR1B beschreibe.

Es besteht nicht der geringste Zusammenhang zwischen den beiden 'B'.
Gast #1736953
Lesenswert?

Ein allgemeiner Tip zur Interrupt-Nutzung:

Es spielt hier aufgrund der Zeitabstände keine Rolle, aber 
erfahrungsgemäß ist das ein beliebter Fallstrick:

Interrupt-Routinen sind so kurz wie irgend möglich und setzen nur Flags 
und ggf. andere Variablen.

Deren Behandlung bzw. die Ausführung einer Timer-Ausgelösten Aktion 
erfolgt dann in main. Insbesondere sind Aufrufe von Subroutinen (ausser 
in Ausnahmefällen) ein absolutes "DONT DO IT". Gerade LCD-Subroutinen 
haben oft noch eigene Verzögerungen, so das man in späteren Projekten, 
das Problem bekommt. "Ohne Interrupt, direkt in main gehts aber wenn ich 
das im Interrupt mache, gehts nicht. Scheinbar werden Interrupts 
verschluckt".

In Deinem Fall wäre der gängige Weg, den OCR beim ersten Interrupt auf 
einen Wert für 10ms zu setzen und beim nächsten wieder auf 1s.
In main dann wird das Display (in irgendeiner Hinsicht) geschaltet.

Falls Du meinem Rat, nur mal so zum probieren folgst, denke an 
"volatile".

Viel Erfolg.
Gast #1736958
Lesenswert?

Tobi schrieb:
> Ich dachte ich muss OCR1B verwenden da ich auch das TCCR1B beschreibe.

Wie bist du denn auf diesen Zusammenhang gekomnen? Das hat nämlich mal 
überhaupt nichts mit einander zu tun.

Du betreibst den Timer im Modus 4, da wird OCR1A als TOP-Wert genommen. 
Wenn er - wie bei dir - 0 ist, zählt der Zähler komplett durch.
Hast du mal etwas länger gewartet? Das Intervall müßte etwa bei 4 
Sekunden liegen, weil der Zähler dann erst ein zweites Mal den Wert 
15625 erreicht hat, bei dem der Interrupt nochmal ausgelöst würde.
Gast #1737005
Lesenswert?

Stefan Ernst schrieb:
> Rolf Magnus schrieb:
>> Wenn er - wie bei dir - 0 ist, zählt der Zähler komplett durch.
>
> Wie kommst du denn darauf?
> Bei OCR1A=0 bleibt der Zähler dauerhaft 0. Er macht dann quasi nichts
> anderes, als ständig überzulaufen.

Stimmt. Ich hatte mich im Datenblatt verlesen.

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