Forum: Mikrocontroller und Digitale Elektronik Switch-Case Anweisung für Events


von Switcher (Gast)


Lesenswert?

Hallo,

ich habe ein Programm, welches im wesentlichen aus einer Sleep-Zeit 
besteht und mehreren Anweisungen, die sporadisch auftreten können.

Die Hauptfunktion sieht also wie folgt aus:
1
if(Taskregister==FLAG_IDLE)
2
{
3
LPM3;
4
}
5
6
else 
7
{
8
Taskmanager();
9
}


und der eigentliche Taskmanager wie folgt:
1
int32_t Taskmanager()
2
{
3
switch(Taskregister)
4
{
5
case FLAG_MEASURE:  // in Timer ISR gesetzt
6
  Measure(&Messergebnisse);    
7
  set(&Taskregister, FLAG_EVALUATE);
8
  reset(&Taskregister, FLAG_MEASURE); 
9
  set  (&Taskregister, FLAG_TEMP_START);
10
  //no break Fallthrough
11
12
case FLAG_EVALUATE:
13
  reset(&Taskregister, FLAG_EVALUATE);
14
  my_itoa_4digit(Messergebnisse.Wert, string_array);
15
  add_string_to_uart_tx_buffer(&TX_Ringbuffer, Wert);
16
  
17
case FLAG_TEMP_START:
18
  uart_transmit();
19
  Measure_Temp();
20
  reset(&Taskregister, FLAG_TEMP_START);
21
  break;
22
...
23
weitere cases


Hinter dem Flag-Register verbirgt sich:
1
#define FLAG_IDLE   0x0000
2
#define FLAG_MEASURE   0x0001
3
#define FLAG_EVALUATE  0x0002
4
#define FLAG_UART  0x0004
5
6
... weitere Flags...
7
8
9
volatile extern uint32_t Taskregister;

Nun ist die Idee dahinter natürlich, dass die einzelnen Flags an 
unterschiedlichen Positionen und auch durch unterschiedliche externe 
Ereignisse gesetzt werden können.
Das funktioniert auch soweit, solange nur ein einziges Flag zur Zeit 
gesetzt ist.
Sobald aber aus welchen Gründen auch immer mehrere Flags gesetzt sind, 
z.B. zeitgleich das 0. und 1. Bit meines Flagregisters, so ist das 
Resultat dann ja dezimal "3" und die Switch-Case Anweisung findet diesen 
Fall nicht mehr... bzw. fängt an einem falschen Punkt an, in die 
Switch-case Anweisung hineinzulaufen

Wie kann ich dieses Problem umgehen und dabei die oben skizzierte 
Strategie der Eventbehandlung beibehalten?

von Pandur S. (jetztnicht)


Lesenswert?

Indem man nur das betreffende flag zuruecksetzt und nicht alle.

von Klaus W. (mfgkw)


Lesenswert?

1
if( Taskregister | FLAG_MEASURE )
2
{
3
    // ...
4
}
5
if( Taskregister | FLAG_EVALUATE )
6
{
7
    // ...
8
}
9
if ...

von Matthias L. (Gast)


Lesenswert?

Da offensichtlich mehrere Events auftreten können, wäre vielleicht ein 
kleines FIFO interessant? Dort kann der "Taskmanager" abzuarbeitende 
Events entnehmen, während woanders welche produziert werden...

von W.S. (Gast)


Lesenswert?

Switcher schrieb:
> ich habe ein Programm, welches im wesentlichen aus einer Sleep-Zeit
> besteht und mehreren Anweisungen, die sporadisch auftreten können.

Switcher schrieb:
> Wie kann ich dieses Problem umgehen und dabei die oben skizzierte
> Strategie der Eventbehandlung beibehalten?

Du arbeitest doch garnicht mit Events. Deine Art zu Programmieren, die 
du hier gezeigt hast, ist überhaupt nicht ereignisgesteuert, sondern 
schlichtweg prozedural.

Deine case Kaskade ist - wenn man sie mal auf's Wesentliche 
zusammenstaucht doch so:

immerzu:
  Measure();
  ConvToString();
  GibStringAus();
  MeasureTemp();
  GibTempAus();
  goto immerzu;

Das hat mit ereignisgesteuerten Abläufen keinelei Ähnlichkeit. Du kannst 
also sinnvollerweise nur eines tun: alles in die Tonne und ganz neu 
beginnen.

W.S.

von Joe F. (easylife)


Lesenswert?

"set" und "reset" sollte man als funktionsnahen besser vermeiden.
ansonsten:

1
if (Taskregister & FLAG_MEASURE)
2
{
3
  reset_flag(&Taskregister, FLAG_MEASURE); 
4
  set_flag  (&Taskregister, FLAG_EVALUATE);
5
  set_flag  (&Taskregister, FLAG_TEMP_START);
6
  Measure(&Messergebnisse);    
7
}
8
9
if (Taskregister & FLAG_EVALUATE)
10
{
11
  reset_flag(&Taskregister, FLAG_EVALUATE);
12
  my_itoa_4digit(Messergebnisse.Wert, string_array);
13
  add_string_to_uart_tx_buffer(&TX_Ringbuffer, Wert);
14
}
15
  
16
if (Taskregister & FLAG_TEMP_START)
17
{
18
  reset_flag(&Taskregister, FLAG_MEASURE); 
19
  uart_transmit();
20
  Measure_Temp();
21
}

von Switcher (Gast)


Lesenswert?

selbstverständlich arbeite ich mit Events.

Events treten z.B. dann auf, wenn der UART-Buffer mal wieder ein neues 
Byte haben möchte, um einen Text innerhalb der Sleepphase zu übertragen.

Und Events treten auch dann auf, wenn externe Sensoren erst nach einer 
definierten Zeit einen Messwert bereit stellen,

Und events treten auch dann auf, wenn mal ein externer Taster gedrückt 
wird...

Nur weil einige dieser Zeiten theoretisch bis auf einige Millisekunden 
genau vorhersehbar sind, heisst das doch nicht, dass dies kein event 
darstellt.


Ist ja auch egal, wahrscheinlich ist es mit den IF-Abfragen am 
einfachsten um zu stricken...

von Joe F. (easylife)


Lesenswert?

soll natürlich heissen:
1
if (Taskregister & FLAG_TEMP_START)
2
{
3
  reset_flag(&Taskregister, FLAG_TEMP_START); 
4
  uart_transmit();
5
  Measure_Temp();
6
}

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.