状态机编程
转载正文2
状态机思路在单片机程序设计中的应用状态机的概念状态机是软件编程中的一个重要概念。比这个概念更重要的是对它的灵活应用。在一个思路清晰而且高效的程序中,必然有状态机的身影浮现。比如说一个按键命令解析程序,就可以被看做状态机:本来在A状态下,触发一个按键后切换到了B状态;再触发另一个键后切换到C状态,或者返回到A状态。这就是最简单的按键状态机例子。实际的按键解析程序会比这更复杂些,但这不影响我们对状态机的认识。进一步看,击键动作本身也可以看做一个状态机。一个细小的击键动作包含了:释放、抖动、闭合、抖动和重新释放等状态。同样,一个串行通信的时序(不管它是遵循何种协议,标准串口也好、I2C也好;也不管它是有线的、还是红外的、无线的)也都可以看做由一系列有限的状态构成。显示扫描程序也是状态机;通信命令解析程序也是状态机;甚至连继电器的吸合/释放控制、发光管(LED)的亮/灭控制又何尝不是个状态机。当我们打开思路,把状态机作为一种思想导入到程序中去时,就会找到解决问题的一条有效的捷径。有时候用状态机的思维去思考程序该干什么,比用控制流程的思维去思考,可能会更有效。这样一来状态机便有了更实际的功用。程序其实就是状态机。也许你还不理解上面这句话。请想想看,计算机的大厦不就是建立在“0”和“1”两个基本状态的地基之上么?
状态机的要素状态机可归纳为4个要素,即现态、条件、动作、次态。这样的归纳,主要是出于对状态机的内在因果关系的考虑。“现态”和“条件”是因,“动作”和“次态”是果。详解如下:①现态:是指当前所处的状态。②条件:又称为“事件”。当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。③动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。④次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。如果我们进一步归纳,把“现态”和“次态”统一起来,而把“动作”忽略(降格处理),则只剩下两个最关键的要素,即:状态、迁移条件。状态机的表示方法有许多种,我们可以用文字、图形或表格的形式来表示一个状态机。纯粹用文字描述是很低效的,所以就不介绍了。接下来先介绍图形的方式。
状态迁移图(STD)状态迁移图(STD),是一种描述系统的状态、以及相互转化关系的图形方式。状态迁移图的画法有许多种,不过一般都大同小异。我们结合一个例子来说明一下它的画法,如图1所示。


用状态机思路实现一个时钟程序接下来,我将就状态机的应用,结合流程图、状态迁移图和状态迁移,举一个实际例子。下面这张图是一个时钟程序的状态迁移图,如图2所示。





转载正文3
实际的状态机编程思想例子看看小时候玩的5块钱那种最简单的电子表。只有2个按钮就能操作。暂且称为按钮A和按钮B现给出一个完整的功能文字描述:在显示时间时按A,屏幕显示变成日期在显示日期时按A,屏幕显示变成秒钟在显示秒钟时按A,屏幕显示变成时间在显示秒钟时按B,秒钟归0在显示时间时按B,屏幕 时间、日期交替显示。在时间、日期交替显示时按B,屏幕“时”闪烁在“时”闪烁时按B,屏幕“时”加1,超过23回0在“时”闪烁时按A,屏幕“分”闪烁在“分”闪烁时按B,屏幕“分”加1,超过59回0在“分”闪烁时按A,屏幕“月”闪烁在“月”闪烁时按B,屏幕“月”加1,超过12回0在“月”闪烁时按A,屏幕“日”闪烁在“日”闪烁时按B,屏幕“日”加1,超过31回0在“日”闪烁时按A,屏幕回到时间显示如果按照新手的思路,尝试去画流程图,很快就会陷入一头雾水:你会发现实现这个功能的程序根本就没有“确定的流程”。因为程序实际流程是根据人的操作而变化的。程序运行到什么地方,完全取决于两个键的次序,有无数种次序组合,根本不可能画出流程图来。但是我们会发现,这个电子表功能的“语言描述”在语法上似乎有某种规律,就是:当系统处于某状态(S1)时,如果发生了什么事情(E),就执行某功能(F),然后系统变成新状态(S2)只要能用上面这句话描述的系统,都可以用一种状态跳转机制很方便的实现,并且一句话其实就是一个if(...),无论有多少多复杂的功能,只要能用上面这句话描述,都可以通过状态机编程实现。 我们将它们抽象。整个系统中有2个事件分别是:A按下,B按下A按下(可以是中断)时执行:{if(Status==TIME) //当显示时间时按下A键{Status=DATE //变成显示日期}if(Status==DATE) //当显示日期时按下A键{Status=SEC //变成显示秒钟}if(Status==SEC) //当显示秒钟时按下A键{Status=TIME //变成显示时间}if(Status==SET_HOUR) //当设置“小时”时按下A键{Status=SET_MINUT //变成设置“分钟”}if(Status==SET_MINUT) //当设置“分钟”时按下A键{Status=SET_MONTH //变成设置“月”}..........}B按下(可以是中断)时执行:{if(Status==SEC) //当显示秒钟时按下B键{Secound=0 //秒归0}if(Status==TIME) //当显示时间时按下B键{Status=TIMEDATE //变成时间日期交替显示}if(Status==TIMEDATE) //当日期交替显示时按下B键{Status=SET_HOUR //变成设置“时”(时闪烁)}if(Status==SET_HOUR) //当设置“时”时按下B键{Status=Hour++ //时加1if(Hour>23) Hour=0; }.......... }和语言描述完全一致,很快就能写完程序。这就是最简单的状态机思想。当然,上述一大堆if可以用switch case来实现实际中,大量的并发过程都可以表述为状态跳转关系,从而将CPU从过程中解放出来,只需处理状态关系,因为真正需要CPU的是状态变化的时刻,而不是过程中大量的等待,这样大量的并发过程都可以并行处理。
评论