状态机的实现

应是天仙狂醉,乱把白云揉碎

        状态机,在一般嵌入式开发中都有所应用,主要是为了实现设备在不同的状态转换时执行一些对应的操作。

下面描述下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 立冬大雪

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值