๐ Scenario: You are working on a simple device that communicates using a protocol with three states: IDLE, RECEIVING, and PROCESSING. The device waits for a start signal, receives data, and then processes it.
๐ฏ Goal: Build a state machine in C that handles the protocol states and transitions correctly.
๐ What You'll Learn
Create an enum for the states: IDLE, RECEIVING, PROCESSING
Create a variable to hold the current state
Write a function to handle state transitions based on input signals
Print the current state after each transition
๐ก Why This Matters
๐ Real World
State machines are used in embedded devices to manage communication protocols, user interfaces, and hardware control.
๐ผ Career
Understanding state machines is essential for embedded systems engineers, firmware developers, and anyone working with hardware-software integration.
Progress0 / 4 steps
1
Define the states enum and current state variable
Create an enum called State with these exact members: IDLE, RECEIVING, PROCESSING. Then create a variable called current_state of type State and set it to IDLE.
Embedded C
Hint
Use typedef enum { ... } State; to define states. Then declare State current_state = IDLE;.
2
Create input signal variable
Create an int variable called input_signal and set it to 0. This will represent the incoming signal to the state machine.
Embedded C
Hint
Declare int input_signal = 0; to hold the signal.
3
Write the state machine function
Write a function called handle_state() that uses switch(current_state) to handle states. For each state, check input_signal and update current_state as follows: - If current_state == IDLE and input_signal == 1, set current_state = RECEIVING. - If current_state == RECEIVING and input_signal == 2, set current_state = PROCESSING. - If current_state == PROCESSING and input_signal == 0, set current_state = IDLE.
Embedded C
Hint
Use a switch statement on current_state. Inside each case, check input_signal and update current_state accordingly.
4
Print the current state after transitions
Write a main() function that sets input_signal to 1, calls handle_state(), then sets input_signal to 2, calls handle_state(), then sets input_signal to 0, calls handle_state(). After each call, print the current state as a string: IDLE, RECEIVING, or PROCESSING.
Embedded C
Hint
Use printf to print the state name after each handle_state() call. Use if statements to check current_state.
Practice
(1/5)
1. What is the main purpose of using a state machine in protocol handling in embedded C?
easy
A. To reduce the size of the compiled program
B. To speed up the processor clock
C. To avoid using any conditional statements
D. To clearly control the sequence of protocol steps and handle events safely
Solution
Step 1: Understand the role of a state machine
A state machine organizes different states and transitions to manage complex sequences clearly.
Step 2: Relate to protocol handling
Protocols require strict step-by-step control and safe event handling, which state machines provide.
Final Answer:
To clearly control the sequence of protocol steps and handle events safely -> Option D
Quick Check:
State machine controls protocol steps safely = C [OK]
Hint: State machines organize steps and events clearly [OK]
Common Mistakes:
Thinking state machines speed up hardware
Believing they reduce program size automatically
Assuming they remove all conditionals
2. Which of the following is the correct way to define states for a protocol using enums in embedded C?
easy
A. enum ProtocolState {IDLE, WAIT_ACK, SEND_DATA, ERROR};
B. enum ProtocolState = {IDLE, WAIT_ACK, SEND_DATA, ERROR};
C. enum ProtocolState {IDLE; WAIT_ACK; SEND_DATA; ERROR};
D. enum ProtocolState (IDLE, WAIT_ACK, SEND_DATA, ERROR);
Solution
Step 1: Recall enum syntax in C
Enums use the syntax: enum Name {value1, value2, ...}; with commas separating values.
Step 2: Check each option
enum ProtocolState {IDLE, WAIT_ACK, SEND_DATA, ERROR}; uses correct syntax with commas and no assignment. Others use invalid syntax like '=' or semicolons.
Final Answer:
enum ProtocolState {IDLE, WAIT_ACK, SEND_DATA, ERROR}; -> Option A
Quick Check:
Enum syntax with commas = B [OK]
Hint: Enums use commas, not equals or semicolons [OK]
Common Mistakes:
Using '=' after enum name
Separating values with semicolons
Using parentheses instead of braces
3. Given the following code snippet, what will be the output printed?
typedef enum {IDLE, WAIT_ACK, SEND_DATA} State;
void handle_event(State *state, int event) {
switch (*state) {
case IDLE:
if (event == 1) {
*state = SEND_DATA;
printf("Sending data\n");
}
break;
case SEND_DATA:
if (event == 2) {
*state = WAIT_ACK;
printf("Waiting for ACK\n");
}
break;
case WAIT_ACK:
if (event == 3) {
*state = IDLE;
printf("ACK received, back to IDLE\n");
}
break;
}
}
int main() {
State current_state = IDLE;
handle_event(ยคt_state, 1);
handle_event(ยคt_state, 2);
handle_event(ยคt_state, 3);
return 0;
}
medium
A. Sending data
Waiting for ACK
ACK received, back to IDLE
B. Waiting for ACK
Sending data
ACK received, back to IDLE
C. Sending data
ACK received, back to IDLE
Waiting for ACK
D. No output
Solution
Step 1: Trace first event with state IDLE and event 1
State is IDLE, event 1 triggers transition to SEND_DATA and prints "Sending data".
Step 2: Trace second event with state SEND_DATA and event 2
State is SEND_DATA, event 2 triggers transition to WAIT_ACK and prints "Waiting for ACK".
Step 3: Trace third event with state WAIT_ACK and event 3
State is WAIT_ACK, event 3 triggers transition to IDLE and prints "ACK received, back to IDLE".
Final Answer:
Sending data
Waiting for ACK
ACK received, back to IDLE
-> Option A
Quick Check:
Events 1,2,3 cause correct state prints = A [OK]
Hint: Follow state changes step-by-step with events [OK]
Common Mistakes:
Mixing order of printed lines
Ignoring state changes after events
Assuming all events print output
4. Identify the bug in this state machine code snippet and select the fix:
typedef enum {IDLE, SEND, WAIT} State;
void process_event(State *state, int event) {
switch (*state) {
case IDLE:
if (event == 1) {
*state = SEND;
printf("Start sending\n");
}
case SEND:
if (event == 2) {
*state = WAIT;
printf("Waiting for response\n");
}
break;
case WAIT:
if (event == 3) {
*state = IDLE;
printf("Back to idle\n");
}
break;
}
}
medium
A. Change enum values to strings
B. Add a break after the IDLE case to prevent fall-through
C. Remove the break after SEND case
D. Replace switch with if-else statements
Solution
Step 1: Analyze switch-case structure
The IDLE case lacks a break, so after executing IDLE code, it falls through to SEND case unintentionally.
Step 2: Identify fix to prevent fall-through
Adding a break after IDLE case stops execution from continuing into SEND case.
Final Answer:
Add a break after the IDLE case to prevent fall-through -> Option B
Quick Check:
Missing break causes fall-through = A [OK]
Hint: Always add break after each case unless intentional fall-through [OK]
Common Mistakes:
Ignoring missing break causing bugs
Changing enum types unnecessarily
Removing needed breaks
5. You want to extend a protocol state machine to handle a timeout event that resets the state to IDLE from any state. Which is the best way to implement this in embedded C?
hard
A. Use goto statements inside switch-case to jump to IDLE
B. Add a new state TIMEOUT and transition only from WAIT state
C. Add a check for timeout event before the switch-case and reset state to IDLE if triggered
D. Ignore timeout events in the state machine and handle separately
Solution
Step 1: Understand requirement for timeout handling
Timeout should reset to IDLE from any state immediately when detected.
Step 2: Choose implementation approach
Checking timeout before switch-case allows immediate reset regardless of current state.
Step 3: Evaluate other options
Adding TIMEOUT state limits reset to one state only; ignoring timeout misses requirement; goto is poor style and error-prone.
Final Answer:
Add a check for timeout event before the switch-case and reset state to IDLE if triggered -> Option C
Quick Check:
Pre-check timeout for immediate reset = D [OK]
Hint: Check global events before state-specific logic [OK]
Common Mistakes:
Adding unnecessary states for global events
Ignoring timeout in state machine
Using goto for flow control
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.