State Machine with Function Pointers
Now how do we benefit from function pointers in the context of a state machine? Simple, just wrap the processing for a given state as a function, and call that:
#include <avr/io.h>
#define F_CPU 20000000UL
#include <util/delay.h>
// States
void led_on();
void led_off();
// State pointer
void (*statefunc)() = led_on;
void led_on() {
PORTB |= 1;
statefunc = led_off;
}
void led_off() {
PORTB &= ~1;
statefunc = led_on;
}
int main() {
DDRB |= 1;
while(1) {
(*statefunc)();
_delay_ms(1000); // sleep for a second
}
return 1; // should not get here
}
We can make one further addition: Instead of setting a global function pointer, let’s just have the state function to return a pointer to the next state function. This will make the code a bit cleaner with maybe a few clock cycle overhead. We’ll use a typedef and some type casting to make the code a little easier to read:
#include <avr/io.h>
#define F_CPU 20000000UL
#include <util/delay.h>
typedef void *(*StateFunc)();
// States
void *led_on();
void *led_off();
void *led_on() {
PORTB |= 1;
return led_off; // next state
}
void *led_off() {
PORTB &= ~1;
return led_on; // next state
}
int main() {
StateFunc statefunc = led_on;
DDRB |= 1;
while(1) {
statefunc = (StateFunc)(*statefunc)();
_delay_ms(1000); // sleep for a second
}
return 1; // should not get here
}
Anyone who can write the code below without a void pointer and a type cast, please give your solution in comments, I’d be interested to see the exact line to do it (extra points if you can typedef the StateFunc as a function pointer that returns a function pointer)!
对状态机的转换函数可以写得抽象写,利用状态机转换表的形式。比如:
/*
Stat1 Stat2 Stat3 Stat4
Stat1 0 1 1 0
Stat2 0 0 1 0
Stat3 1 1 0 0
Stat4 0 0 1 0
*/
bool stateTable[4][4]={false};
typedef void *(*StateFunc)();
// States
void *S1();
void *S2();
void *S3();
void *S4();
void *S1() {
if(stateTable[0][1]==true)
return S2;
else if (stateTable[0][2]==true)
return S3;
else
return S1;
}
void *S2() {
if(stateTable[0][2]==true)
return S3;
else
return S2;
}
void *S3() {
if(stateTable[0][0]==true)
return S1;
else if (stateTable[0][1]==true)
return S2;
else
return S3;
}
void *S4() {
if(stateTable[0][3]==true)
return S3;
else
return S4;
}
int main() {
StateFunc statefunc = S1;
while(1) {
modifystateTable();//modify stateTable according to situations
statefunc = (StateFunc)(*statefunc)();
_delay_ms(1000); // sleep for a second
}
return 1; // should not get here
}