达尔优牧马人鼠标1代:程序设计之有限状态机
来源:百度文库 编辑:九乡新闻网 时间:2024/05/06 08:27:44
程序设计之有限状态机 状态机?以前听说过,忘了是老师说的,还是老大说得了。当时的认识也就是字面的意思,无非是和状态以及状态转换有关系。也许在写过或者读过的一些代码中有遇到过有限状态机的程序,但是当时是一定没有想到这就是状态机吧。最近在学习一些东西的时候竟然多次遇到,觉得还是有必要写点关于程序设计中有限状态机的东西。
http://www.cppblog.com/CppExplore/archive/2008/01/23/41726.html,这里是一篇对状态机从定义到实现都有很好解释的文章,摘录部分如下:
***************************************************************************************
依据状态之间是否有包含关系,分以下两种
(1)常规状态机。状态机中的所有状态是不相交的、互斥的。
(2)层次状态机。状态机中的状态之间要么是互斥的,要么是真包含的,可以用树性结构来描述这些状态集,包含其它状态的状态称为枝节点,不包含其它状态的状态称为叶节点,为方便单树描述,总是设计一个状态包含所有的状态节点,称为根节点。状态机的状态只能停留在叶节点,而不能停留在枝节点,每个枝节点需要指定一个子节点为它的默认子节点,以便状态机进入枝节点的时候能够停留到叶节点。
一般都用switch/case if/else方式实现。在少量状态(3个及其以下)的时候,不需要引入专门的状态机模块。
常规状态机模块实现涉及到的结构由上而下为:
顶层结构是状态机:当前状态id,缺省操作,状态表,
状态表:状态数组
状态结构:状态id,状态名,进入操作,退出操作,缺省操作,状态事件表(数组)
状态事件结构:操作,事件,下一状态的id
***************************************************************************************
从代码易读及美观角度来说,建议用switch/case来实现。 从经验来看,在一些稍大的程序设计中一般都会有状态机的实现,特别是在分层实现,协议栈实现,编解码方面。 下面通过一个简单的例子来看下。这个例子是zigbee精简协议栈实现中的【这里只讲APS层的有限状态机,这是开放源代码的,对于该协议总体上是分层来实现的,每一次层都有状态机来进行实际的数据业务处理】。
(1)定义各状态
typedef enum _APS_STATE_ENUM
{
APS_STATE_IDLE,
APS_STATE_COMMAND_START,
APS_STATE_GENERIC_TX_WAIT,
APS_STATE_NWK_PASSTHRU_WAIT,
APS_STATE_INDIRECT_GETDST,
APS_STATE_INDIRECT_TX,
#ifdef LRWPAN_COORDINATOR
APS_STATE_INJECT_INDIRECT,
#endif
APS_STATE_ACK_SEND_START,
APS_STATE_INDIRECT_TX_WAIT,
APS_STATE_INJECT_LOOPBACK,
APS_STATE_INDIRECT_LOOPBACK
} APS_STATE_ENUM;
(2)设计有限状态机函数
void apsFSM(void)
{
apsFSM_start://状态机入口 switch (apsState) //全局变量,指示当前状态
{
case APS_STATE_IDLE:
if (aps_pib.flags.bits.ackSendPending)
{
apsState = APS_STATE_ACK_SEND_START;//状态转换
goto apsFSM_start;
}
break;
case APS_STATE_ACK_SEND_START:
if (phyTxLocked())
{
break;
}
//send an ACK
//lock the TX buffer
phyGrabTxLock();
//we are now ready
apsFormatAck();
phy_pib.currentTxFlen = 0; //set frame length to zero, build from scratch
apsTxData(TRUE);
//data sent, release the RX buffer, will let RX FSM resume
aps_pib.flags.bits.ackSendPending = 0;
apsState = APS_STATE_GENERIC_TX_WAIT; break; case APS_STATE_GENERIC_TX_WAIT:
if (!apsTXIdle())
{
break;
}
//TX is finished, copy status
a_aps_service.status = apsTxFSM_status;
//release the TX buffer lock before exiting.
phyReleaseTxLock();
apsState = APS_STATE_IDLE;
if (aps_pib.flags.bits.indirectPending)
{
//have used this state to wait for finishing sending an
//ACK back to the source of an indirect transmit. Now
//finish resolving the indirect
goto apsFSM_start;
}
break; case APS_STATE_NWK_PASSTHRU_WAIT:
//for split-phase passthrus
if (nwkBusy())
{
break;
}
a_aps_service.status = a_nwk_service.status;
apsState = APS_STATE_IDLE;
break; case APS_STATE_INJECT_LOOPBACK:
//wait for RX to become idle
if (apsRxState != APS_RXSTATE_IDLE)
{
break;
}
//inject packet into RX FSM
apsInjectPacket(FALSE);
aps_pib.flags.bits.IsUsrBufferFree = 1;
apsState = APS_STATE_IDLE;
goto apsFSM_start;
default:
break;
}
}
(3)大致结构:状态机入口,状态转换,状态机退出从这个函数实现,我们可以简单了解有限状态机的实现过程。当程序的实现有多个状态的时候,也就是要根据不同的状态做不同的事情的时候,可以考虑把某个操作过程拆分为几个步骤【很多时候这是必须的】,对应状态机操作的几个不同状态。多数情况下,这些状态是多个操作可以共用的。一般的状态机函数都会提供一个状态退出操作,每个状态操作可以根据条件来判断是要退出,还是要转换进行下一个状态的。 状态机是程序设计时的一种思想,尤如设计模式,只有在恰当的时候用来才回体现出其价值。
http://www.cppblog.com/CppExplore/archive/2008/01/23/41726.html,这里是一篇对状态机从定义到实现都有很好解释的文章,摘录部分如下:
***************************************************************************************
依据状态之间是否有包含关系,分以下两种
(1)常规状态机。状态机中的所有状态是不相交的、互斥的。
(2)层次状态机。状态机中的状态之间要么是互斥的,要么是真包含的,可以用树性结构来描述这些状态集,包含其它状态的状态称为枝节点,不包含其它状态的状态称为叶节点,为方便单树描述,总是设计一个状态包含所有的状态节点,称为根节点。状态机的状态只能停留在叶节点,而不能停留在枝节点,每个枝节点需要指定一个子节点为它的默认子节点,以便状态机进入枝节点的时候能够停留到叶节点。
一般都用switch/case if/else方式实现。在少量状态(3个及其以下)的时候,不需要引入专门的状态机模块。
常规状态机模块实现涉及到的结构由上而下为:
顶层结构是状态机:当前状态id,缺省操作,状态表,
状态表:状态数组
状态结构:状态id,状态名,进入操作,退出操作,缺省操作,状态事件表(数组)
状态事件结构:操作,事件,下一状态的id
***************************************************************************************
从代码易读及美观角度来说,建议用switch/case来实现。 从经验来看,在一些稍大的程序设计中一般都会有状态机的实现,特别是在分层实现,协议栈实现,编解码方面。 下面通过一个简单的例子来看下。这个例子是zigbee精简协议栈实现中的【这里只讲APS层的有限状态机,这是开放源代码的,对于该协议总体上是分层来实现的,每一次层都有状态机来进行实际的数据业务处理】。
(1)定义各状态
typedef enum _APS_STATE_ENUM
{
APS_STATE_IDLE,
APS_STATE_COMMAND_START,
APS_STATE_GENERIC_TX_WAIT,
APS_STATE_NWK_PASSTHRU_WAIT,
APS_STATE_INDIRECT_GETDST,
APS_STATE_INDIRECT_TX,
#ifdef LRWPAN_COORDINATOR
APS_STATE_INJECT_INDIRECT,
#endif
APS_STATE_ACK_SEND_START,
APS_STATE_INDIRECT_TX_WAIT,
APS_STATE_INJECT_LOOPBACK,
APS_STATE_INDIRECT_LOOPBACK
} APS_STATE_ENUM;
(2)设计有限状态机函数
void apsFSM(void)
{
apsFSM_start://状态机入口 switch (apsState) //全局变量,指示当前状态
{
case APS_STATE_IDLE:
if (aps_pib.flags.bits.ackSendPending)
{
apsState = APS_STATE_ACK_SEND_START;//状态转换
goto apsFSM_start;
}
break;
case APS_STATE_ACK_SEND_START:
if (phyTxLocked())
{
break;
}
//send an ACK
//lock the TX buffer
phyGrabTxLock();
//we are now ready
apsFormatAck();
phy_pib.currentTxFlen = 0; //set frame length to zero, build from scratch
apsTxData(TRUE);
//data sent, release the RX buffer, will let RX FSM resume
aps_pib.flags.bits.ackSendPending = 0;
apsState = APS_STATE_GENERIC_TX_WAIT; break; case APS_STATE_GENERIC_TX_WAIT:
if (!apsTXIdle())
{
break;
}
//TX is finished, copy status
a_aps_service.status = apsTxFSM_status;
//release the TX buffer lock before exiting.
phyReleaseTxLock();
apsState = APS_STATE_IDLE;
if (aps_pib.flags.bits.indirectPending)
{
//have used this state to wait for finishing sending an
//ACK back to the source of an indirect transmit. Now
//finish resolving the indirect
goto apsFSM_start;
}
break; case APS_STATE_NWK_PASSTHRU_WAIT:
//for split-phase passthrus
if (nwkBusy())
{
break;
}
a_aps_service.status = a_nwk_service.status;
apsState = APS_STATE_IDLE;
break; case APS_STATE_INJECT_LOOPBACK:
//wait for RX to become idle
if (apsRxState != APS_RXSTATE_IDLE)
{
break;
}
//inject packet into RX FSM
apsInjectPacket(FALSE);
aps_pib.flags.bits.IsUsrBufferFree = 1;
apsState = APS_STATE_IDLE;
goto apsFSM_start;
default:
break;
}
}
(3)大致结构:状态机入口,状态转换,状态机退出从这个函数实现,我们可以简单了解有限状态机的实现过程。当程序的实现有多个状态的时候,也就是要根据不同的状态做不同的事情的时候,可以考虑把某个操作过程拆分为几个步骤【很多时候这是必须的】,对应状态机操作的几个不同状态。多数情况下,这些状态是多个操作可以共用的。一般的状态机函数都会提供一个状态退出操作,每个状态操作可以根据条件来判断是要退出,还是要转换进行下一个状态的。 状态机是程序设计时的一种思想,尤如设计模式,只有在恰当的时候用来才回体现出其价值。
本文出自 “bluefish” 博客,请务必保留此出处http://bluefish.blog.51cto.com/214870/163407
程序设计之有限状态机
【“算法与计算数学”之四书五经】《计算机程序设计艺术》
有限状态机和地址识别
单片机闹钟程序设计21
Java多线程程序设计解析
Win32汇编语言程序设计教程
几个shell程序设计小知识
最隐晦的程序设计指引
JSP动态网页程序设计详解
Java多线程程序设计详细解析1
看程序设计,体会中外语言不同
农民参与土地整治的程序设计
WINDOWS API 程序设计(第一章:开始) | 博客网
常用字符串长度计算函数 - 游戏程序设计 - 云世界日志
基于VC++的USB2.0接口通信程序设计
Windows 的多线程程序设计初步 - Austin Liu's Fashion - 博...
在线 平面设计三维设计 动画制作 网页制作 工具应用 程序设计
程序设计模式的有趣解释-追MM
程序设计游戏中如何加载人物,场景模型
大量免费的程序设计视频教程,学编程必备啊
高中语文学习策略指导、宏观程序设计与过程管理研究
Fortran基本用法小结-读彭国伦《Fortran 95 程序设计》的笔记-转
巧用头文件,多文件编译少发愁|浅谈实用“StdAfx” - 程序设计
巧用头文件,多文件编译少发愁|浅谈实用“StdAfx” - 程序设计 - 如鹏网 .