Probleme mit Funkionsaufruf

OP #2282555
Lesenswert?

Hi,
ich will gerne eine Funktion aufrufen die mir dann in der Funktion ein 
Ausgang setzt und diesen nach Ablauf eines Counters wieder zurücksetzt.
Problem welches ich jetzt habe ist, das während dem Aufruf der Funktion 
die gleiche Funktion noch einmal aufgerufen werden kann. Sozusagen eine 
weitere Instanz. Wie kann ich das denn bei einem Mikrocontroller der in 
C programmier wird machen ? (In c) Hier ist mein Beispiel:
1
void RelaisSchalten(uint8_t SetBit, uint8_t UnsetBit)  
2
{
3
static uint16_t TimerAusgangCount = 0;
4
  
5
if (Nulldurchgang == true) {TimerAusgangCount++;}   
6
     
7
      AusgangSetBit(SetBit);
8
      AusgangUnsetBit(UnsetBit); 
9
      AusgangOut();
10
    
11
    if (TimerAusgangCount >= 50)
12
    {
13
      AusgangUnsetBit(SetBit); 
14
      AusgangUnsetBit(UnsetBit); 
15
      AusgangOut();
16
      TimerAusgangCount = 0;
17
      RelaisSchaltenStart[0] = false;
18
      RelaisSchaltenStart[1] = false;
19
    }  
20
}

Aufruf in der While schleife :
Alle drei Aufrufe könnten theoretisch gleichzeitg kommen.
1
if (RelaisSchaltenStart[0])
2
{
3
RelaisSchalten(0, 1);  
4
}
5

6
if (RelaisSchaltenStart[1])
7
{
8
RelaisSchalten(3, 4);  
9
}
10

11
if (RelaisSchaltenStart[2])
12
{
13
RelaisSchalten(6, 7);    
14
}
Gast #2282568
Lesenswert?

Markus P. schrieb:
> Alle drei Aufrufe könnten theoretisch gleichzeitg kommen.

da stellt sich erstmal die Frage wie das sein kann? hast du ein 
Betriebssystem auf den µC?

Wenn ja sollte es dort funktionen geben die blockieren wenn schon die 
gleiche funktion aufgerufen wird (bei windows ist es z.b. 
CriticalSection)
#2282578
Lesenswert?

> Aufruf in der While schleife :
> Alle drei Aufrufe könnten theoretisch gleichzeitg kommen.

Was genau hat man sich unter dieser Aussage vorzustellen?

Die einzige Chance, wie eine Funktion vom Aufruf derselben Funktion 
unterbrochen werden kann, ist mittels Interrupt, solange kein 
Betriebssystem im Spiel ist.
OP #2282647
Lesenswert?

Peter II schrieb:

> da stellt sich erstmal die Frage wie das sein kann? hast du ein
> Betriebssystem auf den µC?

Nein, ich will eine Funktion aufrufen und diese andere Werte übergeben:
Jetzt soll ja Bit 0 und 1 bearbeitet werden. (Schieberegister schalten 
die Bits)
1
if (RelaisSchaltenStart[0])
2
{
3
RelaisSchalten(0, 1);  
4
}

Jetzt 3 und 4
1
if (RelaisSchaltenStart[1])
2
{
3
RelaisSchalten(3, 4);  
4
}

Dieser Aufruf der Funktionen kann theoretisch gleichzeitig komme, da sie 
z.B. über zwei unterschiedliche Taster ausgeführt werden.

If (Taster1) RelaisSchaltenStart[1] = true; usw.


Aber die laufende Funktion soll dann nicht abgebrochen werden sondern 
natürlich vernünftig abgearbeitet werden.
Ich befürchte/denke das dieses so nicht möglich ist. Oder ?
Gast #2282657
Lesenswert?

Markus P. schrieb:
> Dieser Aufruf der Funktionen kann theoretisch gleichzeitig komme, da sie
> z.B. über zwei unterschiedliche Taster ausgeführt werden.

nein, das ist immer noch nicht klar. Auch Taster werden nacheinander 
abgefragt und nicht gleicheitig. Ein µC ohne BS macht eigneltich nicht 
gleichzeitg - ist es ja auch nur eine CPU.
OP #2282686
Lesenswert?

Karl Heinz Buchegger schrieb:
> Das hier
>
>   static uint16_t TimerAusgangCount = 0;
>
> ist natürlich ein Problem, das du lösen musst. zb indem du für jedes
> Relais einen eigenen Zähler machst und den ebenfalls der Funktion
> übergibst.
Ah ja das wollt ich wissen, wie mach ich das dann am besten? Funzt das 
so?

void RelaisSchalten(uint16_t Zaehlvariable)
 Static uint16_t  Counter[Zaehlvariable]
....
#2282695
Lesenswert?

So, jetzt machen wir das mal vernünftig.

Als erster fasst du mal alles was es zu einem Relais zu sagen gibt in 
einer Struktur zusammen, damit du da nicht dauernd mit 100-tausend 
Werten hantieren musst.
1
struct Relais {
2
   uint8_t   bitToSet; 
3
   uint8_t   bitToClear;
4
   uint16_t  setCycles;     // Zaehlt die 0-Durchgänge bis zum Abschalten
5
};

