编写 2 级 MATLAB S-Function
设置工作环境以编写 2 级 MATLAB S-Function
此示例打开一个目录,其中包含本主题所需的以下文件。
msfuntmpl_basic.m
msfuntmpl.m
msfcn_unit_delay.m
msfcndemo_sfundsc2.slx
关于 2 级 MATLAB S-Function
2 级 MATLAB® S-Function API 允许您使用 MATLAB 语言创建具有多个输入和输出端口的自定义模块,并且能够处理 Simulink® 模型产生的任何类型的信号,包括任何数据类型的矩阵和帧信号。2 级 MATLAB S-FunctionAPI 与用于创建 C MEX S 函数的 API 紧密对应。用于创建 C MEX S-Function 的大部分文档也适用于 2 级 MATLAB S-Function。为了避免重复,本节重点提供有关编写 2 级 MATLAB S-function 的特定信息。
2 级 MATLAB S-Function 是一个 MATLAB 函数,它定义引用 Simulink 模型中的 MATLAB 函数的 Level-2 MATLAB S-Function模块实例的属性和行为。MATLAB 函数本身包含一组回调方法(参阅 2 级 MATLAB S-Function 回调方法),Simulink 引擎在更新或仿真模型时会调用这些方法。回调方法执行初始化和计算 S-Function 定义的模块的输出的实际工作。
为了促进这些任务,引擎将运行时对象作为参量传递给回调方法。运行时对象有效地充当 S-Function 模块的 MATLAB 代理,允许回调方法在仿真或模型更新期间设置和访问模块属性。
关于运行时对象
当 Simulink 引擎调用 2 级 MATLAB S-Function 回调方法时,它会将 Simulink.MSFcnRunTimeBlock
类的实例作为参量传递给该方法。此实例称为 S-Function 模块的运行时对象,其对于 2 级 MATLAB S-Function 回调方法的作用与 SimStruct
结构对于 C MEX S-Function 回调方法的作用相同。该对象使该方法能够提供和获取有关模块端口、参数、状态和工作向量的各种元素的信息。该方法通过获取或设置属性或调用模块运行时对象的方法来实现此目的。有关获取和设置运行时对象属性以及调用运行时对象方法的信息,请参阅 Simulink.MSFcnRunTimeBlock
类的文档。
运行时对象不支持 MATLAB 稀疏矩阵。例如,如果变量 block
是运行时对象,则 2 级 MATLAB S-Function 中的以下行会产生错误:
block.Outport(1).Data = speye(10);
其中 speye
命令形成稀疏单位矩阵。
注意
除了 MATLAB S-Function 之外,其他 MATLAB 程序可以使用运行时对象来获取有关正在仿真的模型中的 MATLAB S-Function 的信息。请参阅使用 Simulink 中的 在仿真期间访问模块数据 以了解更多信息。
2 级 MATLAB S-Function 模板
使用基本的 2 级 MATLAB S-Function 模板 msfuntmpl_basic.m
来开始创建新的 2 级 MATLAB S-Function。该模板包含由 2 级 MATLAB S-Function API 定义的所需回调方法的骨架实现。要编写更复杂的 S-Function,请使用带注解的模板 msfuntmpl.m
。
要创建 MATLAB S-Function,请复制模板并根据需要编辑副本,以反映您正在创建的 S-Function 的所需行为。以下两节描述了 MATLAB 代码模板的内容。编写 2 级 MATLAB S-Function 的示例 部分描述了如何编写一个用于对单位延迟建模的 2 级 MATLAB S-Function。
2 级 MATLAB S-Function 回调方法
2 级 MATLAB S-Function API 定义了构成 2 级 MATLAB S-Function 的回调方法的签名和一般用途。S-Function 本身提供了这些回调方法的实现。实现反过来又确定了模块属性(例如,端口、参数和状态)和行为(例如,作为时间函数的模块输出以及模块输入、状态和参数)。通过创建具有一组适当的回调方法的 S-Function,您可以定义满足应用程序特定要求的模块类型。
2 级 MATLAB S-Function 必须包含以下回调方法:
setup
函数用于初始化基本 S-Function 特性用于计算 S-Function 输出的
Outputs
函数
您的 S-Function 可以包含其他方法,具体取决于 S-Function 定义的模块的要求。2 级 MATLAB S-Function API 定义的方法通常与 C MEX S-Function API 定义的类似命名的方法相对应。有关在仿真过程中何时调用这些方法的信息,请参阅Simulink Engine Interaction with C S-Functions中的Process View。
下表列出了所有 2 级 MATLAB S-Function 回调方法及其 C MEX 对应方法。
使用 setup
方法
2 级 MATLAB S-Function 中的 setup
方法主体初始化相应的 2 级 MATLAB S-Function 模块的实例。从这一点上看,setup
方法类似于 C MEX S-Function 实现的 mdlInitializeSizes
和 mdlInitializeSampleTimes
回调方法。setup
方法执行以下任务:
初始化模块的输入和输出端口的数量。
设置这些端口的属性,例如维度、数据类型、复杂性和采样时间。
指定模块采样时间。有关如何指定有效采样时间的更多信息,请参阅使用 Simulink 中的 指定采样时间。
设置 S-Function 对话框参数的数量。
通过将 MATLAB S-Function 中的本地函数句柄传递给 S-Function 块的运行时对象的
RegBlockMethod
方法来注册 S-Function 回调方法。有关使用RegBlockMethod
方法的信息,请参阅Simulink.MSFcnRunTimeBlock
的文档。
编写 2 级 MATLAB S-Function 的示例
以下步骤说明如何编写简单的 2 级 MATLAB S-Function。在适用的情况下,这些步骤包括模型 msfcndemo_sfundsc2
中使用的 S-Function 示例 msfcn_unit_delay.m
的示例。所有代码行都使用变量名 block
作为 S-Function 运行时对象。
从工作文件夹中打开 MATLAB S-Function 模板
msfuntmpl_basic.m
。如果复制文件时更改了文件名,请将function
行中的函数名称更改为相同的名称。修改
setup
方法来初始化 S-Function的属性。对于此示例:将运行时对象的
NumInputPorts
和NumOutputPorts
属性设置为1
,以初始化一个输入端口和一个输出端口。调用运行时对象的 SetPreCompInpPortInfoToDynamic 和 SetPreCompOutPortInfoToDynamic 方法来指示输入和输出端口从模型继承其编译属性(维度、数据类型、复杂性和采样模式)。
将运行时对象的
InputPort
的DirectFeedthrough
属性设置为false
,以指示输入端口没有直接馈通。保留模板文件副本中设置的所有其他输入和输出端口属性的默认值。Dimensions
、DatatypeID
和Complexity
属性设置的值将覆盖使用SetPreCompInpPortInfoToDynamic
和SetPreCompOutPortInfoToDynamic
方法继承的值。将运行时对象的
NumDialogPrms
属性设置为1
以初始化一个 S-Function 对话框参数。通过将运行时对象的
SampleTimes
属性值设置为[-1 0]
,指定 S-Function 具有继承的采样时间。调用运行时对象的
RegBlockMethod
方法来注册此 S-Function 中使用的以下四种回调方法。PostPropagationSetup
InitializeConditions
Outputs
Update
从模板文件副本中删除任何其他已注册的回调方法。在对
RegBlockMethod
的调用中,第一个输入参量是 S-Function API 方法的名称,第二个输入参量是 MATLAB S-Function 中关联的本地函数的函数句柄。
msfcn_unit_delay.m
中的以下setup
方法执行前面列出的步骤:function setup(block) %% Register a single dialog parameter block.NumDialogPrms = 1; %% Register number of input and output ports block.NumInputPorts = 1; block.NumOutputPorts = 1; %% Setup functional port properties to dynamically %% inherited. block.SetPreCompInpPortInfoToDynamic; block.SetPreCompOutPortInfoToDynamic; %% Hard-code certain port properties block.InputPort(1).Dimensions = 1; block.InputPort(1).DirectFeedthrough = false; block.OutputPort(1).Dimensions = 1; %% Set block sample time to [0.1 0] block.SampleTimes = [0.1 0]; %% Register methods block.RegBlockMethod('PostPropagationSetup',@DoPostPropSetup); block.RegBlockMethod('InitializeConditions',@InitConditions); block.RegBlockMethod('Outputs', @Output); block.RegBlockMethod('Update', @Update);
如果您的 S-Function 需要连续状态,请使用运行时对象的
NumContStates
属性在setup
方法中初始化连续状态的数量。不要在setup
方法中初始化离散状态。在
PostPropagationSetup
方法中初始化离散状态。2 级 MATLAB S-Function 将离散状态信息存储在 DWork 向量中。模板文件中默认的PostPropagationSetup
方法足以满足本示例的要求。以下来自
msfcn_unit_delay.m
的PostPropagationSetup
方法(名为DoPostPropSetup
)初始化一个名为x0
的 DWork 向量。function DoPostPropSetup(block) %% Setup Dwork block.NumDworks = 1; block.Dwork(1).Name = 'x0'; block.Dwork(1).Dimensions = 1; block.Dwork(1).DatatypeID = 0; block.Dwork(1).Complexity = 'Real'; block.Dwork(1).UsedAsDiscState = true;
如果您的 S-Function 使用额外的 DWork 向量,也请在
PostPropagationSetup
方法中初始化它们(参阅 Using DWork Vectors in Level-2 MATLAB S-Functions)。在
InitializeConditions
或Start
回调方法中初始化离散和连续状态或其他 DWork 向量的值。使用Start
回调方法获取在仿真开始时初始化一次的值。每当重新启用包含 S-Function 的启用子系统时,请使用InitializeConditions
方法重新初始化需要的值。对于此示例,使用
InitializeConditions
方法将离散状态的初始条件设置为 S-Function 的对话框参数的值。例如msfcn_unit_delay.m
中的InitializeConditions
方法是:function InitConditions(block) %% Initialize Dwork block.Dwork(1).Data = block.DialogPrm(1).Data;
对于具有连续状态的 S-Function,使用
ContStates
运行时对象方法初始化连续状态数据。例如:block.ContStates.Data(1) = 1.0;
在
Outputs
回调方法中计算 S-Function 的输出。对于此示例,将输出设置为 DWork 向量中存储的离散状态的当前值。msfcn_unit_delay.m
中的Outputs
方法是:function Output(block) block.OutputPort(1).Data = block.Dwork(1).Data;
对于具有连续状态的 S-Function,在
Derivatives
回调方法中计算状态导数。运行时对象将衍生数据存储在其Derivatives
属性中。例如,下一行将第一个状态导数设置为等于第一个输入信号的值。block.Derivatives.Data(1) = block.InputPort(1).Data;
此示例不使用连续状态,因此没有实现
Derivatives
回调方法。更新
Update
回调方法中的任何离散状态。对于此示例,将离散状态的值设置为第一个输入信号的当前值。msfcn_unit_delay.m
中的Update
方法是:function Update(block) block.Dwork(1).Data = block.InputPort(1).Data;
在
Terminate
方法中执行任何清理,例如清除变量或内存。与 C MEX S-Function 不同,2 级 MATLAB S-Function 不需要具有Terminate
方法。
有关其他回调方法的信息,请参阅2 级 MATLAB S-Function 回调方法。有关运行时对象属性的列表,请参阅 Simulink.MSFcnRunTimeBlock
和父类 Simulink.RunTimeBlock
的参考页。
实例化 2 级 MATLAB S-Function
要在模型中使用 2 级 MATLAB S-Function,请将 Level-2 MATLAB S-Function模块的实例复制到模型中。打开该模块的“模块参数”对话框,然后在 S-Function name 字段中输入实现 S-Function 的 MATLAB 文件的名称。如果您的 S-Function 使用任何附加参数,请在“模块参数”对话框的参数字段中以逗号分隔的列表形式输入参数值。
可变大小信号的操作
以下是对 2 级 MATLAB S-Function 模板(msfuntmpl_basic.m
)的修改以及允许您使用可变大小信号的附加操作。
function setup(block) % Register the properties of the output port block.OutputPort(1).DimensionsMode = 'Variable'; block.RegBlockMethod('SetInputPortDimensionsMode', @SetInputDimsMode); function DoPostPropSetup(block) %Register dependency rules to update current output size of output port a depending on %input ports b and c block.AddOutputDimsDependencyRules(a, [b c], @setOutputVarDims); %Configure output port b to have the same dimensions as input port a block.InputPortSameDimsAsOutputPort(a,b); %Configure DWork a to have its size reset when input size changes. block.DWorkRequireResetForSignalSize(a,true); function SetInputDimsMode(block, port, dm) % Set dimension mode block.InputPort(port).DimensionsMode = dm; block.OutputPort(port).DimensionsMode = dm; function setOutputVarDims(block, opIdx, inputIdx) % Set current (run-time) dimensions of the output outDimsAfterReset = block.InputPort(inputIdx(1)).CurrentDimensions; block.OutputPort(opIdx).CurrentDimensions = outDimsAfterReset;
从 2 级 MATLAB S-Function 生成代码
为包含 2 级 MATLAB S-Function 的模型生成代码需要您提供相应的目标语言编译器 (TLC) 文件。您不需要 TLC 文件来加速包含 2 级 MATLAB S-Function 的模型。加速器模式软件以解释模式运行 2 级 MATLAB S-Function。但是,如果 M-file S-function 位于模型引用中,则 M-file S-Function 不适用于加速模式。有关为 MATLAB S-Function 编写 TLC 文件的更多信息,请参阅 内联 S-Function (Simulink Coder) 和 Inline MATLAB File S-Functions (Simulink Coder)。
MATLAB S-Function 示例
2 级 MATLAB S-Function 示例提供了一组自文档模型,说明了 2 级 MATLAB S-Function 的用法。在 MATLAB 命令提示符下输入 sfundemos
来查看示例。
MATLAB S-Function 限制
2 级 MATLAB S-Function 不支持过零检测。
您无法从 2 级 MATLAB S-Function 触发函数调用子系统。
另请参阅
Level-2 MATLAB S-Function | S-Function Builder | S-Function | MATLAB Function