Interrupt Problem bei Rücksprung (While und If-Schleifen)

OP #1368455
Lesenswert?

Moin,
mein Display funktioniert jetzt wunderbar, ich hab aber jetz noch ein 
Problem mit den Interrupts, wo ich auch nicht mehr weiter weiss.

Und zwar soll mein Programm (Phasenabschnittsteuerung mit wählbaren Ein- 
und Auschaltwinkel) bei jedem Nulldurchgang einen Interrupt starten 
(ext. Zero Point Detector), der wiederum einen Timer Interrupt einstellt 
und aktiviert. Beide Interrupts funktionieren auch tadellos jedoch 
werden bei den Rücksprungen aus den Interrupts die jeweiligen If- und 
While Schleifen an dem das Programm unterbrochen wurde bei dem 
Rücksprung übersprungen

Z.B:
1
    if(TASTE_M)
2
    {

Ursache: Wenn ich beim Debuggen vor dem Sprung die Adresse im Programm 
Counter ansehe lautet sie 0x72. Bei dem Sprung in den Interrupt wird sie 
auf 0x74 erhöht. Daher wird die Schleife übersprungen. Ändere ich den 
Rücksprungwert auf 0x72 spring das Programm wieder dahin wo es soll und 
die If-Bedingung wird wieder korrekt abgefragt.

Gibt es eine Einstellung mit der man die Rücksprungadresse ohne eine 
Erhöhung im Stack speichern kann?

hier mal ein Auszug aus meinem Programm:
1
int main()
2
{
3
...  
4
TCCR1B=0x02;
5
TIMSK=0x04;
6
//HW-Interrupt einstellen und aktivieren
7
MCUCR=0x0A;    //Int. Bedingungen einstellen
8
GIMSK=0x40;    //Int0 aktivieren
9
sei();      //HW-Int aktivieren
10

11
//Hauptprogrammschleife
12
  while(1)
13
  {
14
    if(TASTE_M)
15
    {
16
      merker=0;
17
      zeile = Zeichne_Pfeil(zeile);
18

19
  do{
20
  }while(TASTE_M);
21
  ...
22
    }
23
  return(0);
24
}
1
void INT0_vect(void)
2
{
3
alpha=0x01;
4
...
5
TCNT1H=0xFF; //Timerwert für Timer1
6
TCNT1L=0x38; //Timerwert für Timer1
7
sei();
8
}
1
void TIMER1_OVF_vect(void)
2
{
3
alpha++;
4
TCNT1H=0xFF;
5
TCNT1L=0x38;
6
...
7
sei();
8
}

MfG
Matthias
#1368476
Lesenswert?

Matthias S. schrieb:
> Das sei() ist ja nötig um die Interrupt wieder zu aktivieren
> (SREG=0x80). Nach jedem Interrupt wird SREG zurückgesetzt und wenn ich
> das sei() nicht mache wird der Interrupt nur einmal ausgeführt.

Welcher Compiler überhaupt? GCC? Dann sind die Interrupt-Routinen nicht 
richtig definiert, was auch der Grund dafür ist, dass du 
fälschlicherweise ein sei am Ende brauchst (weil deine Funktionen so 
nämlich nur ein ret statt eines reti am Ende haben).
OP #1368515
Lesenswert?

Stefan Ernst schrieb:
> Zusatz:
> Das dürfte auch der Grund für das beobachtete Fehlverhalten sein, denn
> die Interrupt-Funktionen sichern so auch die Register nicht korrekt.

Das hab ich anfangs auch gedacht, aber der Inhalt vom Stackpointer zeigt 
während der Interruptroutine schon auf den nächsten Befehl.

PC
0x72   if(TASTE_M)      //-> Sprung in den Interrupt (SP=0x74)
       {
0x74     i++;           //<-Rücksprung aus dem Interrupt

Das sei() hab ich erstmal wieder weggenommen.
#1368538
Lesenswert?

Matthias S. schrieb:

> Das hab ich anfangs auch gedacht, aber der Inhalt vom Stackpointer zeigt
> während der Interruptroutine schon auf den nächsten Befehl.

Das ist völlig normal und korrekt so. Wenn dein Programm sich nicht so 
verhält, wie von dir erwartet, hat das damit rein gar nichts zu tun. 
Hast du die Interrupt-Funktionen denn inzwischen mal korrigiert?
#1368546
Lesenswert?

Matthias S. schrieb:
> (ext. Zero Point Detector), der wiederum einen Timer Interrupt einstellt
> und aktiviert. Beide Interrupts funktionieren auch tadellos

Wobei ich mich trotzdem immer noch wundere, wieso deine Funktionen (den 
das sind keine Interrupt Handler, die müssen spezielle Funktionsheader 
haben) überhaupt aufgerufen werden.
OP #1368551
Lesenswert?

Ja, dank den Hinweisen von 
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html 
funktionieren meine Int-Routinen nun. ich hab sie jetzt wie folgt 
umdeklariert:
1
ISR(INT0_vect)
2
{
3
  alpha=0x01;
4
  if(alpha==alpha_ein)
5
  {
6
    STELLER_2_LOW();
7
    STELLER_1_HI();
8
  }  
9
  TCNT1H=0xFF;
10
  TCNT1L=0x38;
11
  //reti();
12
}
13

14
ISR(TIMER1_OVF_vect)
15
{
16
  alpha++;
17
  TCNT1H=0xFF;
18
  TCNT1L=0x38;
19
  if(alpha==alpha_ein)
20
  {
21
    STELLER_2_LOW();
22
    STELLER_1_HI();
23
  }
24

25
  if(alpha==alpha_aus)
26
  {
27
    STELLER_1_LOW();
28
    STELLER_2_HI();
29
  }
30
}

Vielen Dank und MfG
Matthias
OP #1368558
Lesenswert?

Karl heinz Buchegger schrieb:
> Matthias S. schrieb:
>> (ext. Zero Point Detector), der wiederum einen Timer Interrupt einstellt
>> und aktiviert. Beide Interrupts funktionieren auch tadellos
>
> Wobei ich mich trotzdem immer noch wundere, wieso deine Funktionen (den
> das sind keine Interrupt Handler, die müssen spezielle Funktionsheader
> haben) überhaupt aufgerufen werden.

Das hab ich mich anfangs auch drüber gewundert aber es hat ja bis auf 
den Rücksprung vor div. Schleifen und If-Abfragungen funktioniert
#1368563
Lesenswert?

Karl heinz Buchegger schrieb:
> Matthias S. schrieb:
>> (ext. Zero Point Detector), der wiederum einen Timer Interrupt einstellt
>> und aktiviert. Beide Interrupts funktionieren auch tadellos
>
> Wobei ich mich trotzdem immer noch wundere, wieso deine Funktionen (den
> das sind keine Interrupt Handler, die müssen spezielle Funktionsheader
> haben) überhaupt aufgerufen werden.

Weil auch ohne das "ISR" der Name der Funktion vom Präprozessor in die 
Vektornummer übersetzt wird.
#1368565
Lesenswert?

Keine Sorge, da wäre später noch viel mehr merkwürdiger Blödsinn 
passiert, wie beispielsweise Variablen die zufällig und mysteriös ihren 
Wert ändern. Der Unterschied zwischen Funktionen und ISRs beschränkt 
sich nicht auf das I-Flag und die Korrektur der Return-Adresse.

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