4. Stateflow与Simulink接口机制

Stateflow 与 Simulink 的协同能力,本质上由接口机制决定。Stateflow 图不是孤立的状态机,它必须通过输入数据读取 Simulink 信号、通过输出数据驱动外部模型、通过事件广播触发其他图或子系统、通过函数调用复用逻辑,并通过参数传递在仿真前确定行为。理解这些接口,才能让状态机真正嵌入控制系统。

输入输出数据:状态机的“感官”与“动作”

在 Stateflow 中,输入数据(Input Data)和输出数据(Output Data)是图与 Simulink 之间交换信号的主要通道。输入数据通常来自 Simulink 的信号线,例如传感器采集的转速、温度、开关状态;输出数据则回写到 Simulink,用于驱动执行器、使能子系统或记录日志。

定义数据时需要明确几个关键属性:名称、作用域(Scope)、数据类型、端口索引和初始值。作用域选择 Input 或 Output 后,Stateflow 会在图符号上生成对应的输入/输出端口,Simulink 侧即可像连接普通模块一样连线。数据类型必须与 Simulink 信号匹配,例如 uint8、boolean、double,否则会在编译期报类型不匹配错误。端口索引决定端口在图标上的排列顺序,便于布线时快速识别。

一个典型例子是发动机冷却风扇控制:输入 CoolantTemp(double,单位 ℃)来自 Simulink 的温度信号,输出 FanCmd(boolean)驱动风扇继电器。Stateflow 内部根据温度阈值切换状态,输出直接反映控制决策。

事件广播:跨图与跨子系统的触发

事件广播用于在 Stateflow 图之间或图与 Simulink 子系统之间传递“发生了什么”。事件分为输入事件、输出事件和本地事件。输入事件由 Simulink 侧触发,输出事件由 Stateflow 图发出,本地事件仅在当前图内使用。

广播事件时,发送方使用 send(eventName, receiver) 语法,接收方在状态或转移中监听该事件。事件可以携带数据,但通常建议保持事件轻量,数据通过输入输出端口传递。事件广播的典型场景是故障诊断:一个监控图检测到过温后广播 OverTemp 事件,多个控制图同时收到并进入降级模式。

需要注意的是,事件广播是异步语义,在同一个仿真步内可能触发多次转移。如果事件在同一个时间步内被多次广播,Stateflow 会按调度顺序处理,可能导致状态抖动。因此,事件广播应配合去抖逻辑或使能条件使用。

函数调用:图形函数与 Simulink 函数

Stateflow 支持两种函数调用接口:图形函数(Graphical Function)和 Simulink 函数(Simulink Function)。图形函数在 Stateflow 内部定义,可以被同一图或其他图调用,适合封装重复的逻辑判断。Simulink 函数则定义在 Simulink 侧,Stateflow 通过函数调用触发 Simulink 子系统执行。

图形函数的定义方式是在 Stateflow 中新建图形函数,绘制输入输出参数和内部逻辑。调用时使用函数名和实参列表,例如 y = limitCheck(x, upper)。Simulink 函数的调用需要先在 Simulink 中定义 Function-Call Subsystem,然后在 Stateflow 中使用 send 或函数调用语法触发。函数调用是同步的,调用方会等待被调用方执行完毕。

函数调用与事件广播的区别在于:函数调用有明确的输入输出和返回值,适合计算型逻辑;事件广播没有返回值,适合通知型逻辑。选择哪种接口,取决于是否需要返回值以及是否需要跨图同步。

参数传递:仿真前的行为配置

参数(Parameter)是 Stateflow 中在仿真前确定、仿真中不变的量。参数通过 MATLAB 工作区或模型工作区定义,在 Stateflow 中声明为 Parameter 作用域。参数适合存放阈值、增益、查表数据等配置项。

参数传递的关键是数据字典或模型资源管理。推荐使用 Simulink 数据字典统一管理参数,避免工作区变量散落。参数在 Stateflow 中可以直接参与条件判断和动作,例如 if Temp > TempHigh then ...,其中 TempHigh 是参数。参数的值在仿真开始前确定,仿真过程中不可修改,这保证了行为的一致性。

联合仿真配置:让接口真正工作

接口定义完成后,需要配置联合仿真环境。关键步骤包括:设置求解器类型(固定步长或变步长)、设置 Stateflow 的更新方法(连续或离散)、配置数据记录和信号日志。

对于与 Simulink 协同的控制系统,通常选择固定步长离散求解器,步长与控制器采样周期一致,例如 0.01 s。Stateflow 图设置为离散更新,避免连续状态带来的代数环问题。数据记录方面,使用 logsout 或 Signal Logging 记录输入输出数据,便于仿真后分析状态切换时刻和输出响应。

联合仿真中常见的问题是代数环:Stateflow 输出直接反馈到输入,且没有延迟。解决方法是在反馈路径中加入单位延迟(Unit Delay)或使用状态机的历史节点。另一个问题是数据类型不匹配,需要在 Simulink 侧使用 Data Type Conversion 模块显式转换。

Stateflow 与 Simulink 接口机制总览 Simulink 模型 信号源 / 传感器 CoolantTemp (double) 执行器 / 继电器 FanCmd (boolean) Function-Call Subsystem Simulink Function 数据字典 / 工作区 TempHigh = 95 求解器:Fixed-step 0.01s Stateflow 图 输入数据 Input CoolantTemp 输出数据 Output FanCmd 事件广播 send() OverTemp 图形函数 / 参数 limitCheck / TempHigh 更新方法:Discrete 输入数据流 输出数据流 事件广播(异步) 函数调用(同步) 参数传递(仿真前) 联合仿真:固定步长 0.01s + 数据记录 logsout

接口选择与配置要点

面对一个具体控制需求,选择哪种接口需要判断:如果只是传递数值,用输入输出数据;如果需要通知其他图“某事件发生”,用事件广播;如果需要复用计算逻辑并获取返回值,用图形函数;如果需要触发 Simulink 子系统,用 Simulink 函数;如果需要在仿真前配置行为,用参数。

配置时建议遵循以下顺序:先定义数据字典中的参数和信号对象,再在 Stateflow 中声明输入输出和参数,然后连接 Simulink 信号线,最后设置求解器和记录选项。每一步都应在编译后检查端口匹配和类型一致性,避免仿真中途报错。

接口定义完成后,建议先用一个简单的测试模型验证:给输入一个阶跃信号,观察输出是否按预期切换,并检查事件广播是否在正确时刻触发。确认接口无误后,再接入完整控制系统。