我感觉普罗米修斯很多功能模块里面都用到了状态机的思路

比如圆环穿越的,比如最新的二维码降落的代码。

摘自:https://mp.weixin.qq.com/s/qRmBDH-VIHM26AaNFoD9dw

状态机思路在嵌入式开发中的应用说明及注意事项

strongerHuang strongerHuang 今天

关注+星标公众,不错过精彩内容

来源 | 玩转嵌入式

编排 | strongerHuang

学单片机开发的同学,基本都是从裸机开始的,裸机中一般都会使用到状态机。

可能很多人认为裸机中状态机比较low,怎么也要搞一个RTOS,更甚着要跑Linux才觉得高大上。其实,这都是误区,适合自己的才是最好的,做产品也一样,满足需求很重要。

目前裸机状态机依然很流行,我并不会觉得裸机很low,而且之前都还用状态机开发过好几款产品。

下面就来讲讲状态机的内容:

嵌入式专栏

1

状态机的概念

状态机是软件编程中的一个重要概念,比这个概念更重要的是对它的灵活应用,在一个思路清晰而且高效的程序中,必然有状态机的身影浮现。

比如:一个按键命令解析程序,就可以被看做状态机:本来在A状态下,触发一个按键后切换到了B状态;再触发另一个键后切换到C状态,或者返回到A状态。这就是最简单的按键状态机例子。实际的按键解析程序会比这更复杂些,但这不影响我们对状态机的认识。

进一步看,按键动作本身也可以看做一个状态机,一个细小的按键动作包含了:释放、抖动、闭合、抖动和重新释放等状态。

同样,一个串行通信的时序(不管它是遵循何种协议,标准串口也好、I2C也好;也不管它是有线的、还是红外的、无线的)也都可以看做由一系列有限的状态构成。

显示扫描程序也是状态机;通信命令解析程序也是状态机;甚至连继电器的吸合/释放控制、发光管(LED)的亮/灭控制又何尝不是个状态机。

当我们打开思路,把状态机作为一种思想导入到程序中去时,就会找到解决问题的一条有效的捷径。有时候用状态机的思维去思考程序该干什么,比用控制流程的思维去思考,可能会更有效。这样一来状态机便有了更实际的功用。

程序其实就是状态机:

也许你还不理解上面这句话。请想想看,计算机的大厦不就是建立在“0”和“1”两个基本状态的地基之上么?

嵌入式专栏

2

状态机的要素

状态机可归纳为4个要素,即现态条件动作次态。这样的归纳,主要是出于对状态机的内在因果关系的考虑。“现态”“条件”是因,“动作”“次态”是果。详解如下:

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

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

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

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

如果我们进一步归纳,把“现态”“次态”统一起来,而把“动作”忽略(降格处理),则只剩下两个最关键的要素,即:状态迁移条件

状态机的表示方法有许多种,我们可以用文字、图形或表格的形式来表示一个状态机。

纯粹用文字描述是很低效的,所以就不介绍了,接下来先介绍图形的方式。

嵌入式专栏

3

状态迁移图(STD)

状态迁移图(STD),是一种描述系统的状态、以及相互转化关系的图形方式。状态迁移图的画法有许多种,不过一般都大同小异。我们结合一个例子来说明一下它的画法,如图1所示:

图1状态迁移图

状态框
用方框表示状态,包括所谓的“现态”和“次态”。

条件及迁移箭头
用箭头表示状态迁移的方向,并在该箭头上标注触发条件。

节点圆圈
当多个箭头指向一个状态时,可以用节点符号(小圆圈)连接汇总。

动作框
用椭圆框表示。

附加条件判断框
用六角菱形框表示。

状态迁移图和我们常见的流程图相比有着本质的区别,具体体现为:在流程图中,箭头代表了程序PC指针的跳转;而在状态迁移图中,箭头代表的是状态的改变。

我们会发现,这种状态迁移图比普通程序流程图更简练、直观、易懂。这正是我们需要达到的目的。

嵌入式专栏

4

状态迁移表

除了状态迁移图,我们还可以用表格的形式来表示状态之间的关系。这种表一般称为状态迁移表。

表1就是前面介绍的那张状态迁移图的另一种描述形式。

表1状态迁移表

采用表格方式来描述状态机,优点是可容纳更多的文字信息。例如,我们不但可以在状态迁移表中描述状态的迁移关系,还可以把每个状态的特征描述也包含在内。

