Skip to content

Instantly share code, notes, and snippets.

@tfeldmann
Last active October 6, 2015 18:08
Show Gist options
  • Save tfeldmann/3033278 to your computer and use it in GitHub Desktop.
Save tfeldmann/3033278 to your computer and use it in GitHub Desktop.
C - Statemachine
/**
* Erweiterte C-Statemachine
* Das Programm gibt folgendes aus:
*
* BEGIN: Es geht los. Ich initialisiere das Ganze.
* BEGIN: Es geht weiter in den Zustand ADDITION_SMALL
* BEGIN: Auf Wiedersehen!
* ADDITION_SMALL: Ich fange erst einmal mit kleinen Zahlen an.
* ADDITION_SMALL: Addiere Eins...
* ADDITION_SMALL: Addiere Eins...
* ADDITION_BIG: Small hat sich gar nicht verabschiedet. Frech.
* ADDITION_BIG: Jetzt große Zahlen.
* ADDITION_BIG: Addiere Zehn...
* ADDITION_BIG: Addiere Zehn...
* ADDITION_BIG: Addiere Zehn...
* ADDITION_BIG: Addiere Zehn...
* ADDITION_BIG: Ergebnis: 42!
*/
#include <stdio.h>
// -----------------------------------------------------------------------------
// Defines für die Statemachine
//
#define STATES(_states_...) char flag_state_inited; \
enum State {_states_, STATE_NONE} state; \
State next_state;
#define STATE_MACHINE_START(_x_) flag_state_inited = false; \
state = _x_; next_state = _x_;
#define STATE_SWITCH(_x_) next_state = _x_
#define STATE_IS_ACTIVE(_x_) (state == _x_)
#define STATEMACHINE switch (state) {
#define STATE_ENTER(_x_) case _x_: if (!flag_state_inited) { \
flag_state_inited = 1;
#define STATE_LOOP } else { if (next_state == state) {
#define STATE_LEAVE } else { state = next_state; \
flag_state_inited = false;
#define END_OF_STATE }} break;
#define END_STATEMACHINE STATE_ENTER(STATE_NONE) STATE_LOOP \
STATE_LEAVE END_OF_STATE default: break; }
// -----------------------------------------------------------------------------
// Der eigentliche Code
//
int some_number;
STATES(
// hier einfach deine Zustände einfügen
BEGIN,
ADDITION_SMALL,
ADDITION_BIG
);
void statemachine()
{
STATEMACHINE
STATE_ENTER(BEGIN)
puts("BEGIN: Es geht los. Ich initialisiere das Ganze.");
some_number = 0;
STATE_LOOP
puts("BEGIN: Es geht weiter in den Zustand ADDITION_SMALL");
STATE_SWITCH(ADDITION_SMALL);
STATE_LEAVE
puts("BEGIN: Auf Wiedersehen!");
END_OF_STATE
STATE_ENTER(ADDITION_SMALL)
puts("ADDITION_SMALL: Ich fange erst einmal mit kleinen Zahlen an.");
STATE_LOOP
puts("ADDITION_SMALL: Addiere Eins...");
some_number += 1;
// in den loop kommt die Abbruchbedingung, z.B. durch Sensorwerte
if (some_number == 2)
{
STATE_SWITCH(ADDITION_BIG);
}
STATE_LEAVE
END_OF_STATE
STATE_ENTER(ADDITION_BIG)
puts("ADDITION_BIG: Small hat sich gar nicht verabschiedet. Frech.");
puts("ADDITION_BIG: Jetzt große Zahlen.");
STATE_LOOP
puts("ADDITION_BIG: Addiere Zehn...");
some_number += 10;
if (some_number >= 42)
{
STATE_SWITCH(STATE_NONE); // fertig -> kein Zustand ausgewählt
}
STATE_LEAVE
printf("ADDITION_BIG: Ergebnis: %d!\n", some_number);
END_OF_STATE
END_STATEMACHINE
}
int main()
{
STATE_MACHINE_START(BEGIN);
while (!STATE_IS_ACTIVE(STATE_NONE))
{
// der statemachine() Aufruf kommt dann in deinen loop()
statemachine();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment