www.mikrocontroller.net

Forum: Compiler & IDEs Abarbeitung nach Interrupt INT0


Autor: INT-0-8-15 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebe Leute!

Ich habe hier ein einfaches Programm, welches nach dem Einschalten des 
Controllers erstmal nur ein Ampellicht geben soll.
Sobald INT0 aktiv wird (Taster gedrückt wird), so soll die 
Interrrupt-Routine (ISR) ausgeführt werden. Das ist dann einfach ein 
Blinklicht der Ampel auf allen 3 LEDs.
Sobald ich den Taster erneut drücken möchte, soll wieder die normale 
Ampelsteuerung (Rot-Rotgelb-Grün--Gelb-Rot) funkionieren, usw.

Wie realisiere ich das??

Hier der Code:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>



ISR (INT0_vect)        // Interrupt-Vektor-Service-Routine -> was passiert, wenn Interrupt ausgelöst wird?
{
  while(1)
  {
      PORTB = 0x38;
      _delay_ms(10);
      PORTB = 0;
      _delay_ms(10);  
  }
  
}


int main (void)
{
  
  DDRB = 0x38;    


  MCUCR |= (1<<ISC01);
  MCUCR &= ~(1<<ISC00);
  GIMSK |= (1<<INT0);     // fallende Flanke an INT0 erzeugt Interrupt

  
  sei();            // Interrupts scharf schalten (aktivieren)

  while(1)
  {
    PORTB = 0x20;
    _delay_ms(30);
    PORTB = 0x30;
    _delay_ms(10);
    PORTB = 0x08;
    _delay_ms(30);
    PORTB = 0x10;
    _delay_ms(10);
  }  
  return 0;
}


Vielen Dank!

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Interrupt-Routine wird nie mehr verlassen. Da beim Eintritt in die 
Routine das I-Flag gelöscht wird, werden bis zum Verlassen keine 
weiteren Interrupts behandelt.
Ergo: Aufgehangen.

Endlosschleifen und Delays in Interruptroutinen sind überdies eh nich so 
prickelnd.

Autor: Detlev T. (detlevt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da mechanische Taster prellen, ist das mit dem Interrupt keine gute 
Idee. Hier im Forum gibt es diverse Routinen zum Entprellen per 
Software, die du dafür nutzen kannst. Die Ergebnisse fragst du dann 
einfach in der Hauptschleife ab.

Gruß, DetlevT

Autor: Magnetus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal nebenbei bemerkt:

Dir ist schon klar, dass bei deinem Programm eine komplette Ampelphase 
nur 90 Millisekunden dauern würde?

Gruß,
Magnetus

Autor: INT-0-8-15 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das mit der Ampelphasenlänge ist mir bewusst, da ich das Programm nur 
simuliere und momentan die "virtuelle Taktfrequenz" zu niedrig wäre um 
nicht stundenlang auf einen "Signalwechsel" warten zu müssen. Deshalb 
hab ich die "delay-Zeit" auf nur 30 ms gesetzt.

Vom Entprellen der Taster natürlich abgesehen, mir gehts nur darum, wie 
ich aus der Interrupt-Funktion wieder herauskomme.


Gruß

Autor: docean (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
INT-0-8-15 schrieb:
> mir gehts nur darum, wie
> ich aus der Interrupt-Funktion wieder herauskomme.

indem du dort den Pin vom Taster abfragst? statt while(1)

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Grundgedanke scheint, der Beschreibung entsprechend, gewesen zu 
sein, das das Programm nach dem Tastendruck in einer Sondersituation 
(alle Lichter blinken) ist.

So hast Du aber die Beschreibung der Funktion zu direkt in ein Programm 
umgesetzt.

Zwar soll ein Interrupt die Behandlung von asynchronen Ereignissen 
ermöglichen, aber das heisst nicht, das er auch unmittelbar zur Trennung 
von Betriebsarten dient, d.h. das in main das "normale" Programm abläuft 
und im Interrupt das "besondere" Programm.

Die zwei verschiedenen Abläufe werden beide in main beschrieben. 
Lediglich die Umschaltung zwischen den beiden Abläufen erfolgt im 
Interrupt. Das bedeutet im allgemeinen das setzen einer (volatile) 
Variable im Interrupt, die dann in main abgefragt wird. Passenderweise 
an einer Stelle bei der sinnvolle Übergänge zwischen den Betriebsweisen 
möglich sind.

Was hier über Tastenentprellung gesagt wurde ist dennoch zusätzlich zu 
beachten.

Viel Erfolg

Autor: INT-0-8-15 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> indem du dort den Pin vom Taster abfragst? statt while(1)

Dann würde der aber doch nur ein einziges Mal das Blinken blinken 
lassen, oder?
ISR (INT0_vect)        // Interrupt-Vektor-Service-Routine -> was passiert, wenn Interrupt ausgelöst wird?
{
  if(PINB == wert)
  {
      PORTB = 0x38;
      _delay_ms(10);
      PORTB = 0;
      _delay_ms(10);  
  }
  
}


Wäre das nicht doppelgemoppelt? Weil dass der PIN gedrückt wurde, ist ja 
sicher, sonst wäre er erst garnicht in die ISR-Routine gekommen, 
richtig?

Gruß

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

Bewertung
0 lesenswert
nicht lesenswert
INT-0-8-15 schrieb:

> Wäre das nicht doppelgemoppelt? Weil dass der PIN gedrückt wurde, ist ja
> sicher, sonst wäre er erst garnicht in die ISR-Routine gekommen,
> richtig?

Schon.
Aber deine Frage war ja: wie komme ich aus der ISR wieder raus, wenn der 
Taster losgelassen wird. Und diese Lösung würde realsieren: Solange die 
Taste gedrückt ist, bleibt das Programm in dieser Schleife hängen.

Vielleicht ist dir auch gar nicht bewusst, dass diese Abfrage das hier 
realsiert:

* solange eine Taste gedrückt ist

und nicht

* wenn eine Taste gedrückt wurde, mache einmal


Aber sei gewarnt: Es ist trotzdem die falsche Lösung.
Die richtige Lösung besteht darin, wie weiter oben schon angesprochen, 
dass deine Hauptschleife 2 Modi hat, die per Variable ausgewählt werden. 
In der ISR wird dann einfach nur der andere Modus ausgewählt, in dem die 
Variable entsprechend gestellt wird.

Auf solche nicht absehbar langen Schleifen in einer ISR solltest du dich 
erst gar nicht einlassen.

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.