Forum: Mikrocontroller und Digitale Elektronik Probleme mit Funkionsaufruf


von Markus P. (sebastianwurst)


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
}

von Peter II (Gast)


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)

von Karl H. (kbuchegg)


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.

von Markus P. (sebastianwurst)


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 ?

von Peter II (Gast)


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.

von Karl H. (kbuchegg)


Lesenswert?

Markus P. schrieb:

> 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.

Wie kann das gleichzeitig passieren?

Das ist die entscheidende Frage!

hinterinenader: ja. Aber gleichzeitig?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Markus P. (sebastianwurst)


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]
....

von Karl H. (kbuchegg)


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).

von Karl H. (kbuchegg)


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!

von Markus P. (sebastianwurst)


Lesenswert?

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....

von Karl H. (kbuchegg)


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.

von Markus P. (sebastianwurst)


Lesenswert?

Wie hieß denn dein erstes Buch ?

von Karl H. (kbuchegg)


Lesenswert?

Der Klassiker


Kernighan & Ritchie
Programmieren in C

von Markus (Gast)


Lesenswert?

Bestellt.....

Danke nochmal !

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
Noch kein Account? Hier anmelden.