2、Stateflow基础入门:Stateflow编辑器界面、状态与转移的基本概念、创建第一个简单状态机

Stateflow是Simulink中用于建模事件驱动系统和状态逻辑的图形化环境,它允许工程师以有限状态机(FSM)的方式描述复杂的控制逻辑。与Simulink中基于连续时间或离散时间的信号流模型不同,Stateflow模型的核心是状态(State)与转移(Transition),它们共同构成了一个可执行的状态机。本章将引导你熟悉Stateflow的编辑器界面,理解状态与转移的核心语义,并通过一个完整的实例——汽车车门锁控制系统,带你创建并运行第一个简单状态机。

Stateflow 状态机核心概念关系图 状态 (State) entry/exit/during 转移 (Transition) 事件[条件]{动作} 默认转移 初始激活路径 状态内部动作 entry: 进入时执行 during: 循环时执行 exit: 退出时执行 转移标签语法 事件触发 [条件判断] {转移动作} 简单示例 A B E 状态机执行语义 当前状态激活 → 检测事件与条件 → 执行转移动作 → 进入新状态(循环)

上图展示了Stateflow中状态、转移与默认转移之间的基本关系。状态是系统在特定时刻所处的模式,转移则定义了系统如何从一个状态切换到另一个状态。默认转移用于指定状态机启动时首先激活哪个状态。下面我们将深入剖析这些概念,并逐步完成第一个状态机的创建。

2.1 Stateflow编辑器界面与核心操作

Stateflow编辑器是构建状态机的画布,它集成在Simulink环境中。打开方式通常有两种:一是通过Simulink库浏览器中的“Stateflow”库拖入一个“Chart”模块;二是直接在MATLAB命令行输入sfnew命令。双击Chart模块即可进入Stateflow编辑器。

编辑器界面主要由以下几个关键区域构成:

  • 建模画布(Canvas):中央区域,用于绘制状态框、转移箭头和默认转移。支持缩放、平移和网格对齐。
  • 状态/转移工具栏(Palette):左侧或顶部的工具条,包含创建状态(State)、转移(Transition)、默认转移(Default Transition)、注释(Annotation)等图标。
  • 符号面板(Symbols Pane):通常位于左侧,用于管理输入事件、输出数据、局部变量等。这些符号是状态机与Simulink模型交互的接口。
  • 属性检查器(Property Inspector):右侧面板,用于查看和修改选中对象的属性,如状态名称、转移标签、执行顺序等。
  • 调试工具栏:提供单步执行、断点设置、状态激活高亮等调试功能,便于观察状态机的运行过程。

在开始建模前,建议先熟悉以下操作流程:

  1. 创建状态:点击工具栏中的“State”图标,然后在画布上单击并拖动,即可绘制一个状态框。默认名称为“State1”,双击状态框可以修改名称。
  2. 创建转移:点击“Transition”图标,然后从一个状态的边缘(通常是右侧或底部)按住鼠标左键,拖动到另一个状态的边缘,松开鼠标即可生成一条带箭头的转移线。
  3. 创建默认转移:点击“Default Transition”图标,然后在画布空白处单击,再拖动到目标状态的边缘。默认转移通常用带圆点的箭头表示,它没有源状态。
  4. 编辑转移标签:双击转移线,会出现一个文本编辑框,可以输入转移标签,格式为事件[条件]{动作}。
经验提醒:在绘制状态机时,建议保持画布整洁,将相关的状态和转移分组放置。使用网格对齐功能(快捷键Alt+G)可以确保图形排列整齐,避免连线交叉混乱。对于复杂的逻辑,可以合理使用“子状态”(Subchart)功能进行层次化建模,但本章先聚焦于平面状态机。

2.2 状态与转移的基本概念

状态(State)和转移(Transition)是Stateflow的两大基石。理解它们的语义是正确建模的前提。

状态(State)代表系统的一种可区分的行为模式。在Stateflow中,状态可以是激活的(Active)或非激活的(Inactive)。状态内部可以定义三种动作:

动作类型 关键字 执行时机 典型用途
进入动作 entry 当状态被激活时,执行一次 初始化内部变量、置位输出信号、启动定时器
持续动作 during 当状态处于激活状态时,每个时间步执行一次 执行连续的控制算法、更新输出值、检测条件
退出动作 exit 当状态被退出时,执行一次 保存状态信息、复位输出信号、停止定时器

转移(Transition)定义了状态之间的切换路径。一个转移通常由源状态(Source)和目标状态(Destination)组成。转移标签的完整语法为:

事件触发[条件判断]{转移动作}

其中,事件触发是转移发生的必要条件,它可以是来自Simulink输入端口的事件,也可以是Stateflow内部定义的局部事件。条件判断是一个布尔表达式,只有条件为真时,转移才会被激活。转移动作是在转移路径被激活后、目标状态进入前执行的代码,常用于更新变量或执行瞬时操作。

此外,还有两个重要的概念:

  • 默认转移(Default Transition):它没有源状态,用于指定状态机启动时或父状态激活时,首先进入哪个子状态。每个状态机或复合状态必须有且仅有一个默认转移。
  • 转移冲突(Transition Conflict):当多个转移同时满足条件时,Stateflow会根据转移的优先级规则来决定执行哪一个。优先级规则包括:父状态优先于子状态、源状态层次越高优先级越高、多个转移同时满足时,标签中条件更早被评估的优先等。理解这些规则有助于避免逻辑歧义。
