目录
2.1 创建和编辑状态
2.1.1 状态的创建
2.1.2 创建连接节点
2.1.3 转移
2.1.5 默认转移
在Stateflow模型中,将包含有状态的Stateflow框图称状态图而将不包含任何状态的Stateflow框图称为流程图。其中,状态图是Stateflow最常用的一种形式,也是本书重点介绍的内容。
2.1 创建和编辑状态
创建Stateflow框图时,首先需要向框图中插入必要的图形对象。在这部分内容里,我们会全面深入地介绍创建状态、转移、节点以及默认转移的操作方式,同时也会详细分析这些图形元素在 Stateflow 状态图里起到的作用。
2.1.1 状态的创建
状态是 Stateflow 状态图里极为重要的部分。在有限状态里,状态代表着系统所处的某种模式。举个简单例子,房间里的电灯,其工作模式只有亮(ON)和灭(OFF)这两种。要是用 Stateflow 状态图来呈现电灯的工作模式,那就必须设置两个状态。
从状态的行为特点来说,它具备布尔特性,这和高级编程语言里的布尔型变量类似。在任意时刻,状态只可能处于激活或者未激活这两种情况之一,不存在第三种状态。在 Stateflow 的框图中插入状态的方法如下:
- 单击图形对象面板中的状态图标
,然后在 Stateflow 编辑器的空白区域内再次单击鼠标,则可以在状态图中增加一个状态。
- 或者,在图形对象面板的状态图标
上按下鼠标左键并保持,将状态拖放到Stateflow 编辑器的空白区域中。
- 或者,双击图形对象面板的状态图标
,然后在 Stateflow 编辑器的空白区域中单击鼠标,这时每次单击鼠标都会在相应的位置上创建一个状态,最后单击鼠标右键结束状态的添加。
上面的三种方法都可以完成状态的添加,读者可以根据自己的喜好使用不同的方法创建状态。如图所示,在 Stateflow 框图中添加了两个状态。
添加的状态的左上角通过“?”来表示目前状态还没有具体的定义,状态需要具体的
命名,这样才能够在执行状态机的时候具有唯一的布尔行为。单击问号,在光标处插入文本。
状态的标签一般可以由两个部分组成:状态名称和相应的状态动作,也可以使用/**/添加注释部分。完整的状态标签如图所示。
状态动作一般可以为数据对象进行赋值或者进行数据对象的运算,也可以通过状态
动作进行事件广播以触发其他系统的变化。状态动作的关键字主要有三种,分别为:
- entry:.当状态被激活时执行相应的动作。
- exit:当状态退出活动状态时执行相应的动作。
- during:当状态保持其活动状态时执行相应的动作。
例如,当 on状态被激活时赋值LED为 1,则 on 状态的标签应写为如图所示的内容。注意在书写动作表达式时,结尾的分号为结束符。
创建状态之后,也可以在状态上单击鼠标右键选择 Properties 命令,通过状态的属性对话框进一步定义状态,如图所示。
2.1.2 创建连接节点
在 Simulink Stateflow 里,连接节点具有重要作用。它既能在转移通路中充当决策点,依据不同条件决定转移方向,如在温度控制风扇转速系统中,通过连接节点判断温度是否超过不同阈值,从而确定风扇高速、低速运转或停止;又能作为汇合点,当多个转移路径需合并时发挥作用,像交通信号灯控制模型中,不同方向车道车辆通行状态转移可能汇合到连接节点,再由此节点转移至下一状态。
需要强调的是,连接节点不是记忆元件,因此,在状态图中任何转移的执行都不能停留在节点上,转移必须到达某个状态时才能停止。创建连接节点的方法如下:
- 单次创建:单击图形对象面板中的连接节点图标
,然后在 Stateflow 编辑器的空白区域中或者 Stateflow 状态内部单击鼠标,即可添加连接节点。
- 拖动创建:在图形对象面板的连接节点图标
上按下鼠标左键并保持,将其拖放到 Stateflow 编辑器的空白区域。
- 连续创建:双击图形对象面板的连接节点图标
,然后在编辑器空白区域中单击鼠标,每次单击都会在相应位置创建一个连接节点,最后单击鼠标右键结束节点添加。
2.1.3 转移
转移(Transition)定义了状态机从一个状态到另一个状态的转换规则,它可以由事件触发,并且可以附带条件和动作。一个完整的转移通常包含源状态、目标状态、触发事件、转移条件和转移动作等要素。
创建转移线方法:选中源状态后,将鼠标指针移动到状态的边界上,鼠标指针会变成十字线形状。按住鼠标左键并拖动,会出现一条连线。将连线拖动到目标状态上,松开鼠标左键,这样就创建了一条从源状态到目标状态的转移线。
创建转移线后,你可以对转移的属性进行配置,这些属性包括:
- 事件(Event):指定触发转移的事件。事件可以是外部输入的信号、内部定义的事件等。在转移线上双击,会弹出转移属性对话框,在 “Event” 字段中输入事件名称。例如,输入 “State0” 表示当名为 “State0” 的事件发生时触发该转移。
- 条件(Condition):设置转移发生的条件。只有当条件满足时,转移才会被执行。在属性对话框的 “Condition” 字段中输入条件表达式,如 “x > 10”,表示当变量 x 的值大于 10 时,转移才会触发。
- 动作(Action):定义转移发生时要执行的动作。动作可以是对变量的赋值、调用函数等。在 “Action” 字段中输入动作代码,例如 “y = x * 2;”,表示转移发生时将变量 x 的值乘以 2 并赋给变量 y。
2.1.5 默认转移
默认转移:是一种特殊的转移,可视为状态转移的特例。它的主要作用是确定有限状态机或父层次状态处于活动状态时,其所有子状态中首个被激活的状态。根据有限状态机的规则,当有限状态系统被激活时,必然会有一个确定的状态被激活。默认转移的意义就在于,明确规定了在状态机被激活,或者层次模型中的父层次状态被激活的情况下,具体是哪个子状态会被激活。
创建默认转移的方法如下:
- 用鼠标单击图形对象面板中的默认转移图标
,然后将默认的转移(注意鼠标光标
的变化)放置在状态或者连接节点的边缘,就可以完成默认转移的创建了。 - 如果没有把默认转移放置在状态或者连接节点的边缘,而是放置在 Stateflow 编辑器的空白处,则 Stateflow 将自动创建一个节点,作为默认转移的目标。
在默认转移的标签上添加事件和条件进行约束,或者将动作与默认转移建立关联,都是可行的操作。然而,在运用默认转移时,务必保证有限状态系统能够被正确激活,这是极为关键的一点。因为状态机的默认转移仅有一次执行的机会。
如下图示例展示了一个默认转移的示例。此例中的默认转移采用 On 事件进行控制,若系统触发的首个事件为 On 事件,系统能够正常运行。但当系统触发的首个事件并非 On 事件时,系统该如何应对呢?依据有限状态机的原理,只要有事件触发,有限状态机就会被激活。这意味着,无论首个触发的事件是否为 On 事件,系统都会尝试激活状态机。但由于该默认转移由 On 事件控制,且不存在其他默认转移,系统会报出二义性错误。这是因为没有明确的子状态可供激活。所以,在默认转移上添加标签以限制其行为时,需要格外谨慎。