Sprung aus Unterprogramm an eine bestimmte Stelle in der Main

Gast #4063899
Lesenswert?

Hallo,

bin noch kein Programmierprofi und habe folgendes Problem. Ich möchte 
das nach dem längeren Drücken der Taste des Interrupts (idealerweise 1s) 
das Programm in den Modus 0 springt.
Kann ich direkt aus der Interrupt Routine irgendwie an die "Marke" 
springen kann, oder ist der Weg über pause(); der richtigere Weg? Oder 
ist mein Ansatz komplett falsch?

1
#include <avr/io.h>
2
#ifndef F_CPU
3
/* Definiere F_CPU, wenn F_CPU nicht bereits vorher definiert 
4
   (z.&nbsp;B. durch Übergabe als Parameter zum Compiler innerhalb 
5
   des Makefiles). Zusätzlich Ausgabe einer Warnung, die auf die
6
   "nachträgliche" Definition hinweist */
7
//#warning "F_CPU war noch nicht definiert, wird nun mit 3686400 definiert"
8
#define F_CPU 8000000UL     /* Quarz mit 8.000 Mhz */
9
#endif
10

11

12
#include <avr/sleep.h>
13
#include <avr/interrupt.h>
14
#include <util/delay.h>
15

16

17
//////////Variablen//////////////
18
int modus; 
19
int off=0;
20

21

22

23
//////////////////Interrupt Service Routine///////////////////
24
ISR(INT0_vect)
25
{
26
  off=0;
27
  modus++;
28
  while ( !(PINB & (1<<PINB6)))
29
  {
30
    
31
    /////////////Kann ich von hier aus Springen und das IFlag manuell löschen?
32
    while (off<1000)
33
    {
34
      _delay_ms(1);
35
      off++;
36
    }    
37
  }
38
}
39

40

41

42

43

44
///////////LED Ansteuerung///////////////
45
void Reihe1(void)
46
{
47
  PORTA=0x96;
48
}
49
void Reihe2(void)
50
{
51
  PORTA=0xa6;
52
}
53
void Reihe3(void)
54
{
55
  PORTA=0xc6;
56
}
57

58
void LEDoff(void)
59
{
60
  PORTA=0x87;
61
}
62
void LEDallON(void)
63
{
64
  PORTA=0xf7;
65
}
66

67
///////////////Pausenzeit /////////////////////////
68
void pause ( uint8_t ms )
69
{
70
  if (off=1000)
71
  {
72
    modus=0;
73
    //////Springe von hier an die Stelle Marke in der Main
74
  }
75
  for(; ms > 0; ms--) _delay_ms(1);
76
}
77

78

79

80

81

82

83
int main(void)
84
{
85
  ///IO Konfiguartion
86
  DDRA=0xf7;
87
  DDRB=0x00;
88
  
89
  
90
  
91
  while(1)
92
  {
93
    ///Marke: Sprung aus dem Unterprogramm
94
    
95
    if (modus==0)
96
    {
97
      off=0;
98
      LEDoff();
99
    }
100
    if (modus==1)
101
    {
102
      LEDallON();
103
      pause(10);
104
      LEDoff();
105
      pause(10);
106
    }
107
    if (modus==2);
108
    {
109
      Reihe1();
110
      pause(10);
111
      Reihe2();
112
      pause(10);
113
      Reihe3();
114
      pause(10);
115
    }
116
    if (modus==3)
117
    {
118
      modus=0;
119
    }
120
  }
121
  return 0;
122
  
123
}
Gast #4063919
Lesenswert?

Deshalb wollte ich aus der Pause in die Main springen, da ist der 
Interrupt sicher abgehandelt. Habe schon mit Goto versucht, aber das 
kann ja nicht gehen. Aber wie realisiert man einen sauberen Rücksprung? 
Ich denke, diese Problem tritt häufiger auf oder?
Gast #4063932
Lesenswert?

Also üblicherweise springt man in C-Programmen nicht wild über 
Funktionsgrenzen herum, das ist so in der Sprache auch nicht vorgesehen. 
Gehen tuts natürlich (setjmp/longjmp oder Interventionen in Assembler), 
aber man will das nicht.

Jede Art von delay in einer ISR ist ausserdem böse.
Gast #4063950
Lesenswert?

iGast schrieb:
> Deshalb wollte ich aus der Pause in die Main springen, da...

Du bist gerade dabei, das Schlimmstmögliche veranstalten zu wollen.

Mein Rat:

1. denke zu allererst mal gründlich über eine vernünftige 
Programmstruktur nach

2. halte Interruptroutinen KURZ. Nee, nicht 'klein' im Sinne von 
möglichst wenigen Buchstaben, sondern kurz, also möglichst garkeine Zeit 
beanspruchend. Also definitiv KEINE Trampelschleifen im Interrupt.

3. realisiere Zeiten mit Countern/Timern und nicht mit dem Aufruf von 
AufDerStelleTret-Funktionen.

4. schreibe main() möglichst ohne ein return 0 oder so, denn erstens 
sollte bei einem µC main wohl niemals zurückkehren (oder nur dann, wenn 
man ein RTOS o,ä. hat) und zweitens führt sowas leicht zu Verwirrungen. 
Falls dein Compiler einen fehlenden Return moniert, dann versuch's mit 
void main - sofern der Compiler das nicht auch bemeckert (was ich stark 
befürchte) oder benutze alternativ einfach goto. Bei einem Goto dirkt 
vor der Endklammer meckert m.W. KEIN EINZIGER Compiler.

W.S.
Gast #4063954
Lesenswert?

Ein ganz guter Anfang ist hier: 
http://www.mikrocontroller.net/articles/Statemachine beschrieben. Mit 
Beispielen.

Auf Dein Problem bezogen, lohnt sich vielleicht auch eine Beschäftigung 
mit Peter Danneggers Entprellcode hier im Forum.

Allerdings ist das, besonders wenn man ganz allgemein noch wenig 
programmiert hat (ich weiß nicht, ob und inwiefern das Dich zutrifft), 
recht harter Stoff. Ein paar Tage mit intensivem Experimentieren werden 
da schon nötig sein.

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