核心原理:Stateflow的执行模型是基于事件驱动的。在Simulink仿真中,每个时间步都会触发一次状态机的评估。状态机首先检查当前激活状态的所有向外转移,如果某个转移的事件发生且条件为真,则执行该转移。转移动作执行完毕后,退出当前状态(执行exit动作),然后进入目标状态(执行entry动作)。如果没有任何转移被激活,则执行当前状态的during动作。这种“检查-转移-执行”的循环构成了状态机的基本运行机制。

2.3 创建第一个简单状态机:汽车车门锁控制系统

为了将上述概念付诸实践,我们设计一个简单的汽车车门锁控制系统。该系统有两个状态:锁定(Locked)和解锁(Unlocked)。输入信号为来自驾驶员的“锁门”和“开门”按钮事件。当处于“锁定”状态时,按下“开门”按钮,系统转移到“解锁”状态;当处于“解锁”状态时,按下“锁门”按钮,系统转移到“锁定”状态。同时,我们用一个输出信号door_status来指示当前状态(1表示锁定,0表示解锁)。

操作步骤:

  1. 新建模型并添加Chart模块:在Simulink中新建一个空白模型,从库浏览器中拖入一个“Chart”模块(位于Stateflow库中)。
  2. 定义输入输出接口:双击Chart模块进入编辑器。在左侧“符号面板”中,点击“添加输入事件”图标,创建两个输入事件,分别命名为LOCK和UNLOCK。再点击“添加输出数据”图标,创建一个输出数据,命名为door_status,类型设置为uint8。
  3. 绘制状态:在画布上创建两个状态框,分别命名为Locked和Unlocked。
  4. 绘制默认转移:点击“Default Transition”图标,从画布空白处拖一条箭头到Locked状态。这表示系统启动时默认处于锁定状态。
  5. 绘制状态转移:从Locked状态的右侧边缘拖一条转移线到Unlocked状态的左侧边缘。双击转移线,输入标签:UNLOCK。同样,从Unlocked状态拖一条转移线到Locked状态,标签输入:LOCK。
  6. 编写状态动作:双击Locked状态,在状态属性框中,在entry动作栏输入:door_status = 1;。双击Unlocked状态,在entry动作栏输入:door_status = 0;。
  7. 连接Simulink模型:关闭Stateflow编辑器,回到Simulink模型。添加两个“Pulse Generator”模块作为输入,分别连接到Chart模块的LOCK和UNLOCK事件输入端口。添加一个“Scope”模块连接到door_status输出端口。
  8. 配置事件触发方式:双击Chart模块,在“Events”选项卡中,将LOCK和UNLOCK的触发方式设置为“Rising edge”(上升沿触发),这样按钮按下时会产生一个脉冲事件。
  9. 运行仿真:设置仿真时间为20秒,运行模型。观察Scope中的波形,可以看到door_status在0和1之间切换,对应状态的转移。

案例拆解与结果分析:

仿真时间(秒) 输入事件 当前状态 输出 door_status 转移路径
0 - 5 无 Locked 1 默认转移进入
5 UNLOCK 上升沿 Unlocked 0 Locked → Unlocked
5 - 12 无 Unlocked 0 保持
12 LOCK 上升沿 Locked 1 Unlocked → Locked

通过这个简单的例子,我们验证了状态机的核心行为:状态根据事件进行切换,并且每个状态都有对应的输出。这个模型虽然简单,但已经包含了状态、转移、默认转移、事件触发和状态动作等所有基本要素。

常见误区提醒:初学者容易混淆“事件”和“条件”。事件是瞬时发生的信号(如按钮按下),而条件是一个持续为真的逻辑表达式(如speed > 50)。在转移标签中,事件和条件可以同时存在,但它们的语义不同。此外,不要忘记在状态中定义entry或during动作来更新输出,否则输出信号可能保持旧值,导致仿真结果不符合预期。

2.4 常见误区与总结复盘

在Stateflow入门阶段,以下几个误区值得特别关注:

  • 误区一:状态机没有默认转移。如果状态机中没有默认转移,系统启动时无法确定初始状态,仿真会报错或行为不确定。务必为每个状态机或复合状态添加默认转移。
  • 误区二:转移条件永远为真。如果转移标签只写了事件而没有条件,那么只要事件发生,转移就会执行。这在某些场景下是合理的,但若需要基于变量值进行判断,则必须添加条件。
  • 误区三:在转移动作中修改状态输出。转移动作是在转移过程中执行的,此时目标状态尚未进入。如果需要在状态激活时更新输出,应该在目标状态的entry动作中完成,而不是在转移动作中。
  • 误区四:忽略状态动作的执行顺序。在一个时间步内,如果发生转移,执行顺序是:退出当前状态(exit)→ 执行转移动作 → 进入目标状态(entry)。如果转移被禁止,则只执行当前状态的during动作。理解这个顺序对于调试复杂逻辑至关重要。

总结复盘:本章我们完成了Stateflow的入门学习。首先熟悉了编辑器界面,包括画布、工具栏、符号面板和属性检查器。然后深入理解了状态(entry/during/exit动作)和转移(事件[条件]{动作})的核心概念,并了解了默认转移和转移冲突的规则。最后,通过一个车门锁控制系统的实例,完整走通了从创建状态、绘制转移、定义接口到仿真验证的全过程。这个简单的状态机虽然功能单一,但它所体现的建模思想——将系统行为分解为离散状态和状态间的转移——是后续学习更复杂状态机(如层次状态机、并行状态机)的基础。建议读者在完成本章后,自行尝试修改这个例子,例如增加一个“车门未关紧”的报警状态,或者将输出改为通过Simulink信号控制一个物理模型,以加深理解。