如果表格内容较多,过于臃肿不利于阅读,我们也可以将状态迁移表进行拆分。经过拆分后的表格根据其具体内容,表格名称也有所变化。

比如,我们可以把状态特征和迁移关系分开列表。被单独拆分出来的描述状态特征的表格,也可以称为“状态真值表”。这其中比较常见的就是把每个状态的显示内容单独列表。这种描述每个状态显示内容的表称之为“显示真值表”。同样,我们把单独表述基于按键的状态迁移表称为“按键功能真值表”。另外,如果每一个状态包含的信息量过多,我们也可以把每个状态单独列表。

由此可见,状态迁移表作为状态迁移图的有益补充,它的表现形式是灵活的。

状态迁移表优点是信息涵盖面大,缺点是视觉上不够直观,因此它并不能取代状态迁移图。比较理想的是将图形和表格结合应用。用图形展现宏观,用表格说明细节。二者互为参照,相得益彰。

嵌入式专栏

5

状态机思路实现一个时钟程序

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

图2时钟程序状态迁移图

把这张图稍做归纳,就可以得到它的另一种表现形式——状态迁移表,如表2所示。

表2时钟程序状态迁移表

嵌入式专栏

6

状态机应用的注意事项

基于状态机的程序调度机制,其应用的难点并不在于对状态机概念的理解,而在于对系统工作状态的合理划分。

初学者往往会把某个“程序动作”当作是一种“状态”来处理。我称之为“伪态”。那么如何区分“动作”和“状态”。本匠人的心得是看二者的本质:

“动作”是不稳定的,即使没有条件的触发,“动作”一旦执行完毕就结束了;

而“状态”是相对稳定的,如果没有外部条件的触发,一个状态会一直持续下去。

初学者的另一种比较致命的错误,就是在状态划分时漏掉一些状态。我称之为“漏态”。

伪态和漏态这两种错误的存在,将会导致程序结构的涣散。因此要特别小心避免。

嵌入式专栏

7

更复杂的状态机

前面介绍的是一种简单的状态结构。它只有一级,并且只有一维,如图3所示。

图3 线性状态机结构

如果有必要,我们可以建立更复杂的状态机模型。

1.多级状态结构
状态机可以是多级的。在分层的多级状态机系统里面,一个“父状态”下可以划分多个“子状态”,这些子状态共同拥有上级父状态的某些共性,同时又各自拥有自己的一些个性。

在某些状态下,还可以进一步划分子状态。比如,我们可以把前面的时钟例子修改如下:

把所有和时钟功能有关的状态,合并成1个一级状态。在这个状态下,又可以划分出3个二级子状态,分别为显示时间、设置小时、设置分钟;

同样,我们也可以把所有和闹钟功能有关的状态,合并成1个一级状态。在这个状态下,再划分出4个二级子状态,分别为显示闹钟、设置“时”、设置“分”、设置鸣叫时间。

我们需要用另一个状态变量(寄存器)来表示这些子状态。

子状态下面当然还可以有更低一级的孙状态(子子孙孙无穷尽也),从而将整个状态体系变成了树状多级状态结构,如图4所示。

图4树状多级状态结构

2.多维状态结构
状态结构也可以是多维的。从不同的角度对系统进行状态的划分,这些状态的某些特性是交叉的。比如,在按照按键和显示划分状态的同时,又按照系统的工作进程做出另一种状态划分。这两种状态划分同时存在,相互交叉,从而构成了二维的状态结构空间。

举一个这方面的例子,如:空调遥控器,如图5所示。

图5多维状态机结构

同样,我们也可以构建三维、四维甚至更多维的状态结构。每一维的状态都需要用一个状态变量(寄存器)来表示。

无论多级状态结构和多维状态结构看上去多么迷人,匠人的忠告是:我们依然要尽可能地简化状态结构,能用单级、单维的结构,就不要给自己找事,去玩那噩梦般的复杂结构。