damit ist ein Relais prinzipiell mal grundsätzlich in seiner vollen 
Pracht beschrieben.

Dann hast du 3 Relais
1
struct Relais   MotorEin  = { 0, 1, 0 };
2
struct Relais   RolloHoch = { 3, 4, 0 };
3
struct Relais   TuerAuf   = { 6, 7, 0 };

da sind sie. Komplett mit der Definition, welche Bits zu bedienen sind 
und jedes Relais hat seinen eigenen 0-Durchgangszähler.

Weiters brauchst du eine Funktion, die 1 Relais bei mehrmaligem Aufruf 
bedienen kann. Die Funktion funktioniert so wie deine, wobei der 
springende Punkt darin besteht, dass die Funktion alles Wissenswerte 
über das zu bedienende Relais aus der Strukturbeschreibung erfährt, und 
zwar von dem Relais auf das es einen Pointer bekommt. Die Funktion 
liefert true oder false zurück, je nachdem ob die Relaiszeit abgelaufen 
ist oder nicht. Dies brauchst du in der Hauptschleife, damit du dort die 
Anforderung für das Relais-Schalten wieder zurück setzen kannst.
1
uint8_t RelaisSchalten( struct Relais* theRelais )  
2
{
3
  if (Nulldurchgang)
4
    theRelais->setCycles++;
5
     
6
  AusgangSetBit( theRelais->bitToSet );
7
  AusgangUnsetBit( theRelais->bitToClear ); 
8
  AusgangOut();
9
    
10
  if (theRelais->setCycles >= 50)
11
  {
12
    AusgangUnsetBit( theRelais->bitToSet ); 
13
    AusgangUnsetBit( theRelais->bitToClear ); 
14
    AusgangOut();
15

16
    theRelais->setCycles = 0;
17
    return true;
18
  }  
19

20
  return false;
21
}

und die Funktion rufst du jetzt auf
1
int main()
2
{
3
   ....
4

5

6
  while( 1 ) {
7

8
    ....
9

10
    if (RelaisSchaltenStart[0])
11
    {
12
      if (RelaisSchalten( &MotorEin ))
13
        RelaisSchaltenStart[0] = false;
14
    }
15
  
16
    if (RelaisSchaltenStart[1])
17
    {
18
      if (RelaisSchalten( &RolloHoch ))
19
        RelaisSchaltenStart[1] = false;
20
    }
21

22
    if (RelaisSchaltenStart[2])
23
    {
24
      if (RelaisSchalten( &TuerAuf ))
25
        RelaisSchaltenStart[2] = false;
26
    }
27
}

und wenn die Funktion zurückliefert, dass es das jeweilige Relais wieder 
abgeschaltet hat, dann nimmst du hier auch wieder die Anforderung zurück 
(und nicht in der Funktion, das ist nicht ihre Aufgabe sich darum zu 
kümmern).
#2282700
Lesenswert?

Markus P. schrieb:
> Karl Heinz Buchegger schrieb:
>> Das hier
>>
>>   static uint16_t TimerAusgangCount = 0;
>>
>> ist natürlich ein Problem, das du lösen musst. zb indem du für jedes
>> Relais einen eigenen Zähler machst und den ebenfalls der Funktion
>> übergibst.
> Ah ja das wollt ich wissen, wie mach ich das dann am besten? Funzt das
> so?
>
> void RelaisSchalten(uint16_t Zaehlvariable)
>  Static uint16_t  Counter[Zaehlvariable]
> ....

Nein.
Kauf dir ein C-Buch und arbeite zumindest das erste Drittel durch. Wie 
man Funktionen aufruft und wie das mit den Parametern funktioniert sind 
absolute Grundlagen. Ich werde dir das hier nicht näher erläutern. Das 
steht in jedem noch so grindigem C-Buch für 8 Euro vom Wühltisch 
drinnen.

Aber ich hab dir eine andere, bessere Lösung im vorhergehenden Post 
zumindest soweit skizziert, dass du damit klar kommen solltest. Aber 
auch hier wieder: Auch das sind eigentlich C-Grundlagen. Du brauchst ein 
C-Buch!
#2282711
Lesenswert?

Markus P. schrieb:
> Ok, danke das werde ich mir besorgen. Gegooglet habe ich danach, aber
> nichts gefunden und dann liegt es einfach nahe hier die Frage zu stellen
> weil man hier geholfen wird....

Drum habe ich dir auch die Struktur-Lösung gemacht. Denn da geht es dann 
schon in den Bereich "Wie designed man vernünftig eine Lösung" hinein. 
Das ist dann eben der Unterschied ob du von jeder Schachfigur weißt, wie 
sie ziehen kann und wie man das ganze dann benutzt um eine Strategie 
umzusetzen, meinetwegen ein Damengambit. Aber solange du mit den 
prinzipiellen Zugmöglichkeiten der Figuren auf Kriegsfuss stehst (das 
sind die Grundlagen), hat es keinen Sinn sich über die Feinheiten eines 
Damengambits ( = guter Programmierstil) zu unterhalten. Und darum 
benötigst du ein Buch, um dir die Grundlagen beizubringen und erst mal 
zu wissen welche Möglichkeiten du überhaupt zur Verfügung hast.

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