0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

嵌入式软件架构设计之状态机

汽车电子技术 来源:大橙子疯嵌入式 作者:大橙子疯 2023-02-15 15:49 次阅读

前言

功能业务代码写多了,回看代码会发现用if-else if-else用的越来越多,因为有很多场景需要区分,不同场景下的功能不一样,因此需要通过if做判断,场景一旦多了起来起来,用if-else if-else就会越来越多。

这里的if-else if-else通常是用来区分不同场景下的功能实现,和上篇提到的表驱动编程还不太一样。

为了避免这种情况,本编介绍一种开发方法-- 状态机编程

为什么需要状态机编程?相信很多人在实现if判断的时候,偶尔会出现不小心漏掉或者写错一些触发条件,导致功能出现异常的问题,特别是一些复杂的逻辑条件,一大堆的&&/||/()等眼花缭乱的复杂逻辑,写完之后恐怕自己都得检查好一会,担心是不是哪个条件不能正常触发。状态机通常采用 switch-case实现。

那么状态机的引入解决了哪些问题呢?

  • 当程序有多个状态时,规范了程序的状态转换,避免了一些引入一些复杂的判断逻辑。
  • 规范了程序在不同状态下的实现和所能提供的能力。
  • 在能力上可以进行横向扩展,提供新的状态来完善现有逻辑
  • 逻辑清楚,实现过程会多考虑一些情况,方便定位问题所在

介绍

什么是状态机?

状态机是有限状态自动机(FSM)的简称,是现实事物运行规则抽象而成的一个 数学模型

简单理解就是:现实事物是有不同状态的,比如灯,就有“亮”和“灭”两种状态,再复杂抽象一点,增加一个“损坏”状态,那这属于异常情况了。

概念

  • 现态:当前所处的状态,一个状态机至少要包含两个状态,某一时刻只能是一种状态,比如刚才说到的灯,就有“亮”和“灭”两种状态
  • 条件:又称事件,执行某个操作的触发条件或者口令,比如灯通过开关控制,操作开关就是一个事件
  • 动作:事件发生以后要执行动作,比如开关按下开关,灯亮,松开则灭
  • 次态:条件满足后要迁往的新状态,比如开关按下后灯从当前灭的状态变为亮的状态

图片

用过"RTOS"的朋友应该也知道任务的几种状态,任务的四种状态分别是: 就绪态、运行态、阻塞态、挂起态 ,不会同时出现两种及两种以上的状态存在,OS 根据当前的状态,和任务优先级、滴答时钟、主动睡眠等条件进行任务的状态切换。

状态机的动作类型

  • 进入动作:在进入状态时进行
  • 退出动作:在退出状态时进行
  • 输入动作:依赖于当前状态 和 输入条件进行
  • 转移动作:在进行特定转移时进行

实现

首先,看一个简单的例子,在不同场景下实现控制电机的功能:设备开机启动三次电机、开关按下一次启动一次、关机启动三次电机。采用非状态机的写法,通过各种标志位去判断设备是否需要控制电机,什么条件下退出等。

只是简单的实现一下,可能其中也有一些状态机的思想吧(毕竟状态机编程思想已经在脑海里,不可避免吧),不过我还是尽量还原我初次编程期间的实现这个功能的逻辑思想吧,勿怪。

/* 控制电机函数 */
void MotorCtrlTask(void)
{
    if (ctrlCnt)
    {
        MotorCtrl(ON);
        delay(1);
        MotorCtrl(OFF);
    }
    else
    {
        MotorCtrl(OFF);
    }
}

int isPowerOn = true;
int isPowerOff = false;
int ctrlCnt = 0;

