Level-2 MATLAB S-Function解析
Level-2 MATLAB S-Function文章目录Level-2 MATLAB S-Function一、 打开Matlab模板二、 Level-2 MATLAB S-Function结构2.1 总体架构三层结构2.2 第一层主函数2.3 第二层setup 函数1. 端口设置2. 参数设置3. 状态与采样时间4. 选项配置5. 方法注册—— 最关键的部分2.3 局部函数实现A. 参数与配置检查B. 端口属性传播C. 工作区DWork设置D. 仿真运行核心逻辑E. 生命周期钩子2.4 结构总结时序与职责2.5 设计模式总结一、 打开Matlab模板edit msfuntmpl打开模板可以看到以下代码functionmsfuntmpl(block)%MSFUNTMPL MATLAB S-Function 模板% MATLAB S-function 被编写为一个与 S-function 同名的 MATLAB 函数。% 请将 msfuntmpl 替换为您的 S-function 的名称。% 版权所有 2003-2018 The MathWorks, Inc.%% setup 方法用于设置 S-function 的基本属性% 例如端口、参数等。请勿在主函数体中添加任何其他调用。%setup(block);%endfunction% Function: setup % 摘要:% 设置 S-function 模块的基本特性例如% - 输入端口% - 输出端口% - 对话框参数% - 选项%% 必需 : 是% C MEX 对应函数: mdlInitializeSizes%functionsetup(block)% 注册端口数量。block.NumInputPorts1;block.NumOutputPorts1;% 将端口属性设置为继承或动态。block.SetPreCompInpPortInfoToDynamic;block.SetPreCompOutPortInfoToDynamic;% 覆盖输入端口属性。block.InputPort(1).DatatypeID0;% double 类型block.InputPort(1).ComplexityReal;% 实数% 覆盖输出端口属性。block.OutputPort(1).DatatypeID0;% double 类型block.OutputPort(1).ComplexityReal;% 实数% 注册参数。block.NumDialogPrms3;block.DialogPrmsTunable{Tunable,Nontunable,SimOnlyTunable};% 设置连续状态。block.NumContStates1;% 注册采样时间。% [0 offset] : 连续采样时间% [positive_num offset] : 离散采样时间%% [-1, 0] : 继承采样时间% [-2, 0] : 可变采样时间block.SampleTimes[00];% -----------------------------------------------------------------% 选项% -----------------------------------------------------------------% 指定加速器模式是使用 TLC 还是回调 MATLAB 文件block.SetAccelRunOnTLC(false);% 指定模块的工作点合规性。模块工作点用于包含它的模型的工作点保存/恢复。% 允许的值为% Default : 模块的工作点与内置模块相同% UseEmpty: 模块工作点中没有数据需要保存/恢复% Custom : 具有自定义的工作点保存/恢复方法% 请参见下面的 GetOperatingPoint/SetOperatingPoint% Disallow: 在保存或恢复模块工作点时报错。block.OperatingPointComplianceDefault;% -----------------------------------------------------------------% MATLAB S-function 使用内部注册表来管理所有模块方法。% 您应按如下所示注册所有相关方法可选和必需。% 您可以为这些方法选择任何合适的名称并在同一文件中将它们实现为局部函数。% -----------------------------------------------------------------% -----------------------------------------------------------------% 注册在更新图表/编译期间调用的方法% -----------------------------------------------------------------%% CheckParameters:% 功能 : 用于验证模块对话框参数。您有责任在 setup 方法% 的开头显式调用此方法。% C MEX 对应函数: mdlCheckParameters% block.RegBlockMethod(CheckParameters,CheckPrms);%% SetInputPortSamplingMode:% 功能 : 检查并设置输入和输出端口属性并指定端口是以% 基于采样还是基于帧的模式运行。% C MEX 对应函数: mdlSetInputPortFrameData.% 需要 DSP System Toolbox 才能将端口设置为基于帧% block.RegBlockMethod(SetInputPortSamplingMode,SetInpPortFrameData);%% SetInputPortDimensions:% 功能 : 检查并设置输入端口以及可选地设置输出端口的维度。% C MEX 对应函数: mdlSetInputPortDimensionInfo% block.RegBlockMethod(SetInputPortDimensions,SetInpPortDims);%% SetOutputPortDimensions:% 功能 : 检查并设置输出端口以及可选地设置输入端口的维度。% C MEX 对应函数: mdlSetOutputPortDimensionInfo% block.RegBlockMethod(SetOutputPortDimensions,SetOutPortDims);%% SetInputPortDatatype:% 功能 : 检查并设置输入端口以及可选地设置输出端口的数据类型。% C MEX 对应函数: mdlSetInputPortDataType% block.RegBlockMethod(SetInputPortDataType,SetInpPortDataType);%% SetOutputPortDatatype:% 功能 : 检查并设置输出端口以及可选地设置输入端口的数据类型。% C MEX 对应函数: mdlSetOutputPortDataType% block.RegBlockMethod(SetOutputPortDataType,SetOutPortDataType);%% SetInputPortComplexSignal:% 功能 : 检查并设置输入端口以及可选地设置输出端口的复数属性。% C MEX 对应函数: mdlSetInputPortComplexSignal% block.RegBlockMethod(SetInputPortComplexSignal,SetInpPortComplexSig);%% SetOutputPortComplexSignal:% 功能 : 检查并设置输出端口以及可选地设置输入端口的复数属性。% C MEX 对应函数: mdlSetOutputPortComplexSignal% block.RegBlockMethod(SetOutputPortComplexSignal,SetOutPortComplexSig);%% PostPropagationSetup:% 功能 : 设置工作区DWork和状态变量。您也可以在此处注册运行时方法。% C MEX 对应函数: mdlSetWorkWidths% block.RegBlockMethod(PostPropagationSetup,DoPostPropSetup);% -----------------------------------------------------------------% 注册在运行时调用的方法% -----------------------------------------------------------------%% ProcessParameters:% 功能 : 用于更新运行时参数的调用。% C MEX 对应函数: mdlProcessParameters% block.RegBlockMethod(ProcessParameters,ProcessPrms);%% InitializeConditions:% 功能 : 用于初始化状态和工作区值的调用。% C MEX 对应函数: mdlInitializeConditions% block.RegBlockMethod(InitializeConditions,InitializeConditions);%% Start:% 功能 : 用于初始化状态和工作区值的调用。% C MEX 对应函数: mdlStart% block.RegBlockMethod(Start,Start);%% Outputs:% 功能 : 在仿真步长期间生成模块输出的调用。% C MEX 对应函数: mdlOutputs% block.RegBlockMethod(Outputs,Outputs);%% Update:% 功能 : 在仿真步长期间更新离散状态的调用。% C MEX 对应函数: mdlUpdate% block.RegBlockMethod(Update,Update);%% Derivatives:% 功能 : 在仿真步长期间更新连续状态导数的调用。% C MEX 对应函数: mdlDerivatives% block.RegBlockMethod(Derivatives,Derivatives);%% Projection:% 功能 : 在仿真步长期间更新投影的调用。% C MEX 对应函数: mdlProjections% block.RegBlockMethod(Projection,Projection);%% SimStatusChange:% 功能 : 当仿真进入暂停模式或离开暂停模式时调用。% C MEX 对应函数: mdlSimStatusChange% block.RegBlockMethod(SimStatusChange,SimStatusChange);%% Terminate:% 功能 : 在仿真结束时调用用于清理。% C MEX 对应函数: mdlTerminate% block.RegBlockMethod(Terminate,Terminate);%% GetOperatingPoint:% 功能 : 返回模块的工作点。% C MEX 对应函数: mdlGetOperatingPoint% block.RegBlockMethod(GetOperatingPoint,GetOperatingPoint);%% SetOperatingPoint:% 功能 : 使用给定的值设置模块的工作点数据。% C MEX 对应函数: mdlSetOperatingPoint% block.RegBlockMethod(SetOperatingPoint,SetOperatingPoint);% -----------------------------------------------------------------% 注册在代码生成期间调用的方法% -----------------------------------------------------------------%% WriteRTW:% 功能 : 向 model.rtw 文件写入特定信息。% C MEX 对应函数: mdlRTW% block.RegBlockMethod(WriteRTW,WriteRTW);%endfunction% -------------------------------------------------------------------% 下面的局部函数用于说明如何实现上述各种模块方法。% -------------------------------------------------------------------functionCheckPrms(block)ablock.DialogPrm(1).Data;if~isa(a,double)meMSLException(block.BlockHandle,message(Simulink:blocks:invalidParameter));throw(me);end%endfunctionfunctionProcessPrms(block)block.AutoUpdateRuntimePrms;%endfunctionfunctionSetInpPortFrameData(block,idx,fd)block.InputPort(idx).SamplingModefd;block.OutputPort(1).SamplingModefd;%endfunctionfunctionSetInpPortDims(block,idx,di)block.InputPort(idx).Dimensionsdi;block.OutputPort(1).Dimensionsdi;%endfunctionfunctionSetOutPortDims(block,idx,di)block.OutputPort(idx).Dimensionsdi;block.InputPort(1).Dimensionsdi;%endfunctionfunctionSetInpPortDataType(block,idx,dt)block.InputPort(idx).DataTypeIDdt;block.OutputPort(1).DataTypeIDdt;%endfunctionfunctionSetOutPortDataType(block,idx,dt)block.OutputPort(idx).DataTypeIDdt;block.InputPort(1).DataTypeIDdt;%endfunctionfunctionSetInpPortComplexSig(block,idx,c)block.InputPort(idx).Complexityc;block.OutputPort(1).Complexityc;%endfunctionfunctionSetOutPortComplexSig(block,idx,c)block.OutputPort(idx).Complexityc;block.InputPort(1).Complexityc;%endfunctionfunctionDoPostPropSetup(block)block.NumDworks2;block.Dwork(1).Namex1;block.Dwork(1).Dimensions1;block.Dwork(1).DatatypeID0;% double 类型block.Dwork(1).ComplexityReal;% 实数block.Dwork(1).UsedAsDiscStatetrue;% 用作离散状态block.Dwork(2).NamenumPause;block.Dwork(2).Dimensions1;block.Dwork(2).DatatypeID7;% uint32 类型block.Dwork(2).ComplexityReal;% 实数block.Dwork(2).UsedAsDiscStatetrue;% 用作离散状态% 将所有可调参数注册为运行时参数。block.AutoRegRuntimePrms;%endfunctionfunctionInitializeConditions(block)block.ContStates.Data1;%endfunctionfunctionStart(block)block.Dwork(1).Data0;block.Dwork(2).Datauint32(1);%endfunctionfunctionWriteRTW(block)block.WriteRTWParam(matrix,M,[12;34]);block.WriteRTWParam(string,Mode,Auto);%endfunctionfunctionOutputs(block)block.OutputPort(1).Datablock.Dwork(1).Datablock.InputPort(1).Data;%endfunctionfunctionUpdate(block)block.Dwork(1).Datablock.InputPort(1).Data;%endfunctionfunctionDerivatives(block)block.Derivatives.Data2*block.ContStates.Data;%endfunctionfunctionProjection(block)statesblock.ContStates.Data;block.ContStates.Datastateseps;%endfunctionfunctionSimStatusChange(block,s)block.Dwork(2).Datablock.Dwork(2).Data1;ifs0disp(仿真暂停。);elseifs1disp(恢复仿真。);end%endfunctionfunctionTerminate(block)disp([正在终止句柄为 num2str(block.BlockHandle) 的模块。]);%endfunctionfunctionoperPointDataGetOperatingPoint(block)% 将 DWork 数据打包作为此模块的整个工作点operPointDatablock.Dwork(1).Data;%endfunctionfunctionSetOperatingPoint(block,operPointData)% 此模块的工作点就是 DWork 数据此方法通常执行 GetOperatingPoint 方法的逆操作block.Dwork(1).DataoperPointData;%endfunction二、 Level-2 MATLAB S-Function结构2.1 总体架构三层结构┌─────────────────────────────────────────┐ │ 第一层主函数入口 (msfuntmpl) │ ← 对外接口仅调用 setup ├─────────────────────────────────────────┤ │ 第二层核心设置 (setup) │ ← 注册所有端口、参数、方法 ├─────────────────────────────────────────┤ │ 第三层功能实现 (所有局部函数) │ ← 具体执行仿真逻辑 │ - CheckPrms, Outputs, Update, ... │ └─────────────────────────────────────────┘2.2 第一层主函数functionmsfuntmpl(block)%MSFUNTMPL A Template for a MATLAB S-Function% The MATLAB S-function is written as a MATLAB function with the% same name as the S-function. Replace msfuntmpl with the name% of your S-function.% Copyright 2003-2018 The MathWorks, Inc.%% The setup method is used to setup the basic attributes of the% S-function such as ports, parameters, etc. Do not add any other% calls to the main body of the function.%setup(block);%endfunction结构要点要素说明函数名必须与 S-Function 模块中填写的名字完全一致唯一参数block——Simulink 传入的模块句柄唯一操作调用setup(block)。不要在这里添加其他代码%endfunctionMATLAB 的显式函数结束标记可选但模板中常用设计思想主函数只做“路由”把所有初始化工作委托给setup子函数保持入口干净。2.3 第二层setup 函数setup 函数是最核心的部分负责“注册”该模块的一切特性。它按照属性分组循序渐进地配置1. 端口设置block.NumInputPorts1;block.NumOutputPorts1;block.SetPreCompInpPortInfoToDynamic;% 设为动态继承block.InputPort(1).DatatypeID0;% double 类型定义模块有几个输入/输出以及它们的数据类型。2. 参数设置通俗理解就是你在 Simulink 模块双击打开设置对话框时里面那些你可以填写的参数框。% 注册参数数量告诉 Simulink 对话框里要有 3 个输入框block.NumDialogPrms3;% 设置参数的可调性在仿真过程中能否修改block.DialogPrmsTunable{Tunable,Nontunable,SimOnlyTunable};定义对话框中有 3 个参数并指定它们的可调性。三种可调性含义类型含义‘Tunable’仿真运行过程中可以随时修改比如在线调参‘Nontunable’仿真开始后不能修改必须在启动前设好‘SimOnlyTunable’只能在仿真模式下调代码生成时固定3. 状态与采样时间block.NumContStates1;% 1 个连续状态block.SampleTimes[00];% 连续采样时间[0 0]表示连续系统离散系统会用[周期, 偏移]。4. 选项配置通俗理解选项不是给用户在对话框里填的而是告诉 Simulink 引擎“我这个模块有什么特殊要求或行为模式”。block.SetAccelRunOnTLC(false);% 加速器模式是否用 TLCblock.OperatingPointComplianceDefault;控制代码生成和运行时的行为。5. 方法注册—— 最关键的部分block.RegBlockMethod(CheckParameters,CheckPrms);block.RegBlockMethod(SetInputPortDimensions,SetInpPortDims);block.RegBlockMethod(Outputs,Outputs);block.RegBlockMethod(Update,Update);% ... 等等这里注册了三大类方法阶段注册的方法作用编译/检查阶段CheckParameters、SetInputPortDimensions、SetInputPortDataType等验证参数、传播维度/类型运行阶段InitializeConditions、Outputs、Update、Derivatives、Terminate执行仿真逻辑代码生成阶段WriteRTW生成.rtw文件供代码生成2.3 局部函数实现这些函数是真正干活的每个函数对应一个注册的方法。它们按功能分组A. 参数与配置检查functionCheckPrms(block)ablock.DialogPrm(1).Data;if~isa(a,double)throw(MSLException(...));end在编译时验证用户输入的参数是否合法。B. 端口属性传播functionSetInpPortDims(block,idx,di)block.InputPort(idx).Dimensionsdi;block.OutputPort(1).Dimensionsdi;当输入维度改变时自动将输出维度设为相同维度继承。C. 工作区DWork设置functionDoPostPropSetup(block)block.NumDworks2;block.Dwork(1).Namex1;block.Dwork(1).UsedAsDiscStatetrue;定义内部工作向量可作离散状态、缓存等。D. 仿真运行核心逻辑functionOutputs(block)block.OutputPort(1).Datablock.Dwork(1).Datablock.InputPort(1).Data;最关键每个仿真步长调用计算输出。functionUpdate(block)block.Dwork(1).Datablock.InputPort(1).Data;离散状态更新下一个时刻的状态。functionDerivatives(block)block.Derivatives.Data2*block.ContStates.Data;连续状态导数用于积分器。E. 生命周期钩子functionStart(block)% 仿真开始时初始化functionSimStatusChange(block,s)% 暂停/恢复时触发functionTerminate(block)% 仿真结束时清理functionGetOperatingPoint(block)% 保存操作点functionSetOperatingPoint(block,operPointData)% 恢复操作点2.4 结构总结时序与职责这个模板实际上描述了一个S-Function 的完整生命周期仿真开始 │ ▼ [编译阶段] ├── CheckParameters → 验证参数 ├── SetInputPortDims → 确定维度 ├── SetInputPortDataType→ 确定类型 └── PostPropagationSetup→ 分配 DWork 内存 │ ▼ [初始化阶段] ├── Start → 执行启动操作 └── InitializeConditions→ 设置初始状态 │ ▼ [运行循环] (每个时间步) ├── Outputs → 计算输出 ├── Update → 更新离散状态 (可选) └── Derivatives → 计算连续状态导数 (可选) │ ▼ [结束阶段] └── Terminate → 清理资源2.5 设计模式总结设计原则在该模板中的体现注册表模式通过RegBlockMethod把函数名映射到 Simulink 引擎回调机制引擎在特定时刻如输出计算回调你注册的函数延迟绑定编译时动态确定端口维度/类型而非硬编码模块化每个功能独立为一个局部函数职责单一模板方法模式主流程由 Simulink 引擎控制用户只需填充具体实现