嵌入式软件中状态机的几种操作

嵌入式软件中状态机的几种操作

1、状态机的术语

  • 现态:是指当前所处的状态。

  • 条件:又称为“事件”,当一个条件被满足,将会触发一个动作,或者执行一次状态的迁移。

  • 动作:条件满足后执行的动作。动作执行完毕后,可以迁移到新的状态,也可以仍旧保持原状态。动作不是必需的,当条件满足后,也可以不执行任何动作,直接迁移到新状态。

  • 次态:条件满足后要迁往的新状态。“次态”是相对于“现态”而言的,“次态”一旦被激活,就转变成新的“现态”了。

2、当前任务需求

在这里插入图片描述
如图,是一个定时计数器,计数器存在两种状态,一种为设置状态,一种为计时状态。

  • 设置状态

“+” “-” 按键对初始倒计时进行设置
当计数值设置完成,点击确认键启动计时 ,即切换到计时状态

  • 计时状态

按下“+” “-” 会进行密码的输入“+”表示1 ,“-”表示输入0 ,密码共有4位
确认键:只有输入的密码等于默认密码,按确认键才能停止计时,否则计时直接到零,并执行相关操作

2、嵌套switch实现嵌套

/***************************************
1.列出所有的状态
***************************************/
typedef enum{
    SETTING,
    TIMING
} STATE_TYPE;

/***************************************
2.列出所有的事件
***************************************/
typedef enum{
    UP_EVT,
    DOWN_EVT,
    ARM_EVT,
    TICK_EVT
} EVENT_TYPE;

/***************************************
3.定义和状态机相关结构:时间显示框会出现的状态
***************************************/
struct  bomb
{
    uint8_t state;
    uint8_t timeout;
    uint8_t code;
    uint8_t defuse_code;
} bomb1;

/***************************************
4.初始化状态机
***************************************/
void bomb1_init(void)
{
    bomb1.state = SETTING;
    bomb1.defuse_code = 6;    //0110 
}

/***************************************
5. 状态机事件派发
***************************************/
void bomb1_fsm_dispatch(EVENT_TYPE evt ,void* param)
{
    switch(bomb1.state)
    {
        case SETTING:
        {
            switch(evt)
            {
                case UP_EVT:    // "+"   按键按下事件
                    if(bomb1.timeout< 60)  
                        ++bomb1.timeout;
                    bsp_display(bomb1.timeout);
                break;
                
                case DOWN_EVT:  // "-"   按键按下事件
                    if(bomb1.timeout > 0)  
                        --bomb1.timeout;
                    bsp_display(bomb1.timeout);
                break;
                
                case ARM_EVT:   // "确认" 按键按下事件
                    bomb1.state = TIMING;
                    bomb1.code  = 0;
                break;
            }
        } 
        break; 
        
        case TIMING:
        {
            switch(evt)
            {
                case UP_EVT:     // "+"   按键按下事件
                    bomb1.code = (bomb1.code <<1) | 0x01;
                break;
                
                case DOWN_EVT:  // "-"   按键按下事件
                    bomb1.code = (bomb1.code <<1); 
                break;
                
                case ARM_EVT:   // "确认" 按键按下事件
                    if(bomb1.code == bomb1.defuse_code)
                    {
                        bomb1.state = SETTING;
                    }
                    else
                    {
                        bsp_display("bomb!")
                    }
                break;
                
                case TICK_EVT:
                    if(bomb1.timeout)
                    {
                        --bomb1.timeout;
                        bsp_display(bomb1.timeout);
                    }
                    if(bomb1.timeout == 0)
                    {
                        bsp_display("bomb!")
                    }
                break;      
            }   
        }
        break;
    }
}

-----------------------------------
优点:

简单,代码阅读连贯,容易理解

缺点:

当状态或事件增多时,代码状态函数需要经常改动,状态事件处理函数会代码量会不断增加

状态机没有进行封装,移植性差。

没有实现状态的进入和退出的操作。进入和退出在状态机中尤为重要:

进入事件:只会在刚进入时触发一次,主要作用是对状态进行必要的初始化

退出事件:只会在状态切换时触发一次 ,主要的作用是清除状态产生的中间参数,为下次进入提供干净环境

3、二维转态表

状态机可以分为状态和事件 ,状态的跃迁都是受事件驱动的,因此可以通过一个二维表格来表示状态的跃迁。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值