状态机思路在嵌入式开发中的应用说明及注意事项(普罗米修斯中不少功能节点用了状态机的方法来写)相关推荐

  1. Go:普罗米修斯中间件开发

    目录  Prometheus介绍  Grafana介绍和使用  Prometheus中间件开发  测试Prometheus中间件 Prometheus介绍 分布式监控系统 完全被开源,使用Go ...

  2. 状态机思路在嵌入式开发中的应用详解

    关注.星标公众号,直达精彩内容 ID:技术让梦想更伟大 整理:李肖遥 状态机的概念 状态机是软件编程中的一个重要概念.比这个概念更重要的是对它的灵活应用.在一个思路清晰而且高效的程序中,必然有状态机的 ...

  3. 嵌入式开发中常用的几种通信接口总结

    关注.星标公众号,直达精彩内容 在嵌入式系统中,板上通信接口是指用于将各种集成电路与其他外围设备交互连接的通信通路或总线. 以下内容为常用板上通信接口:包括I2C.SPI.UART.1-Wire: I ...

  4. 【经验总结】10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的?(文末赠书5本)

    [经验总结]一位近10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的? RT-Thread绝对可以称得上国内优秀且排名靠前的操作系统,在嵌入式IoT领域一直享有盛名.近些年,物联网产 ...

  5. 嵌入式开发输出调试信息的几种方法(常规法及非常规法)

    这篇文章对于研发查找问题和测试都有很大帮助,在这里保存记录一下. 论语>有云:"工欲善其事,必先利其器".输出调试信息是软件开发中必不可少的调试利器,在出现bug时如果没有调 ...

  6. ubuntu执行编译好的文件显示文件不存在_嵌入式开发 | 什么是交叉编译(CROSS_COMPILE)...

    在嵌入式系统开发中,经常会听到一个词:交叉编译.到底什么是"交叉编译"呢?为什么要使用"交叉编译"呢?今天这篇文章,我们来讨论下这个话题. 在讨论交叉编译之前, ...

  7. RISC-V嵌入式开发准备篇1:编译过程简介

    原文出处:https://mp.weixin.qq.com/s/-syKN0DibKGGPCllaeNqMg 随着国内第一本RISC-V中文书籍<手把手教你设计CPU--RISC-V处理器篇&g ...

  8. 嵌入式开发:嵌入式 Linux – Shell 脚本 101

    Android和Linux操作系统在过去几年变得非常流行.由于它们的开源性质,成本是合理的,值得庆幸的是,大量的工程师已经加入到将这些操作系统移植到几乎所有可以想象的平台的努力中来.它们的广泛使用使得 ...

  9. 基于STM 32、矩阵键盘和独立键盘实现LCD显示的智能计算器(带括号的加减乘除运算、混合四则运算)——普中科技单片机开发试验仪嵌入式开发

    0 引言 智能计算器是嵌入式开发的入门项目,本章使用STM 32芯片作为CPU,并将矩阵键盘和独立键盘作为输入外设,LCD1602作为显示屏,实现可输入的可视化智能计算器. 备注:最终生成的可执行HE ...

最新文章

  1. Xtrabackup实现数据的备份与恢复
  2. SQLServer数据的基本操作:简单的增、删、改、查
  3. 云计算的 2020:云原生崛起,重新定义软件!
  4. java 方法 示例_Java语言环境getISOCountries()方法与示例
  5. 计算机设计思想 —— 解耦(分离)与内聚
  6. 引用的本质是const指针
  7. oracle宣传片,会声会影X8震撼的宣传片效果该怎么制作?
  8. 积木导出pdf打不开文件,后台报空指针
  9. 神经网络的深度、宽度
  10. CameraBag Photo 2020 for Mac(Mac滤镜软件)
  11. java 导出word 带图片
  12. LeetCode刷题攻略
  13. 1104-捷径(DP)
  14. 【计算机网络】实验报告一:验证性实验
  15. 塞雷三分钟漫画中国史4
  16. 编程趣味知识:固执的“and”和变通的“or”
  17. 微软提出MiniViT | 把DeiT压缩9倍,性能依旧超越ResNet等卷积网络
  18. 牛腩新闻发布--过程或函数 'news_selectByCaId' 需要参数 '@caid',但未提供该参数(一)
  19. 解决PYTHON爬取:RESPONSE.STATUS_CODE为418、403 问题
  20. 每天5分钟机器学习算法:支持向量机的目标函数是怎么来的?

热门文章

  1. Ubuntu Xfce桌面系统设置项
  2. msk 频偏_基于MSP430的MSK调制解调实现.doc
  3. Excel的照相机功能(转载+亲自实践)
  4. Html5游戏开发攻略(API篇)
  5. python xy 官网_pythonxy 安装
  6. MyBatis学习笔记2 ——第一个MyBatis程序
  7. 如何用人工的方式将Excel里的一堆数字变成一个数组
  8. 微前端 - qiankun
  9. 一分钟了解矩阵、方阵、对角矩阵、单位矩阵之间的关系
  10. java面向对象基础练习1(坐标点移动)