Forum: Compiler & IDEs Atmega8 - Timer1 Interrupt-Behandlung wird nicht beendet


von Hans M. (l_phoenix0009)


Lesenswert?

Hallo,

ich lerne gerade die Programmierung von Microcontrollern. Bei der 
Implementierung eines Sekundenzählers (Timer1) mittels Interrupt stoße 
ich auf folgende Problematik:

Der Timer 1 soll einen Interrupt bei einem Buffer-Overflow auslösen. Der 
Zähler wird mit Prescaler (1024) und einem Startwert parametriert. Die
Interrupt-Serviceroutine soll den Timer stoppen und die Endlosschleife 
beenden.

Hier der Code-Ausschnitt:
1
#include <avr/io.h>
2
#include <stdio.h>
3
#include <avr/interrupt.h>
4
5
(...)
6
7
int wait(int i)
8
{
9
  
10
  for (int j = 0; j<= i; j++)
11
  {
12
    TCCR1A=0x00; // Normal port operation
13
    TCCR1B |= (1 << CS12) | (0 << CS11) | (1 << CS10);   
14
    TCNT1=61936; // Startwert des Timers
15
    TIMSK|=0x04; // Timer1 Overflow Interrupt = Enable
16
    
17
      
18
    while(sekunde=1)
19
    {
20
      //warten auf Interrupt
21
    }
22
                     /* Diese Stelle wird nie erreicht!*/    
23
    sekunde=1;
24
  }  
25
  
26
  
27
  return(0);
28
  
29
}
30
31
ISR(TIMER1_OVF_vect)
32
{
33
  TCCR1B=0x00;    //Timer:stop!
34
  TIMSK&=~(0x04); //Interrupt löschen
35
  sekunde=100;
36
  
37
}
Problem: Der Interrupt wird ausgelöst, die ISR wird bearbeitet. Nachdem 
die ISR abgearbeitet wird, wird a.) die ISR nicht verlassen b.) die 
(Endlos-) Schleife nicht beendet.
Da Ich nun schon mehrere Versuche (eine Variante ist oben zu sehen) 
unternommen habe, viele Code-Beispiele gesichtet habe, das Manual 
gequält habe aber meinen Fehler nicht sehe, bitte ich um Hilfe :-) .
Vielen Dank im Voraus!!!

von troll (Gast)


Lesenswert?

>while(sekunde=1)
Guck dir mal den Unterschied zwischen Vergleich und Zuweisung an.

von troll (Gast)


Lesenswert?

Btw, ich glaskugele mal und tippe auf ein fehlendes volatile. Wie 
ist sekunde definiert?

von Hans M. (l_phoenix0009)


Lesenswert?

Hi, sorry sekunde ist mit "volatile int sekunde" deklariert. Die 
(Endlos-) Schleife wird auch mit folgender Bedingung nie verlassen: 
while(1) {}

PS: Vielen Dank für die schnellen Antworten!!! :-)

von troll (Gast)


Lesenswert?

Hans Meier schrieb:
> Hi, sorry sekunde ist mit "volatile int sekunde" deklariert.
Passt.


> Die
> (Endlos-) Schleife wird auch mit folgender Bedingung nie verlassen:
Äh ja natürlich wird sie bei while(1) nicht verlassen, aber das ist doch 
nicht das was du willst?!

Also zusammengefasst: Das Problem ist dass das Programm nach der ISR 
nicht weiterläuft richtig?? Das könnte dann ein Problem mit dem Stack 
oder so sein, aber daran glaube ich erstmal nicht.

von troll (Gast)


Lesenswert?

(Ach und: Bei int brauchst du atomaren Zugriff)

von Hans M. (l_phoenix0009)


Lesenswert?

Du hast natürlich recht mit While{1}. Habe mich verm. schon etwas zu 
lange mit der Problematik beschäftigt.

Zu Punkt2:
Richtig. Die Interrupt-Routine wird bearbeitet bis zum Ende. Danach wird 
entweder die Interrupt-Routine nicht beendet oder die Schleife in der 
Methode wird nicht verlassen.

Zum restlichen Code:

Der Programm-Ablauf sieht es vor, eine gewisse Zeit (i-Sekunden) zu 
warten, bevor die nächste Methode abgearbeitet wird (Methode wait(int 
i). Die Methode wait zählt Sekunden, bis der Zielwert erreicht ist. Bei 
der ersten Sekunde stoppt die Zeitmessung, da der Programmablauf nicht 
fortgesetzt wird.
Ist diese Zeitperiode vorrüber, soll in die aufrufende Methode 
"gesprungen" werden.

von xfr (Gast)


Lesenswert?

Hans Meier schrieb:
> while(sekunde=1)

Falls es noch nicht klar geworden ist, das muss heißen:
1
while(sekunde==1)

Die Timer-Initialisierung brauchst Du nicht jedes Mal in der Schleife 
machen. Das reicht einmal zu Beginn des Programms.

Und ganz allgemein: Was Du da vorhast, sieht nach Unsinn aus. Statt der 
wait-Funktion kannst Du auch einfach delay_ms() benutzen. Der Timer ist 
dafür da, dass man eben kein Polling mehr betreiben muss à la:
1
while (!irgendwas) {
2
  // warte bis irgendwas eintritt
3
}

von troll (Gast)


Lesenswert?

Hans Meier schrieb:
> Danach wird
> entweder die Interrupt-Routine nicht beendet oder die Schleife in der
> Methode wird nicht verlassen.
Grmpf! Das ist so gar nicht das selbe. Bei 1. ist der Fehler irgendwo in 
den Innereien zu suchen, bei 2. ist nur der Code Müll. s.o/u

von Hans M. (l_phoenix0009)


Lesenswert?

Hi, das fehlende "=" ist bereits korrigiert, genauso wie das "volatile 
int sekunde" => "int sekunde"...

Erst nachdem ich nun die Platine nochmals stromlos gemacht, die IDE 
geschlossen und neu geöffnet und erneut überspielt habe, funktioniert es 
nun.

Vielen Dank für die Hifle!

von troll (Gast)


Lesenswert?

Hans Meier schrieb:
> genauso wie das "volatile
> int sekunde" => "int sekunde"...
Das volatile war schon richtig...

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.