void main(void)
{   
    while (1)
    {
        if (isPowerOn)
        {
            isPowerOn = false;
            ctrlCnt = 3;
        }

        if (keyPress)
        {
            keyPress = false;
            ctrlCnt = 1;
        }

        if (...)  // 关机条件
        {
            if (ctrlCnt == 0 && !isPowerOff && !isPowerOn)
            {
                isPowerOff = true;
                ctrlCnt = 3;
            }
        }

        MotorCtrlTask();

        if (ctrlCnt > 0)
            ctrlCnt--;
        else
        {
            if (ctrlCnt == 0 && isPowerOff && !isPowerOn)
            {
                return;
            }
        }
    }
}

通过采用状态机编程的方式,首先考虑的就是有三种状态:开机、关机和工作状态,先理清楚三种状态之间转换的条件和当前状态需要执行的相关功能,然而在实现过程中就会意识到还需要增加一种过渡状态:关机准备中(关机过程中需要执行的一系列操作)。

只有逻辑清晰了,才会下意识的察觉少了一些东西了,特别是一些临界处理等。

int sysState = POWER_OFF; // 默认关机状态
int ctrlCnt = 0;

/* 控制电机函数 */
void MotorCtrlTask(void)
{
    if (ctrlCnt)
    {
        MotorCtrl(ON);
        delay(1);
        MotorCtrl(OFF);
    }
    else
    {
        MotorCtrl(OFF);
    }
}

void main(void)
{
    while (1)
    {
        switch (sysState)
        {
            case POWER_OFF: // 关机状态
                sysState = POWER_ON; // 自动切换成开机状态
                ctrlCnt = 3;
                break;
            case POWER_ON:  // 开机过程状态
                ... // 开机过程中的其他功能

                if (ctrlCnt == 0) // 控制结束自动切换工作状态
                {
                    sysState = WORKING;
                    break;
                }
                break;
            case WORKING:  // 工作状态
                if (...) // 关机条件
                {
                    sysState = POWER_OFF_READY;
                    ctrlCnt = 3;
                    break;
                }

                if (keyPress)
                {
                    keyPress = false;
                    ctrlCnt = 1;
                }
                break;

            case POWER_OFF_READY:  // 关机准备中
                ... // 关机准备中的其他功能

                if (ctrlCnt == 0) // 控制结束自动退出
                {
                    sysState = POWER_OFF;
                    return; // 退出程序
                }
                break;

            default:
                break;
        }

        MotorCtrlTask();

        if (ctrlCnt > 0)
            ctrlCnt--;
    }
}

总结:从上述两份代码看,你觉得哪一个逻辑更清晰呢?非状态机实现方式还有一些异常处理没有实现,比如开机过程中在启动三次调节电机过程中按下会有什么现象呢,为了避免这种情况又需要加入多少if条件判断呢?

适用场景

状态机应用范围挺广的,不止是在C语言中,其他都能使用,准确来说这个属于一种编程思想。特别是业务功能,状态机是常用的。

比如常常使用的模块也有状态机的身影:比如按键的按下和松开,按下又包括按下瞬间、多次按下、持续按下、松开瞬间和持续松开等

通常状态机和表驱动可以结合使用,状态机的现态、条件、动作和次态作为数据,执行这些状态切换的作为逻辑。完全可以根据实际情况灵活使用。

代码参考:

菜单 :菜单控制,可以这样理解:当前菜单界面为现态、菜单进入和退出为条件、菜单切换时的函数执行为动作、上下级菜单理解为次态,其中菜单选项表就灵活使用了状态机和表驱动的方式。

https://gitee.com/const-zpc/menu.git

ESP8266 :AT指令数据表,包含指令、期望响应、时间和函数指针【后续的动作】等,可以这样理解:数组索引当前值为现态、收到响应和超时为条件、收到响应或超时执行的函数为动作、数组索引的未来值为次态

https://gitee.com/const-zpc/esp8266
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 状态机
    +关注

    关注

    2

    文章

    492

    浏览量

    27529
  • fsm
    fsm
    +关注

    关注

    0

    文章

    35

    浏览量

    12822
  • 数学模型
    +关注

    关注

    0

    文章

    83

    浏览量

    11933
收藏 人收藏

    评论

    相关推荐

    嵌入式状态机的几种大牛才懂的操作

    状态机嵌入式软件中随处可见,可能你会说状态机有什么难的,不就是 switch 吗? switch仅仅是最基础的一个点,关于状态机的更多操作
    发表于 11-17 10:41 1470次阅读
    <b class='flag-5'>嵌入式</b><b class='flag-5'>状态机</b>的几种大牛才懂的操作

    嵌入式软件开发中常用的状态机编程实现

    嵌入式软件开发中,状态机编程是一个十分重要的编程思想,它也是嵌入式开发中一个常用的编程框架。掌握了状态机编程思想,可以更加逻辑清晰的实现复
    发表于 09-06 10:25 2002次阅读

    为何要进行嵌入式软件架构设计?如何设计?

    为何要进行嵌入式软件架构设计?如何进行嵌入式软件架构设计?
    发表于 11-01 06:31

    嵌入式状态机编程的概念是什么

    干货 | 嵌入式状态机编程干货篇文章描述了基本的状态机编程概念,感觉还可以。如果在搭上事件驱动框架,就可以写一个简单的RTOS了,这个OS可以作为一种不可剥夺型内核。...
    发表于 12-22 06:25

    嵌入式软件架构设计资料分享

    作为程序员,我觉得如果要走的更远必须要成为工程师,毕竟年龄和资历都摆在那里了。所以就让我这个老程序员浅谈一下嵌入式软件架构设计。我参考的也是一篇博文。原图如下![在这里插入图片描述](?x-oss-process=image/w
    发表于 12-24 07:09

    状态机嵌入式系统中的应用

    为了便于研究和描述状态机嵌入式前后台软件系统中的应用,本文将以移动2G光纤直放站近端的监控软件案例来阐述和说明。
    发表于 05-23 10:48 2157次阅读
    <b class='flag-5'>状态机</b>在<b class='flag-5'>嵌入式</b>系统中的应用

    嵌入式软件架构设

    嵌入式软件架构的设计,帮助我们建立合理,有效的软件架构
    发表于 11-09 17:34 19次下载

    嵌入式软件状态机的抽象与实现

    文中提出了 在嵌入式软件中把状态机作为一个独立模块从控制模块中抽象出来的思想 , 描述了 抽象出来的状态机模块 。 并介绍了 如何将这种状态机
    发表于 03-22 15:47 1次下载

    有限状态机嵌入式系统中的实现及应用

    如何使嵌入式软件代码更加可靠 增强程序的可维护性 一直以来都是嵌入式程序员追 求的目标。论述了有限状态机的原理和其实现方法;采用状态机方法编
    发表于 03-22 15:40 1次下载

    有限状态机嵌入式软件中的应用

    有限状态机嵌入式软件中的应用,感兴趣的小伙伴们可以看看。
    发表于 07-26 10:43 27次下载

    嵌入式UI架构设计漫谈

    嵌入式UI架构设计漫谈
    发表于 11-03 17:36 15次下载
    <b class='flag-5'>嵌入式</b>UI<b class='flag-5'>架构设</b>计漫谈

    嵌入式状态机的设置

    状态机嵌入式软件中随处可见,可能你会说状态机有什么难的,不就是 switch 吗?
    的头像 发表于 11-02 09:04 1086次阅读

    嵌入式状态机的编程优点分析

    嵌入式状态机编程是真的好用,写出来的程序结构非常清晰!所以平时用的也比较多。
    的头像 发表于 02-25 16:21 838次阅读

    嵌入式状态机的设计与实现

    嵌入式状态机是一种常用的软件设计模式,它能够提高代码的可读性和可维护性。状态机是一个抽象的概念,它描述了一个系统或者组件的不同状态以及在不同
    的头像 发表于 04-14 11:55 1774次阅读

    C语言实现嵌入式状态机简单描述与应用

    嵌入式状态机是一种常用的软件设计模式,它能够提高代码的可读性和可维护性。
    发表于 05-20 14:52 1690次阅读