Beenden eine while(1)-schleife in einer Interruptroutine

Gast #1460137
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
Gast #1460443
Lesenswert?

So macht man das für gewöhnlich:
1
ISR (WHATEVER) {
2
  marker++;
3
}
4

5
main:
6

7
while (1) {
8
  switch(marker) {
9
    case 1: bla; break;
10
    case 2: bla2; break;
11
    case 3: bla3; break;
12
    default: break;
13
}
Gast #1460493
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();
.
.
.

}
#1460554
Lesenswert?

1
void Einspritzen(void)
2

3
{
4
  while(1)
5
  {
6
    // do many things
7
    if (flag_end_einprizen) break;
8
  }
9

10
}
11

12
void vorbereitung(void)
13
{
14
  while(1)
15
  {
16
   //do many things
17
   if (flag_end_vorbereitung) break;
18
   }
19

20
}
21

22
//globale variable
23

24
char flag_end_vorbereitung;
25
char flag_end_einprizen;
26

27
int main()
28
{
29
vorbereitung();
30
einspritzen();
31
.
32
.
33
.
34

35
}
36

37
ISR (whatever)
38
(
39
     if (bedingung) flag_end_vorbereitung =1;
40
)
Gast #1460556
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
#1460566
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)
Gast #1460581
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.
Gast #1460594
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
Gast #1460608
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
Gast #1555196
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
1
 
2
volatile unsigned int arbeit_ende=0;
3
volatile unsigned int wasser=0;
4
ISR (einsptz)
5
(
6
     arbeit_ende=1;
7
)
8
 
9
 
10
ISR (vorber)
11
(
12
     wasser=1;
13
)
14
 
15
 
16
void vorbereitung(void)
17
{
18
  while(!arbeit_ende)
19
  {
20
   while ( !(UCSR0A & (1<<RXC0)) );
21
/* Get and return received data from buffer */
22
x=UDR0;
23
   while ( !(UCSR0A & (1<<RXC0)) );
24
/* Get and return received data from buffer */
25
y=UDR0;
26
   while ( !(UCSR0A & (1<<RXC0)) );
27
/* Get and return received data from buffer */
28
z=UDR0;
29
 
30
   }
31
 
32
}
33
 
34
 
35
void Einspritzen(void)
36
 
37
{
38
  while(!wasser)
39
  {
40
    // do many things
41
 
42
  }
43
 
44
}
45
 
46
 
47
int main()
48
{
49
while(1)
50
{
51
vorbereitung();
52
 
53
Einspritzen();
54
 
55
}
56
 
57
}

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
Gast #1555361
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
Gast #1555383
Lesenswert?

ich hab da mal was vorbereitet:
1
#define maxstrlen 10
2
...
3
volatile char string[maxstrlen+1];
4
volatile uint8_t str_complete;
5
volatile uint8_t str_count;
6
...
7
ISR(USART_RXC_vect)
8
{
9
    unsigned char buffer;
10

11
    // Daten aus dem Puffer lesen
12
    buffer = UDR;
13
  // Daten werden erst in string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
14
    if (buffer!='\n' && buffer!='\r' && str_count<maxstrlen-1){ //&& str_complete!=0) {
15
    string[str_count]=buffer;
16
    str_count++;
17
  } else {
18
    if (buffer!='\n' && buffer!='\r'){
19
      string[str_count]=buffer;
20
      str_count++;
21
    }
22
    string[str_count]='\0';
23
    str_complete=1;
24
  }
25
}

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
Angehängte Dateien:
#1555533
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
#1555704
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.
Gast #1557775
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
#1558802
Lesenswert?

Man könnte zb
1
void vorbereitung(void)
2
{
3
  while(!arbeit_ende)
4
  {
5
    while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
6
     ;
7
    /* Get and return received data from buffer */
8
    x=UDR0;
9

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

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


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.
1
uint8_t readValue( uint8_t * pVal )
2
{
3
  while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
4
    ;
5

6
  if( arbeit_ende )
7
    return FALSE;
8

9
  *pVal = UDR0;
10
  return TRUE;
11
}
12

13
void vorbereitung(void)
14
{
15
  while(!arbeit_ende)
16
  {
17
    if( !readValue( &x ) )
18
      return;
19

20
    if( !readValue( &y ) )
21
      return;
22

23
    if( !readValue( &z ) )
24
      return;
25
  }
26
}

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).
Gast #1570033
Lesenswert?

Karl heinz Buchegger schrieb:
> Man könnte zb

1
C-Code
2

3
while(!arbeit_ende)
4
  {
5
    while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
6
     ;
7
    /* Get and return received data from buffer */
8
    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
•
1
while(!arbeit_ende)
2
  {
3
    while ( !arbeit_ende && !(UCSR0A & (1<<RXC0)) )
4
     ;
5
    /* Get and return received data from buffer */
6
    x=UDR0;
7
.
8
.
9
.
10

11
//-------kombination 2-------------------------
12
while(!arbeit_ende)
13
  {
14
    while ( !arbeit_ende & !(UCSR0A & (1<<RXC0)) )
15
     ;
16
    /* Get and return received data from buffer */
17
    x=UDR0;
18
.
19
.
20
.
21
//----------kombination 3----------------------------------
22

23
while(!arbeit_ende)
24
  {
25
    while ( (!arbeit_ende) && (!(UCSR0A & (1<<RXC0))) )
26
     ;
27
    /* Get and return received data from buffer */
28
    x=UDR0;
29
.
30
.
31
.


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

danke

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren