0
0
Power-electronicsHow-ToBeginner · 4 min read

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-case can 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 enum for clear state names.
  • Keep state actions short and non-blocking.
  • Always update the state variable to move forward.
  • Use a switch-case for 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.