mikrocontroller.net

Forum: Compiler & IDEs Interrupt/Timer Problem: Nur einmalige Ausführung


Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welcher Controller?  (Wegen PORTC -> JTAG-Fuse?)

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AT90CAN128, JTAG liegt dort auf PORTF, LEDs blinken auf wie gewollt. Nur 
halt nicht durch Interrupt (bzw. durch mehr als einen Interrupt).

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  OCR1B = 0x3D09; // Compare value is 15625
OCR1A legt den Top-Wert beim CTC-Mode fest, nicht OCR1B.

Und so nebenbei: der korrekte Wert wäre 15624.

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, erstmal Danke für deine Antwort. Im AVR-Studi ist der at90can 
eingestellt, das Makefile hat das AVR-Studi erstellt. Was mir aber 
aufgefallen ist beim debuggen mit dem JTAG Ice mkII, das im SREG das 
I-Bit nach der ISR nicht wieder gesetzt ist.

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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'.

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.