mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik allg. Frage zu Interrupts und Programmablauf (in C)


Autor: Hans Meier (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

so langsam bin ich völlig am verzweifeln, stehe mit dem uC auf
"Kriegsfuss" ;=)
Bevor ich mit was großem weiter mache, muss ich erwst weiter Grundlagen
lernen. Was ein Interrupt ist, was er macht, wer wann die Steuerung
übernimmt ist mir soweit klar. Einzig und allein zur Implementierung
(in C) habe ich eine Frage. Meinetwegen habe ich so etwas:

void main (void)
{
   // Schleife die immer läuft
   while (1)
   {
      // Schleife die nur läuft wenn der Interrupt ausgelöst wurde
      while (interrupt_ausgeloest)
      {
         // mach was :=)
         pause
         Ports lesen
         Ports schreiben
         usw.

         [...]

         interrupt_ausgeloest = 0;
      }
   }
}

void Interruptroutine (void)
{
   interrupt_ausgeloest = 1;
}


Was den Interrupt auslöst ist erstmal egal. Was ich letztendlich haben
möchte: wenn der Interrupt ausgelöst wurde, soll im Hauptprogramm eine
"extra-Schleife" abgearbeitet werden und zwar immer (!) vom Beginn ab
an. Obiges macht das ja fast soweit, nur was passiert wenn der Interrupt
2 mal "schnell" hintereinander ausgelöst wird? Soweit ich das
verstehe, passiert da nichts weiter, die while (interrupt_ausgeloest)
Schleife läuft einfach an der alten Stelle weiter (ok, das
Hauptprogramm wird unterbrochen, die Interruptroutine wird abgearbeitet
und das Hauptprogramm wird an der alten (!) Stelle fortgesetzt (also
nicht wie gewünscht von Beginn an)). Sie beginnt also nicht so wie von
mir gewünscht von vorne.

Wie kann ich dieses Problem lösen? Soll die ganze Interrupt-Schleife in
die Interruptroutine (was passiert dann bei 2 "schnellen"
Interrupts?), kann man die while schleife immer von Anfang an beginnen
(wäre mir am liebsten)?

Freue mich über jeden Tipp, Link, Codeschnipsel...

Gruß,

Hans

Autor: Elektrolurch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if (interrupt_ausgeloest == 1) danach gleich die Variable auf 0 setzen
und dann mit der Portmanipulation fortfahren. Wenn inzwischen der
Interrupt noch einmal auftritt, wird im Hauptprogramm wieder in den
Programmteil verzweigt.

Autor: ...HanneS... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi...

Also wenn der Umgang mit Interrupts unter C wirklich so umständlich und
kompliziert sein sollte, dann werde ich wohl für immer bei Assembler
bleiben.

Da kümmert mich der Int in der Hauptschleife nicht, denn jeder Int hat
seine eigene ISR, die beim Aufruf abgearbeitet wird. Und in dieser kann
man Flags (Bits in einem dafür reservierten Register) setzen, auf die
die Hauptschleife reagieren kann...

Bit- & Bytebruch...
...HanneS...

Autor: Olaf Stieleke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab das vor geraumer Zeit gelernt: Was bei einem IRQ passieren soll,
gehört in den IRQ-Handler, nicht ins Main.

Wäre es nicht also sinnvoller, die Schleife direkt im Interrupt-Handler
ablaufen zu lassen (womit es dann keine Schleife mehr wäre)? Dann würde
sich das Problem mit zwei schnell nacheinander auftretenden IRQ's
nicht stellen (SEI vorausgesetzt).

Darüber hinaus kann der IRQ-Handler ja noch immer ein Flag setzen, das
das Hauptprogramm "wenn es Zeit hat" auswertet.

Autor: Hans Meier (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

erst mal danke für die Antworten.

@Elektrolurch:
bist du dir da sicher? Wenn der Interrupt abgearbeitet wurde, kehrt der
uC doch an seine alte Stelle im Programm zurück, also mitten in die if
Schleife und nicht an den Anfang (bzw. sogar noch davor wo die
Bedingugn geprüft wurde), oder irre ich da gewaltig?

@...HanneS...
Keine Angst, das geht in C ja genauso. z.B. folgendes:
SIGNAL (SIG_INTERRUPT0)
{
    // int 0 ausgelöst
}

SIGNAL (SIG_OVERFLOW1)
{
    // Überlauf 1 ausgelöst
}

SIGNAL (SIG_UART_RECV)
{
    // Empfangen
}
usw.
Es interessiert mich einzig und allein dein Satz "...auf die
die Hauptschleife reagieren kann...". Das ist mein "Problem".

@Olaf Stieleke:
Bis jetzt habe ich immer nur gelesen und gelernt, das eine Interrupt
Routine möglichst kurz/schnell fertig sein sollte. "Leider" muss ich
auch ein paar Takte bei der Abarbeitung warten.

Gruß,

Hans

Autor: Joline (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

Interrupts werden durch bestimmte Ereignisse ausgelöst, z.B.
Timer-Überlauf (passiert, wenn bspw. der 8-Bit-Timer > 255 werden
würde). Auf diese Interrupts kann man reagieren, indem man bestimmte
ISR (Interrupt-Service-Routinen) in sein Programm einbaut, also z.B.

SIGNAL (SIG_OVERFLOW0)
{

}

um mal beim 8-Bit-Timer zu bleiben.

Der Sinn solcher Funktionen liegt nun darin, das gerade laufende
Programm zu unterbrechen (deshalb Interrupt = Unterbrechung), weil eben
was Wichtiges passiert ist und den in der ISR definierten Code
auszuführen. Anschliessend macht das Programm an der Stelle weiter, an
der es unterbrochen wurde.

Ein C-Programm sieht also dann in etwa so aus:

void main (void)
{
   // Schleife die immer läuft
   for (;;)
   {
   }
}

SIGNAL (interruptkennung)
{
    // mach was :=)
    Ports lesen
    Ports schreiben
    usw.

    [...]
}

Pausen (respektive irgendwelche Zählschleifen) sollte man in seinem
Programm möglichst vermeiden. Der Prozessor hat meist genug zu tun, als
sich mit solchen (meist sinnlosen) Dingen aufzuhalten. Dann sind
plötzlich nämlich auch die kleineren unter ihnen ganz schnell.  ;o)

Joline

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.