Forum: Mikrocontroller und Digitale Elektronik Probleme mit der Endlosschleife


von Tom K. (tommy)


Angehängte Dateien:

Lesenswert?

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?

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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?

von Tom K. (tommy)


Lesenswert?

Okay an der Formatierung kann sicherlich noch was ändern. Aber was mit
der While-Schleife im main-Program ? Wieso lässt sie kein
Timer-Interrupt zu ?

von Ralf K. (Gast)


Lesenswert?

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

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Mal nichts überstürzen. Für eine Ampelsteuerung ist ganz bestimmt kein
Assembler notwendig.

Tom, setz erst mal die Vorschläge um, dann löst sich das Problem
vielleicht von ganz alleine, und vorher wird sich auch niemand das
Programm genauer anschauen wollen.

von GerhardB (Gast)


Lesenswert?

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.

von Tom K. (tommy)


Lesenswert?

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!

von Ralf K. (Gast)


Lesenswert?

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

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

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.

von Rahul D. (rahul)


Lesenswert?

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...

von Tom K. (tommy)


Lesenswert?

Danke Andreas !

Wenn man die Variablen mit volatile deklariert dann läufts auch mit For
und While-Schleifen !

Tschüss
Tom

von Andreas Fertl (Gast)


Lesenswert?

warum müssen die denn volatile sein?

Gruß Andreas

von Rahul D. (rahul)


Lesenswert?

weil der Compiler sie sonst wegoptimiert.

von Andreas Fertl (Gast)


Lesenswert?

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

von Rahul D. (rahul)


Lesenswert?

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?

von A.K. (Gast)


Lesenswert?

volatile gehört zum Standard.

von Andreas Fertl (Gast)


Lesenswert?

jo :)
gehört dazu.
Ist im K&R Büchlein drinn....

ok das leuchtet ein dass er se wegoptimiert.

Thx.
Gruß Andreas

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.