Probleme mit der Endlosschleife

OP #216414
Hallo Leute !

Ich benutze in meiner Main function goto label als Endlosschleife, da
gibt es auch keinerlei Probleme mit dem Timer-Interupt!!! Doch wenn ich
while(1) { } oder for(;;) als Endlos-Schleife benutzte funktioniert der
Timer-Interrupt nicht mehr.
Das Programm verbleibt in der main-Function!! Könnt mir weiterhelfen?
Angehängte Dateien:
Admin Persönliche Seite #216415
Könntest du das bei Gelegenheit etwas lesbarer formatieren? Dann kann
man die Programmstruktur viel leichter erkennen. Schau dir mal ein paar
Beispiele an, und achte drauf entweder nur Tabs oder nur Leerzeichen zu
verwenden, aber nicht beides.

Und das Goto scheint mir so überflüssig wie ein Kropf; das kann man
doch alles ins case-Statement packen.
Persönliche Seite #216416
Was soll denn das hier:

switch (phase) {
         case 1: goto label_1; break;
         case 2: goto label_2; break;
     case 3: goto label_3; break;
     case 4: goto label_4; break;
     case 5: goto label_5; break;
     case 6: goto label_6; break;
          }


Man kann das ganze sicherlich noch unübersichtlicher programmieren,
aber was bitte hat goto in einem switch-Statement verloren?
Gast #216418
Hi Tom,
also ich würde mal wie üblich auf Stacküberlauf tippen.
Einfach mal HW und SW Stack höher setzen.
Kann auch sein, daß die Interruptroutine einfach zu lange braucht.
Miss mal die Zeit nach, die die IR Routine braucht.
Als Problemlösung schlanker und schneller machen, am besten in
Assembler.

Viel Erfolg
lg Ralf
Gast #216420
Hallo Tom

Da Dein Programm nichts anderes macht oder tun muss, als glegentlich
den Code der Interrupt Routine auzuführen, würde ich den Code der ISR
in die Hauptschleife verfrachten.

Mit einem Timer würde ich eine Uhr realisieren (z.B. long SysTicks).
Diese liesse sich dann einfach laufend abfragen.

Dein Programmode wird dadurch auch viel robuster.

Mir scheint es nämlich aus so, dass die Ursache für Dein Problem eine
zu komplexe ISR ist.

Beste Grüsse

Gerhard
Eine Ampelsteuerung wäre übrigens ein "schönes" Beispiel für eine
State-Machine. Nach diesem Gesichtspunkt könnte man das Programm auch
sehr gut lesbar machen.
OP #216421
Ich weiß nicht,ob  ihr mein Problem richtig verstanden habt!
Wenn ich in der main-Funktion goto - Schleife einbaue, läuft alles
einwandfrei !

void main(void)  //Hauptprogramm
{
  init();
  loop:
  PORTB = temp;
  PORTD = temp2;
    if bit_is_clear(PINB,7) // ( !(PINB & (1<<PINB7)) )
    {
      temp2 &= ~ (1<< PD1) ; // PD1 wird auf Low
      Taster_gedrueckt = 1; // Taster wurde betätigt
    }
  goto loop;   // Endlosschleife
 }




Verwende ich jedoch ich einen While oder-for Schleife wird die
Interruptroutine nicht aufgerufen!
Gast #216422
Das sieht nach einem Compilerfehler aus.
Um der Sache genau auf den Grund zu gehen müßtest den Code
disassemblieren und den Fehler suchen.
Bei den AVR Compilern kommen leider hin und wieder Compilerfehler vor
und dann geht nur ausprobieren und tüfteln, meine Erfahrung.

lg Ralf
Admin Persönliche Seite #216423
Ein Fehler bei einem so simplen Stück Code ist so unwahrscheinlich dass
man von einem Fehler beim Anwender ausgehen kann, und nach einem Blick
auf dem Code wird der auch schnell klar: Variablen die in
Interruptroutinen und Hauptprogramm verwendet werden müssen als
volatile deklariert werden.

Vermutlich wird goto bei der Optimierung etwas anders behandelt als
eine Schleife, deshalb funktioniert es in dem einen Fall und in dem
anderen nicht.
#216424
Das ist die längste ISR, die ich jemals gesehen habe.

Erinnern tut mich das Programm an eins, das ein Freund vor Jahren
(damals war der 286er richtig gut und teuer...) geschrieben hat. Ihm
war wohl auch die Existenz von Feldern bekannt.

So würde ich es machen:

Ein Feld (aus Konstanten) mit den sechs Phasen erzeugen.
Mit der Timer-ISR einfach den Phaseindex hochzählen, wenn er zu groß
ist zurück auf 0 setzen.
Scheinbar (dank der fehlenden Dokumentation noch schwieriger
herauszufinden) handelt es sich um eine Bedarfsampel, die auf
Tastendruck erst startet.

In der Main wird also einfach die Ampel initialisiert (rot für
Fußgänger, grün für Kfz).
In einer Schleife wird solange abgefragt, ob die Taste gedrückt wurde,
bis sie gedrückt wurde.
Jetzt wird der Timer gestartet. In einer weiteren Schleife wird
geprüft, ob sich der Phasenindex dank eines Timer-Überlaufs geändert
hat Entsprechend wird die Konstante an den Port geschrieben.
Die Schleife wird abgebrochen, sobald der Phasenindex bei der letzten
Phase angekommen ist. Dann landet das Programm wieder in der
"aufdieTastendrück"-Warteschleife.
In der ISR wird der Phasenindex inkrementiert und der Timer-Reload-Wert
neu gesetzt.

Viel Code ist das nicht. Man braucht definitiv kein goto.

Eigentlich sollte man die Benutzung dieses Wortes unter Strafe stellen.
Zuletzt habe ich es gebraucht, als auf dem Apple][ noch ein
Basic-Interpreter arbeitete. Der Rechner verstand auch noch keine
Funktionsaufrufe...
Gast #216428
holla,

is es net so dass ich ne variable volatile setzte wenn se von aussen
(z.B. ein polling eines pins durch einen interrupt) gesetzt werden?

@Tom
Mach die gotos raus, das is wirklich nicht toll.
Du benutzt doch eh schon states warum dann noch goto?


Gruß Andreas
#216429
Variablen, die "von aussen" sichtbar sein sollen, müssen global
vereinbart werden.
Volatile weist den Compiler nur an, die Variable zu übersetzen, auch
wenn er dafür in diesem Moment keine Verwendung sieht. Ist sie nicht
als volatile vereinbart, und der Compiler sieht keine Verwendung, dann
optimiert er sie weg. (Suchfunktion des Forums zum Thema
"volatile").

volatile gehört ja auch nicht zu Standard-C, oder?

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 21 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.