mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Interrupt Problem bei Rücksprung (While und If-Schleifen)


Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht 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:
    if(TASTE_M)
    {

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:
int main()
{
...  
TCCR1B=0x02;
TIMSK=0x04;
//HW-Interrupt einstellen und aktivieren
MCUCR=0x0A;    //Int. Bedingungen einstellen
GIMSK=0x40;    //Int0 aktivieren
sei();      //HW-Int aktivieren

//Hauptprogrammschleife
  while(1)
  {
    if(TASTE_M)
    {
      merker=0;
      zeile = Zeichne_Pfeil(zeile);

  do{
  }while(TASTE_M);
  ...
    }
  return(0);
}
void INT0_vect(void)
{
alpha=0x01;
...
TCNT1H=0xFF; //Timerwert für Timer1
TCNT1L=0x38; //Timerwert für Timer1
sei();
}
void TIMER1_OVF_vect(void)
{
alpha++;
TCNT1H=0xFF;
TCNT1L=0x38;
...
sei();
}

MfG
Matthias

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lass mal das sei(); am ende er int routinen weg.

Autor: Matthias S. (lecorde)
Datum:

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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein ist es nicht, dafür ist ein reti zuständig, das setzt der Compiler 
selber. (zur not mal im Asselbly nachschauen)

Autor: Stefan Ernst (sternst)
Datum:

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

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zusatz:
Das dürfte auch der Grund für das beobachtete Fehlverhalten sein, denn 
die Interrupt-Funktionen sichern so auch die Register nicht korrekt.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  (While und If-Schleifen)
> die jeweiligen If- und While Schleifen
Es gibt nach wie vor keine If-Schleifen ...
Das einzige was mit If möglich ist, ist eine Abfrage.

> hier mal ein Auszug aus meinem Programm: ...
Hast du irgendwelche asm-Zeilen (Inline-Assembler) in den Programm?

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ich Arbeite mit dem AVR_Studio -> GCC,

bei mir bringt der Befehl reti leider nicht und bei ret schimpft der 
Compiler.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas W. schrieb:

> normalerweise sollte Dein Compiler am Ende der Interuptfunktion den
> Befehl: "reti"   setzen

Außer halt, der Compiler weiß gar nicht, dass es Interruptfunktionen 
sind, so wie in diesem Fall.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matthias S. schrieb:
> Ja, ich Arbeite mit dem AVR_Studio -> GCC,
>
> bei mir bringt der Befehl reti leider nicht und bei ret schimpft der
> Compiler.

Du sollst den auch nicht selber einfügen, sondern die Interrupt-Funktion 
korrekt deklarieren.
http://www.nongnu.org/avr-libc/user-manual/group__...

Autor: Matthias S. (lecorde)
Datum:

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

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wer weiss, vielleicht ist das bei Interrupts immer so. Anderswo (ARM) 
ist das normal. Also mach richtige Interrupt-Handler aus deinen falschen 
Interrupt-Handlern und diskutier nicht mit der Hardware wer Recht hat. 
Die ist garantiert sturer.

Autor: Stefan Ernst (sternst)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nur ne Schätzung:
Es wäre ggf möglich, wenn man die Funktionsadressen selber in die 
Interruptvektoren schreibt.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Interrupt-Leiste ruft bestimmte Namen auf. Wenn die passen hat man 
gewonnen.

Autor: Matthias S. (lecorde)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, dank den Hinweisen von 
http://www.nongnu.org/avr-libc/user-manual/group__... 
funktionieren meine Int-Routinen nun. ich hab sie jetzt wie folgt 
umdeklariert:
ISR(INT0_vect)
{
  alpha=0x01;
  if(alpha==alpha_ein)
  {
    STELLER_2_LOW();
    STELLER_1_HI();
  }  
  TCNT1H=0xFF;
  TCNT1L=0x38;
  //reti();
}

ISR(TIMER1_OVF_vect)
{
  alpha++;
  TCNT1H=0xFF;
  TCNT1L=0x38;
  if(alpha==alpha_ein)
  {
    STELLER_2_LOW();
    STELLER_1_HI();
  }

  if(alpha==alpha_aus)
  {
    STELLER_1_LOW();
    STELLER_2_HI();
  }
}

Vielen Dank und MfG
Matthias

Autor: Matthias S. (lecorde)
Datum:

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

Autor: Stefan Ernst (sternst)
Datum:

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

Autor: A. K. (prx)
Datum:

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

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.