www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Beenden eine while(1)-schleife in einer Interruptroutine


Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo Leute
ich bin dabei eine C funktion zu  implementieren
Das Programm ist in mehrere Routine aufgeteilt.
Die erste Routine soll abfaufen bis Zeichen  zur Übergang zur nächte 
kommt.
ich habe mir gedach in der Erste Routine eine while(1) schleife zu 
setzen und eine Interrupt für die nächste Routine zu implementieren.
Nun  so weiß ich nicht wie  oder ob es machbar eine while schleife 
innerhalb einer Interruptfunktion zu unterbrechen  und in die nächte 
einzuspringen.

Hat jemand eine Idee  wie diese machbar ist  ?  oder eine andere 
Möglichkeit vorzuschlagen?

Ich wäre für jeden Beitrag bankbar.
Karl

Autor: Agro_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So macht man es sicher nicht, warum setzt du nicht in deiner ISR einen 
Merker und wechselst daraufhin zur nächsten Routine. ISRs sollte man 
immer so kurz wie möglich halten.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie eine Merker???
ich verstehe nicht. kannst du mal eine kurze beispiel zeigen

Autor: Mandrake (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bau ein Switch-Case in deine while(TRUE)-Schleife und schalte in deiner 
ISR einfach die switch-variable um. So einfach ist das...


Gruß

Mandrake

Autor: heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau dir mal das Konzept von "Finite State Machines" (fsm, oder in dt. 
Endliche Automaten) an.

br
heinz

Autor: karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja    aber ich  möchte diese auf Sofware-basis realisieren.


danke

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So macht man das für gewöhnlich:
ISR (WHATEVER) {
  marker++;
}

main:

while (1) {
  switch(marker) {
    case 1: bla; break;
    case 2: bla2; break;
    case 3: bla3; break;
    default: break;
}

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
} nach dem switch vergessen.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Interrupt

Autor: karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Interrups laufen nicht über die selbe Taste  deswegen  kann schlecht 
unter Switsch   gemach werden.

Jede interrupt hat sein Erzeuger(taste).

so meine  ich :


void Einspritzen(void)

{
  while(1)
  {
    // do many things
  }

}

void vorbereitung(void)
{
  while(1)
  {
   //do many things
   }

}


int main()
{
vorbereitung();
einspritzen();
.
.
.

}

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
we  soll dann  zum beispiel eine Interrup  sein, die die 
Vorbereitungsfunktion beendet und die Einspritzungsfunktion startet 
aussehen.

danke.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void Einspritzen(void)

{
  while(1)
  {
    // do many things
    if (flag_end_einprizen) break;
  }

}

void vorbereitung(void)
{
  while(1)
  {
   //do many things
   if (flag_end_vorbereitung) break;
   }

}

//globale variable

char flag_end_vorbereitung;
char flag_end_einprizen;

int main()
{
vorbereitung();
einspritzen();
.
.
.

}

ISR (whatever)
(
     if (bedingung) flag_end_vorbereitung =1;
)

Autor: Hans Fanic (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

aus einer while(1) Schleife kommst Du nur noch über die brutalo Methode 
"gehe zurück zu Los, ziehe keine 4.000" ein. Los ist in diesem Fall 
RESET.

Wenn Du aus einer Schleife wieder rauskommen willst must Du schon als 
Abruchbedingung eine Variable setzen.

Hans

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

Bewertung
0 lesenswert
nicht lesenswert
Was du da hast ist doch Unsinn.
Da benutzt mn doch keine Endlos-while Schleifen nur um sie dann mit 
Gewalt abzuschiessen.

Dafür benutzt man Schleifen, die von einer Bedingung abhängen. Welche 
das sind musst du entscheiden.
Aber im Grunde

void vorbereiten()
{
  while( !vorbereitung abgeschlossen )
    mache vorbereitungsarbeit
}

Jetzt bist du drann. Woran kann man erkennen, dass die Vorbereitung 
abgeschlossen ist?
(Selbiges auch für die anderen Funktionen)

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jetzt  ist  mir was aus verschiedene Posten aufgefallen. ich mache eine 
While mit Bedingung.  und in der ISR setze ich die Bedingung zu 1.  Dann 
brich die Whileschleife ab und läuft normal weiter in die andere 
Funktion.


Ich denke so geht.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so  habe ich mir das nun vorgestellt:




ISR (einsptz)
(
     arbeit_ende=1;
)


ISR (vorber)
(
     wasser=1;
)


void vorbereitung(void)
{
  while(arbeit_ende)
  {
   //do many things

   }

}


void Einspritzen(void)

{
  while(wasser)
  {
    // do many things

  }

}

.
.
.


Was meint ihr .  ich kann  das nun   nicht debuggen , aber ist plausibel 
oder ??


lg
Karl

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

Bewertung
0 lesenswert
nicht lesenswert
Karl schrieb:

> Was meint ihr .  ich kann  das nun   nicht debuggen ,

Warum nicht?

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo wird arbeit_ende = 0 gesetzt, damit es nicht weiter ausgeführt wird 
wenn wasser = 1?

Kannst Du bitte mal deine Leertaste entprellen.   Das ist fürchterlich 
mit den  vielen   Leerzeichen  .

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach nööön ich habe ein Fehler gemacht

Verzeihung ich meinte in der ISR die variablen zu Null(Wasser=0 und 
arbeits_ende=0) setzen damit die whilen abbrechen.

>Kannst Du bitte mal deine Leertaste entprellen.   Das ist fürchterlich
>mit den  vielen   Leerzeichen  .

Ok ich bemühe mich die Leezeichen in griff zu bekommen.

lg
Karl

Autor: Roland Praml (pram)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
noch wichtig, die Variablen im Interrupt und in der Schleife müssen als 
"volatile" deklariert werden

Gruß
Roland

Autor: stefan Konrad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute

mir ist was änhliches am brennen.

in der Schleife , die ich abbrechen will, warte ich auf 3 daten per 
Pollin der UART  (receive).
d h bei einem drduck an dem Taster würde ich zwar die ISR laufen lassen 
aber das Programm wird beim Rückker auf das Ursprungliche warten zurück 
kommen und ewig verhaaren.

ich schliesse mich als Beispiel an dem Code von Karl
 
volatile unsigned int arbeit_ende=0;
volatile unsigned int wasser=0;
ISR (einsptz)
(
     arbeit_ende=1;
)
 
 
ISR (vorber)
(
     wasser=1;
)
 
 
void vorbereitung(void)
{
  while(!arbeit_ende)
  {
   while ( !(UCSR0A & (1<<RXC0)) );
/* Get and return received data from buffer */
x=UDR0;
   while ( !(UCSR0A & (1<<RXC0)) );
/* Get and return received data from buffer */
y=UDR0;
   while ( !(UCSR0A & (1<<RXC0)) );
/* Get and return received data from buffer */
z=UDR0;
 
   }
 
}
 
 
void Einspritzen(void)
 
{
  while(!wasser)
  {
    // do many things
 
  }
 
}
 
 
int main()
{
while(1)
{
vorbereitung();
 
Einspritzen();
 
}
 
}

Aber das möchte, dass es nach dem Interrupt zu der Funtion Einspritzen() 
springt und die Kommunikation wieder initialisiert so dass es auf keine 
Zeichen mehr wartet.

vieleicht hat eine ein Idee.

Danke

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst nicht in einen While bereich hinein springen. Machs mit Goto:

beginn:
.
.
.

schleife1:
    tuh irgendwas;
    if (taster2) goto schleife2;
goto schleife1;

.
.
.

schleife2:
    tuh irgendwas;
    if (taster1) goto schleife1;
goto schleife2;

.
.
.

goto beginn;

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
NEEEEEIIIIIIIIIN!
Es geht auch ohne ver***** goto!!!

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum einfach, wenns auch kompliziert geht :c)

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

Bewertung
0 lesenswert
nicht lesenswert
Das sieht nur auf den ersten Blick einfach aus.
Oft verwandelt sich diese 'Einfachheit' ganz schnell in einen Bumerang, 
der auf einen zurückschlägt.

Das Beispiel hier schreit doch schon förmlich danach, dass man die in 
der ISR gesetzten Flags benutzt!

Autor: gastlich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Goto in einem c-programm ???

leute, leute ... das geht unter "ganz böse", sollte mann vermeiden ...

wegen den zeichen an der UART:

warum empfängst du die zeichen nicht auch per interrupt? dannn 
bräuchtest du die while() nicht.

innerhalb der uart_rx ISR in einen buffer schreiben und diesen zu den 
richtigen zeiten entweder auswerten oder löschen ...

gruss Claudio

Autor: uart (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ich hab da mal was vorbereitet:
#define maxstrlen 10
...
volatile char string[maxstrlen+1];
volatile uint8_t str_complete;
volatile uint8_t str_count;
...
ISR(USART_RXC_vect)
{
    unsigned char buffer;

    // Daten aus dem Puffer lesen
    buffer = UDR;
  // Daten werden erst in string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
    if (buffer!='\n' && buffer!='\r' && str_count<maxstrlen-1){ //&& str_complete!=0) {
    string[str_count]=buffer;
    str_count++;
  } else {
    if (buffer!='\n' && buffer!='\r'){
      string[str_count]=buffer;
      str_count++;
    }
    string[str_count]='\0';
    str_complete=1;
  }
}

Im Hauptprogramm fragst du einfach zyklisch ab ob str_complete=1 ist und 
holst dir die Zeichenkette aus string. Du darfst natürlich das 
Rücksetzen der Variablen nicht vergessen.

PS an alle Nörgler: das ist nur ein Vorschlag

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da haben sich schon zwei gegen da "goto" ausgesprochen. Was ist so 
schlimm daran? Im Assembler heisst der Befehl JMP oder RJMP und und wird 
sehr häufig verwendet... Klärt mich mal auf... so als Neben-Topic...

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Igor Ebner (anfaenger69)

>Da haben sich schon zwei gegen da "goto" ausgesprochen. Was ist so
>schlimm daran?

Es führt meist zu Sphagetticode. Und es ist in C praktisch unnötig, von 
gaaaaaaaanz wenige Ausnahmen mal abgesehen, wo man es als Vereinfachung 
nutzen KÖNNTE!
Wird aber praktisch nie gemacht, denn man kann jeden Programmablauf 
sauber duch die normalen Konstrukte if, for, while, Switch abbilden.

> Im Assembler heisst der Befehl JMP oder RJMP und und wird
>sehr häufig verwendet...

Auch der Compiler nutzt die, ist auch OK. Aber sinnvollerweise nur, um 
eben die oben genannten Konstrukte zu generieren, welche dann sauber 
sind. Gleiches sollte man auch von hand in Assembler tun und solche 
sauberen Konstruktionen schreiben. Wilde Sprünge quer durch die Botanik 
gibt es auch nicht in einem sauberen Assemblerprogramm!

MfG
Falk

Autor: I. E. (anfaenger69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahhhh, OK... danke Dir... back to topic :c)

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

Bewertung
0 lesenswert
nicht lesenswert
Igor Ebner schrieb:
> Da haben sich schon zwei gegen da "goto" ausgesprochen. Was ist so
> schlimm daran?

Eine Analogie:
Man kann seine Kabel einfach zusammenknüdeln und in eine Kiste 
schmeissen. Man kann aber auch die Kabel vorher sauber aufrollen und die 
Rollen so sichern, dass sich in der Kabellade keine Rolle mit einer 
anderen verheddert.

Autor: stefan Konrad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok danke für Anrregungen.

gibt es nicht eine Möglichkeit es zu machen ohne ein ISR bei RX-Uart zu 
nutzen?
Denn mommentan habe ich das gesamte Programm übernommen und es ist 
überrall mit Pollin implementiert.

Und wenn ich es mit ISR machen sollte(aufwendig den gesamten Code zu 
fummeln, na ja wenn nicht anders geht...), die Daten sind keine Strings 
sondern Bytes-Pakette  genauso wie ich es oben in meiner Vorgehensweise 
dargestellt habe.   Wie soll dann nun ihr ISR aussehen?

danke

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

Bewertung
0 lesenswert
nicht lesenswert
Man könnte zb
void vorbereitung(void)
{
  while(!arbeit_ende)
  {
    while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
     ;
    /* Get and return received data from buffer */
    x=UDR0;

    while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
      ;
    /* Get and return received data from buffer */
    y=UDR0;

    while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
      ;
    /* Get and return received data from buffer */
    z=UDR0;
  }
}


Man könnte aber auch den immer gleichen Teil in eine eigene Funktion 
rausziehen und so auf einfache Art die Fehlbelegung von y oder z 
verhindern.
uint8_t readValue( uint8_t * pVal )
{
  while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
    ;

  if( arbeit_ende )
    return FALSE;

  *pVal = UDR0;
  return TRUE;
}

void vorbereitung(void)
{
  while(!arbeit_ende)
  {
    if( !readValue( &x ) )
      return;

    if( !readValue( &y ) )
      return;

    if( !readValue( &z ) )
      return;
  }
}

Möglichkeiten gibt es genug, ohne auf einen goto ausweichen zu müssen. 
Was in der jeweiligen Situation vernünftig ist und was nicht, hängt zwar 
immer von den Umständen ab, aber ein goto ist selten vernünftig (und 
wenn dann nur in ganz bestimmten Situationen die hier aber nicht 
vorliegen).

Autor: stefan Konrad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Man könnte zb

C-Code

while(!arbeit_ende)
  {
    while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
     ;
    /* Get and return received data from buffer */
    x=UDR0;



danke Karl,
diese Vorgehensweise habe ich auch versucht und es kalpptauch nicht.
Auch die Simulation auf dem Board hat nicht geklappt. an der Schleife 
bleibt es bei der simulation hängen und es kann keine Pins mehr gesetzt 
werden.

Bei dem Test auf dem wirklichen System läuft das Programm nicht weiter.
Ich habe schon alle mögliche Kombination durchgeführt, aber ohne erfolgt
•
while(!arbeit_ende)
  {
    while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
     ;
    /* Get and return received data from buffer */
    x=UDR0;
.
.
.

//-------kombination 2-------------------------
while(!arbeit_ende)
  {
    while ( !arbeit_ende & !(UCSR0A & (1<<RXC0)) )
     ;
    /* Get and return received data from buffer */
    x=UDR0;
.
.
.
//----------kombination 3----------------------------------

while(!arbeit_ende)
  {
    while ( (!arbeit_ende) && (!(UCSR0A & (1<<RXC0))) )
     ;
    /* Get and return received data from buffer */
    x=UDR0;
.
.
.


der Schlüsselname ist diese "arbeit_ende". weiss nur nicht wie ich es am 
besten gleichzeitig mit deAbfrage des Empfangsdatens verknüpfen kann.

danke

Autor: freak (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich muss mir das   offline debugen

Autor: stefan Konrad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
übrigens

arbeits_ende ist in der main.c  als globalvariable und volatile 
deklariert. in der anderen ".c" wo es verwendet wird, wird er als : 
extern volatile ... arbeits_ende.

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.