基于C语言的状态机框架和实现
Posted 吴跃前
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于C语言的状态机框架和实现相关的知识,希望对你有一定的参考价值。
本文的目的是基于C语言实现简单高效的状态机。例子是倒计时bomb。Bomb有两种状态,一种是设置状态,一种是倒计时。一旦开始计时,要想回到设置状态必须要调整code的值等于bomb预设的密码值,否则无法进行状态转换。倒计时到0就BOMB了啦。基于这个例子来实现状态机。状态机实现框架包括以下几个部分:
1. 状态
enum BombStates
SETTING_STATE,//设置
TIMING_STATE//倒计时
;
2. 触发状态转换的信号事件,用键盘模拟
enum BombSignals
UP_SIG, //按u
DOWN_SIG,//按d
ARM_SIG,//按a,状态转换键
TICK_SIG//0.1秒发出一个倒计时事件
;
3. 信号事件的数据结构
typedef struct EventTag
uint16_t sig; // BombSignals的赋值
/* 可以添加其他属性到这里 */
Event;
此外,还要定义信号事件附带的参数:
typedef struct TickEvtTag
Event super; //继承Event
uint8_t fine_time; //毫秒值,为0时代表倒计1秒
TickEvt;
4. 状态全局变量
typedef struct Bomb1Tag
uint8_t state; // BombStates状态赋值
uint8_t timeout; //当前倒计时间,为0游戏结束
uint8_t code; //用于调整数值,等于defuse密码才能转换状态
uint8_t defuse; //解除bomb的密码,需要预设
Bomb1;
5. 状态初始化
#define INIT_TIMEOUT 10
#define TRAN(target_) (me->state = (uint8_t)(target_))
void Bomb1_ctor(Bomb1 *me, uint8_t defuse)
me->defuse = defuse;
void Bomb1_init(Bomb1 *me)
me->timeout = INIT_TIMEOUT;
TRAN(SETTING_STATE);
6. 状态转换
void Bomb1_dispatch(Bomb1 *me, Event const*e)
switch (me->state)
case SETTING_STATE:
switch (e->sig)
case UP_SIG:
if (me->timeout < 60)
++me->timeout;
BSP_display(me->timeout);
break;
case DOWN_SIG:
if (me->timeout > 1)
--me->timeout;
BSP_display(me->timeout);
break;
case ARM_SIG:
me->code = 0;
TRAN(TIMING_STATE); /* transition to "timing"*/
break;
break;
case TIMING_STATE:
switch (e->sig)
case UP_SIG:
me->code <<= 1;
me->code |= 1;
BSP_display(me->code);
break;
case DOWN_SIG:
me->code <<= 1;
BSP_display(me->code);
break;
case ARM_SIG:
if (me->code ==me->defuse)
TRAN(SETTING_STATE); /*transition to "setting" */
break;
case TICK_SIG:
if (((TickEvt const*)e)->fine_time == 0)
--me->timeout;
BSP_display(me->timeout);
if (me->timeout ==0)
BSP_boom(); /* destroy the bomb */
break;
break;
7. 测试代码,用VC6.0
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include<windows.h>
static Bomb1 l_bomb; /* time bomb FSM*/
void main()
Bomb1_ctor(&l_bomb, 0x0D); /* the secret defuse code, 1101 binary */
printf("Time Bomb (Nested switch)\\n"
"Press 'u' for UP event\\n"
"Press 'd' for DOWNevent\\n"
"Press 'a' for ARM event\\n"
"Press <Esc> to quit.\\n");
Bomb1_init(&l_bomb); /* take the initialtransition */
for (;;) /* event loop */
static TickEvt tick_evt = TICK_SIG, 0;
Sleep(100); /* 100ms delay */
if (++tick_evt.fine_time == 10)
tick_evt.fine_time = 0;
printf("T(%1d)%c", tick_evt.fine_time,
(tick_evt.fine_time == 0)? '\\n' : ' ');
Bomb1_dispatch(&l_bomb, (Event *)&tick_evt); /* dispatch tickevent */
if (kbhit())
static Event const up_evt = UP_SIG ;
static Event const down_evt = DOWN_SIG ;
static Event const arm_evt = ARM_SIG ;
Event const *e = (Event *)0;
switch (getch())
case 'u': /* UP event*/
printf("\\nUP : ");
e = &up_evt; /* generate the UP event */
break;
case 'd': /* DOWNevent */
printf("\\nDOWN: ");
e = &down_evt; /* generate the DOWN event */
break;
case 'a': /* ARMevent */
printf("\\nARM : ");
e = &arm_evt; /* generate the ARM event */
break;
case '\\33': /*<Esc> key */
printf("\\nESC : Bye!Bye!");
exit(0);
break;
if (e != (Event *)0) /* keyboard event available? */
Bomb1_dispatch(&l_bomb,e); /* dispatch the event */
更多的嵌入式linux和android、物联网、汽车自动驾驶等领域原创技术分享请关注微信公众号:
以上是关于基于C语言的状态机框架和实现的主要内容,如果未能解决你的问题,请参考以下文章