应是天仙狂醉,乱把白云揉碎
状态机,在一般嵌入式开发中都有所应用,主要是为了实现设备在不同的状态转换时执行一些对应的操作。
下面描述下Snow的状态机如何实现:
首先假设我们有6个状态分别为StateA~StateF
typedef enum EnSnowStatus
{
SNOW_STATE_A = 0,
SNOW_STATE_B,
SNOW_STATE_C,
SNOW_STATE_D,
SNOW_STATE_E,
SNOW_STATE_F,
SNOW_STATE_END
}en_snow_status;
那么我们状态切换时需要一个条件触发,我们把这个触发称为事件,假设我们有8个事件分别为EventA~EventH
typedef enum EnSnowEvent
{
SNOW_EVENT_A = 0,
SNOW_EVENT_B,
SNOW_EVENT_C,
SNOW_EVENT_D,
SNOW_EVENT_E,
SNOW_EVENT_F,
SNOW_EVENT_G,
SNOW_EVENT_H,
SNOW_EVENT_END
}en_snow_event;
有了事件和状态后,我们还需要根据项目流程需求,实现一个状态转换图,假设我们的各个状态转
换图如下:
这样根据上面的转换图我们可以得出一个状态事件处理关系,根据这个关系我们可以总结出我们的状态机实现时需要的一些参数,如下:
//! 定义一个执行转换时需要进行的回调函数
typedef void (*action_callback)(void *arg, int *result);
//! 首先定义一个结构体,表示一个事件触发时需要执行的转换过程
typedef struct _StateTransition
{
en_snow_status m_cur_state; //!< 表示事件触发时的当前状态
en_snow_status m_next_state; //!< 执行完这个转换流程后要切换到的状态
en_snow_event m_cur_event; //!< 表示当前触发了哪个事件
action_callback f_action_callback; //!< 状态转换时需要执行的回调函数
}state_transition;
然后根据我们的状态图,我们可以定义出所有需要的状态处理信息:
//! 根据状态图,我们可以得出我们共有8个转换关系
#define STATE_TRANSITON_MAX_NUM 8
//! 定义一个处理所有转换关系的结构体
typedef struct _StateMachineInfo
{
en_snow_state m_cur_status; //!< 表示当前状态机正处于的状态
en_snow_event m_cur_event; //!< 表示当前已经发生的事件
state_transition m_state_transition_list[STATE_TRANSITON_MAX_NUM]; //!< 表示所有转换关系列表
pthread_mutex_t m_state_mutex; //!< 如果涉及多线程处理可以添加个状态转换锁
}state_machine_info;
有了以上这些,我们就可以搭建我们的状态机了,首先我们需要一个状态索引函数,查找我们需要执行的转换过程,然后我们根据查找到的结果去执行转换过程:
//! 首先我们需要一个全局的状态机信息句柄
state_machine_info g_machine_info;
//! 查找需要执行的转换句柄
state_transition* state_machine_find_transition()
{
state_transition *p = NULL;
for(uint8_t i=0; i<STATE_TRANSITON_MAX_NUM; i++)
{
if(g_machine_info.m_state_transition_list[i].m_cur_state == g_machine_info.m_cur_status &&
g_machine_info.m_state_transition_list[i].m_cur_event == g_machine_info.m_cur_event) //!< 判断事件和当前状态是否在转换表中
{
p = &g_machine_info.m_state_machine_list[i];
break;
}
}
return p;
}
实现查找函数后,我们还需要有一个初始化我们状态机的过程:
//! arg 传入参数,result返回结果
void execute_a_to_b(void * arg, int * result)
{
}
//! arg 传入参数,result返回结果
void execute_b_to_c(void * arg, int * result)
{
}
//! arg 传入参数,result返回结果
void execute_c_to_d(void * arg, int * result)
{
}
//! arg 传入参数,result返回结果
void execute_d_to_e(void * arg, int * result)
{
}
//! arg 传入参数,result返回结果
void execute_e_to_f(void * arg, int * result)
{
}
//! arg 传入参数,result返回结果
void execute_a_to_c(void * arg, int * result)
{
}
//! arg 传入参数,result返回结果
void execute_d_to_f(void * arg, int * result)
{
}
//! arg 传入参数,result返回结果
void execute_a_to_b(void * arg, int * result)
{
}
//! arg 传入参数,result返回结果
void execute_a_to_b(void * arg, int * result)
{
}
void state_machine_init()
{
g_machine_info.m_cur_event = SNOW_EVENT_IDLE;
g_machine_info.m_cur_status = SNOW_EVENT_A;
g_machine_info.m_transition_list[0].m_cur_state = SNOW_STATE_A;
g_machine_info.m_transition_list[0].m_next_state = SNOW_STATE_B;
g_machine_info.m_transition_list[0].m_cur_event = SNOW_EVENT_A;
g_machine_info.m_transition_list[0].f_action_callback = execute_a_to_b;
g_machine_info.m_transition_list[1].m_cur_state = SNOW_STATE_A;
g_machine_info.m_transition_list[1].m_next_state = SNOW_STATE_C;
g_machine_info.m_transition_list[1].m_cur_event = SNOW_EVENT_G;
g_machine_info.m_transition_list[1].f_action_callback = execute_a_to_c;
g_machine_info.m_transition_list[2].m_cur_state = SNOW_STATE_B;
g_machine_info.m_transition_list[2].m_next_state = SNOW_STATE_C;
g_machine_info.m_transition_list[2].m_cur_event = SNOW_EVENT_B;
g_machine_info.m_transition_list[2].f_action_callback = execute_b_to_c;
g_machine_info.m_transition_list[3].m_cur_state = SNOW_STATE_C;
g_machine_info.m_transition_list[3].m_next_state = SNOW_STATE_D;
g_machine_info.m_transition_list[3].m_cur_event = SNOW_EVENT_C;
g_machine_info.m_transition_list[3].f_action_callback = execute_c_to_d;
g_machine_info.m_transition_list[4].m_cur_state = SNOW_STATE_D;
g_machine_info.m_transition_list[4].m_next_state = SNOW_STATE_E;
g_machine_info.m_transition_list[4].m_cur_event = SNOW_EVENT_D;
g_machine_info.m_transition_list[4].f_action_callback = execute_d_to_e;
g_machine_info.m_transition_list[5].m_cur_state = SNOW_STATE_D;
g_machine_info.m_transition_list[5].m_next_state = SNOW_STATE_F;
g_machine_info.m_transition_list[5].m_cur_event = SNOW_EVENT_H;
g_machine_info.m_transition_list[5].f_action_callback = execute_a_to_c;
g_machine_info.m_transition_list[6].m_cur_state = SNOW_STATE_E;
g_machine_info.m_transition_list[6].m_next_state = SNOW_STATE_F;
g_machine_info.m_transition_list[6].m_cur_event = SNOW_EVENT_E;
g_machine_info.m_transition_list[6].f_action_callback = execute_a_to_c;
g_machine_info.m_transition_list[7].m_cur_state = SNOW_STATE_F;
g_machine_info.m_transition_list[7].m_next_state = SNOW_STATE_A;
g_machine_info.m_transition_list[7].m_cur_event = SNOW_EVENT_F;
g_machine_info.m_transition_list[7].f_action_callback = execute_a_to_c;
}
最后我们写一个通过查找函数查找并执行状态改变的方法,我们的简单状态机就实现了:
void run()
{
state_transition*p_transition = NULL;
int ret;
while(1)
{
p_transition = state_machine_find_transition();
if(p_transition != NULL)
{
g_machine_info.m_cur_event = SNOW_EVENT_IDLE;
p_transition->f_action_callback(NULL, &ret);
if(ret == 0) //!< 执行成功
{
g_machine_info.m_cur_status = p_transition->m_next_state;
}
}
usleep(1000*5); //!< 记得加延时,要不会耗掉你的cpu
}
}
2023.11.8 立冬大雪