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
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.
wie eine Merker??? ich verstehe nicht. kannst du mal eine kurze beispiel zeigen
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
Schau dir mal das Konzept von "Finite State Machines" (fsm, oder in dt. Endliche Automaten) an. br heinz
Ja aber ich möchte diese auf Sofware-basis realisieren. danke
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 | }
|
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(); . . . }
we soll dann zum beispiel eine Interrup sein, die die Vorbereitungsfunktion beendet und die Einspritzungsfunktion startet aussehen. danke.
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 | )
|
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
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)
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.
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
Karl schrieb:
> Was meint ihr . ich kann das nun nicht debuggen ,
Warum nicht?
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 .
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
noch wichtig, die Variablen im Interrupt und in der Schleife müssen als "volatile" deklariert werden Gruß Roland
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
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;
NEEEEEIIIIIIIIIN! Es geht auch ohne ver***** goto!!!
Warum einfach, wenns auch kompliziert geht :c)
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!
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
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
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...
@ 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
Ahhhh, OK... danke Dir... back to topic :c)
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.
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
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).
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
ü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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.