How to Implement State Machine in Embedded C: Simple Guide
To implement a state machine in embedded C, define an
enum for states and use a switch-case inside a loop to handle state transitions. Each case represents a state with its actions and conditions to move to the next state.Syntax
Use an enum to list all states, a variable to hold the current state, and a switch-case to execute code based on the current state. Update the state variable to transition between states.
- enum: Defines all possible states.
- state variable: Holds the current state.
- switch-case: Executes code for each state.
- state transitions: Change the state variable to move between states.
c
typedef enum {
STATE_INIT,
STATE_RUN,
STATE_STOP
} State;
State current_state = STATE_INIT;
while(1) {
switch(current_state) {
case STATE_INIT:
// Initialization code
current_state = STATE_RUN;
break;
case STATE_RUN:
// Running code
// condition to stop
current_state = STATE_STOP;
break;
case STATE_STOP:
// Stop code
break;
}
}Example
This example shows a simple state machine with three states: INIT, RUN, and STOP. It prints messages for each state and transitions automatically.
c
#include <stdio.h>
#include <stdbool.h>
typedef enum {
STATE_INIT,
STATE_RUN,
STATE_STOP
} State;
int main() {
State current_state = STATE_INIT;
bool running = true;
while(running) {
switch(current_state) {
case STATE_INIT:
printf("State: INIT\n");
// Move to RUN state
current_state = STATE_RUN;
break;
case STATE_RUN:
printf("State: RUN\n");
// After running once, move to STOP
current_state = STATE_STOP;
break;
case STATE_STOP:
printf("State: STOP\n");
// End the loop
running = false;
break;
}
}
return 0;
}Output
State: INIT
State: RUN
State: STOP
Common Pitfalls
- Not updating the state variable causes the machine to get stuck in one state.
- Forgetting to handle all states in the
switch-casecan cause undefined behavior. - Using blocking code inside states can freeze the machine; keep state actions quick.
- Not initializing the state variable properly can lead to unpredictable behavior.
c
/* Wrong: Missing state update causes infinite loop */ State current_state = STATE_INIT; while(1) { switch(current_state) { case STATE_INIT: // Forgot to update state break; case STATE_RUN: // ... break; case STATE_STOP: // ... break; } } /* Right: Always update state to avoid stuck */ State current_state = STATE_INIT; while(1) { switch(current_state) { case STATE_INIT: current_state = STATE_RUN; break; case STATE_RUN: current_state = STATE_STOP; break; case STATE_STOP: // End or reset break; } }
Quick Reference
Remember these tips for embedded C state machines:
- Use
enumfor clear state names. - Keep state actions short and non-blocking.
- Always update the state variable to move forward.
- Use a
switch-casefor clean state handling. - Initialize the state before the loop.
Key Takeaways
Define states using an enum for clarity and maintainability.
Use a switch-case inside a loop to handle state actions and transitions.
Always update the state variable to avoid infinite loops or stuck states.
Keep state code short and avoid blocking calls to maintain responsiveness.
Initialize the state variable before entering the main loop.