- 细节
- 类别: 设计
设计一个状态机来解决问题
状态机常用于解决某些类型的控制问题,其中控制流可以描述为在多个不同状态间的转换。状态机有多种不同的定义和实际描述;从理论层面来说,它就像一个自动机,通过改变自身状态来响应特定的刺激。为了给出一个具体而通用的表达,例如,可以将其视为一个通过遍历一系列状态来响应输入字符串的自动机。如果达到期望状态,则输入字符串等价于该通用表达式。
在控制软件中,通常将状态机的有限性和确定性作为其计算模型的基础。这从根本上意味着可能的状态或状态组合的数量是有限的,并且状态机在任何给定时间只能处于一个状态。我们稍后会看到,一次只能处于一个状态的规则可以放宽,但关键在于状态流的状态是一个确定性属性。
状态: 状态可以看作是对系统当前状态的简写。举个简单的例子,考虑一个外围设备,它在最高层级上可以有三种可选的工作模式:开、关或待机。
事件:事件是状态机的输入消息。事件可以导致状态机改变状态。例如,在待机模式下按下电视机的开机按钮就是一个事件,如果运气好的话,它会唤醒电视机,使其进入开机状态。
转换: 转换是从一个状态到另一个状态的有向路径。转换通常用事件名称来指定,表明当状态机处于转换的起始状态时,如果指定的事件发生,则转换将发生。最终结果是状态机的状态变为转换所指向的状态。为了使情况更复杂——或者更确切地说,为了增强状态机表示法的表达能力——转换可以由看门狗条件“保护”,只有满足这些条件,转换才会发生。
动作 ——动作是指状态机在特定时间点要执行的活动。通常,动作会在环境中执行某些任务,例如从 I/O 设备读取数据或向其写入数据。动作可以与状态转换相关联,也可以指定为特定状态下的输入和输出动作。
这些概念是状态机设计形式化方法的基础,我们将在 UML 建模语言的子集中找到它。
除了基础知识之外,
我们来看一个教科书中的基本例子:面向状态的问题。我们尝试在状态机上找到一个合适的实现方案。在这种情况下,实际上有两种不同的解决方案,各有优缺点,选择取决于对它们利弊的评估。
问题:“一条繁忙的主干道与一条车流量较小的支路交叉。支路上安装了检测器,当有车辆等待穿越主干道时,检测器会触发C形信号灯。交通信号控制器应按以下方式运行:只要支路上没有检测到车辆,主干道方向的交通信号灯应保持绿灯。如果检测到支路上有车辆,主干道方向的交通信号灯应由黄灯变为红灯,支路上的交通信号灯变为绿灯。只要检测到支路上有车辆,支路上的交通信号灯就应保持绿灯,但不会持续一段设定的时间间隔,以确保主干道上的交通畅通。如果满足上述条件,支路上的交通信号灯将由绿灯变为黄灯,然后再变为红灯,主干道方向的交通信号灯恢复为绿灯。即使有车辆等待穿越主干道,主干道也应保持绿灯一段时间。”¹
本练习侧重于硬件层面,但稍加修改,即可应用于软件环境。请注意,示例中采用的是黄灯总是单独出现的约定(世界上某些地区使用其他约定)。但这实际上并不影响问题的难度;它只是让追踪可能的颜色组合变得更容易。
状态机设计的简单方法可以描述如下:
1. 识别事件和动作;
2. 识别状态;
3. 按层次结构分组;
4. 按并发性分组;
5. 添加状态转换;
6. 添加同步。
这并非一套固定的方案,而是一种无论选择何种工具和实现方法,通常都有助于构建解决方案的方法。
让我们深入探讨一下。
首先,我们来审视问题描述,寻找可能的事件和动作。在状态机的上下文中,事件的构成要素是什么?简而言之,事件是可能触发状态机改变状态并执行某些动作的触发器。对于信号量而言,我们可以找到一系列潜在事件:
以下几个时间段与此相关:
有车辆通行
时,该时间也可作为本地道路信号灯保持绿灯的固定时间
两条道路信号灯从黄灯切换到绿灯和从黄灯切换回绿灯的延迟时间。
延误间隔本身并非事件;相反,间隔的结束可以被视为一个事件。实际上,这让我们得到两个事件:一个是两条道路绿灯期间的长间隔事件,另一个是红绿灯交替期间的短且均匀的延误事件。
这样我们就得到了三个事件,可以分别称为本地道路交通事件 (LocalRoadTrafficEvent)、长事件 (LongEvent) 和短事件 (ShortEvent)。
那么,在这个问题中,什么才算是一个动作呢?改变交通信号灯的颜色就是一个典型的动作。唯一的问题是,同时改变两条道路上的信号灯算作一个动作还是两个动作。答案其实取决于约定俗成。我们可以将其视为两个独立的动作,分别处理一条道路;也可以将其视为一个动作。我选择将其视为两个独立的动作,原因稍后会解释。
我选择将这两个动作分别命名为 ConfigureLocalRoadLight() 和 ConfigureMainRoadLight();每个动作都接受一个颜色参数,用于指定所需的颜色。
这里的想法是,我们选择的事件会在特定情况下触发交通信号灯颜色的变化。
我们还需要一种方法来跟踪时间间隔,因此引入了一个名为“定时器操作”的特殊操作。它的作用是启动一个指定时间间隔的计时器,并跟踪一个在计时器结束时触发的事件。为简单起见,我们将此定时器操作称为 `ActionTemp()`。
为了更好地理解交通信号灯系统的控制逻辑,我们需要了解可能的状态以及它们之间的转换。第一个解决方案将基于以下观察:
在任何给定时间,交通信号灯将显示以下颜色组合之一:{绿,红}、{黄,红}、{红,红}、{红,黄}、{红,绿}、{红,黄}。根据交通信号灯的运行规则,显然不应允许其他颜色组合,以避免给同时通过两条道路交叉口的车辆带来风险。每对颜色中的第一个颜色是主路的交通信号灯。
上述颜色组合会按照固定的顺序显示:{绿,红}、{黄,红}、{红,红}、{红,黄}、{红,绿}、{红,黄}、{红,红}、{黄,红},然后回到第一个组合重新开始。
很容易看出序列中的每个阶段都代表一种可能的状态,因为它清晰地包含了系统在特定时刻的状态。状态之间的转换则由每次颜色变化的时间间隔触发。假设序列以主路绿灯开始,那么整个序列都由一个本地道路交通事件 (LocalRoadTrafficEvent) 触发。
细心的读者会注意到,上述颜色组合序列中存在一些重复项。例如,“两个交通灯均为红灯”的组合出现了两次。我们应该将它们视为一个状态还是两个状态呢?我选择将序列中的每个位置都视为独立的状态。这一决定意味着状态之间的转换应该尽可能简单。
我们已经有了基础,包括一系列事件、一些动作和一组候选状态。
图 2 以 UML 表示法展示了设计。图中以圆形绘制了所提出的状态,状态转换以相应的事件命名。每个状态还包含用于改变交通灯颜色的输入动作。如图所示,只有起始状态需要同时配置两个交通灯以确保序列正确启动;对于其他状态,只需在前一个状态的基础上改变一个交通灯的颜色即可。这就解释了为何需要使用两个不同的动作函数。起始状态由初始状态和当前状态之间的转换表示,该转换在左上角用一个小圆圈标出。.
UML语义利用初始状态及其转换来指向期望的起始状态,这意味着我们可以直接在图中表达系统初始化。该转换不包含任何事件,并且隐式地包含在启动过程中。
从状态机的角度来看,该设计几乎已经完成,但缺少对主干道最短绿灯间隔的处理。我们可以通过多种方式解决这个问题,但以下方案似乎非常简单。
通过在MainGreen_LocalRed状态中创建一个状态机,在模型中引入少量层次结构。该状态机由两个状态加上初始伪状态组成。每当进入周围状态时,NewGreen状态也会被激活。
当从进入MainGreen_LocalRed状态开始的较长时间间隔到期时,我们让这个小型状态机的状态更改为LocalRoadEventOK。现在我们知道主干道绿灯的最短绿灯间隔已经过去,如果支路有车辆,那么支路的绿灯亮起应该是正确的(OK)。
为了维持主路最短绿灯时间,最后需要做的就是在从 GreenMain_RedLocal 状态转换出来时添加一个“保护”机制。只有当 LocalRoadEventOK 状态被触发时,这个转换才会被覆盖。这可以理解为转换中的一个正向状态条件或正向同步。由此产生的更改如图 3 所示。
这个方案并不完美,因为它没有考虑到在主路最短绿灯时间内到达支路的车辆会一直保持静止状态,直到绿灯时间结束后有另一辆车到达才会通行。为了解决这个问题,我们需要记录绿灯时间内发生的任何 LocalRoadTrafficEvent 事件,以便在绿灯时间结束后采取相应的措施。这里我们不会探讨完整的解决方案,但如果您尝试设计一个解决方案,以下几点可以作为参考:
在状态机中引入一个内部警报变量,并在主路每次进入绿灯状态时将其重置为零。
在主路绿灯状态下引入一个“内部反应”,当收到 LocalRoadTrafficEvent 事件时触发警报,保护状态可能为 NewGreen。
在 LocalRoadEventOK 状态下引入一个“进入反应”,当进入该状态时触发警报,则发送一个信号(信号是状态机自身可以发送的特殊事件)。
状态转换到黄色状态会触发信号并启动一个短暂的定时间隔。
还有其他方法可以解决这个问题,但它们需要更复杂的 UML 语法,这里无法一一赘述。
软件状态机与硬件状态机的区别在于,软件状态机必须检测并响应硬件环境中的事件。这意味着软件状态机的计算模型基于由离散步骤组成的“检测-事件-响应-事件”循环,而硬件状态机可以“同时”响应给定引脚上信号的变化。 (当然,门电路的实际变化在位级别上是离散的活动。)例如,一组硬件信号可以在门电路处组合,当输入端出现特定的信号组合时,就会产生一个事件。在软件环境中,要么需要让中断和设备驱动程序执行组合操作,要么需要让状态机执行此操作。(除非您控制硬件设计。)
另一种方法
正如开头所强调的,解决同一问题至少还有一种完全不同的方法,即把状态机建模为同一个高级状态机内的两个并行区域。这种方法的优势在于,可以将整个解决方案视为一个由独立且半独立的组件构成的系统。由于篇幅所限,无法在此展开详述,但您可以在 www.iar.com/p236597/p236597_eng.php 在线查阅
。
具体选择哪种解决方案其实并不重要,但一般来说,尽量保持简洁是明智之举。使用像 IAR visualSTATE 这样的图形化状态机设计工具是提高抽象层次的有效方法,因为优秀的工具能够支持代码生成、测试和仿真以及验证模型功能等诸多方面。
作者:Anders Holmberg,IAR Systems
印刷杂志
社交网络
热门新闻电子
西班牙电子产品杂志。出版超过25年。.
西班牙 - 马德里 - 版权所有 © Convertronic 专业西班牙电子杂志。.
