news 2026/7/6 3:10:07

Level-2 MATLAB S-Function解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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.NumInputPorts=1;block.NumOutputPorts=1;% 将端口属性设置为继承或动态。block.SetPreCompInpPortInfoToDynamic;block.SetPreCompOutPortInfoToDynamic;% 覆盖输入端口属性。block.InputPort(1).DatatypeID=0;% double 类型block.InputPort(1).Complexity='Real';% 实数% 覆盖输出端口属性。block.OutputPort(1).DatatypeID=0;% double 类型block.OutputPort(1).Complexity='Real';% 实数% 注册参数。block.NumDialogPrms=3;block.DialogPrmsTunable={'Tunable','Nontunable','SimOnlyTunable'};% 设置连续状态。block.NumContStates=1;% 注册采样时间。% [0 offset] : 连续采样时间% [positive_num offset] : 离散采样时间%% [-1, 0] : 继承采样时间% [-2, 0] : 可变采样时间block.SampleTimes=[00];% -----------------------------------------------------------------% 选项% -----------------------------------------------------------------% 指定加速器模式是使用 TLC 还是回调 MATLAB 文件block.SetAccelRunOnTLC(false);% 指定模块的工作点合规性。模块工作点用于包含它的模型的工作点保存/恢复。% 允许的值为:% 'Default' : 模块的工作点与内置模块相同% 'UseEmpty': 模块工作点中没有数据需要保存/恢复% 'Custom' : 具有自定义的工作点保存/恢复方法% (请参见下面的 GetOperatingPoint/SetOperatingPoint)% 'Disallow': 在保存或恢复模块工作点时报错。block.OperatingPointCompliance='Default';% -----------------------------------------------------------------% 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)a=block.DialogPrm(1).Data;if~isa(a,'double')me=MSLException(block.BlockHandle,message('Simulink:blocks:invalidParameter'));throw(me);end%endfunctionfunctionProcessPrms(block)block.AutoUpdateRuntimePrms;%endfunctionfunctionSetInpPortFrameData(block,idx,fd)block.InputPort(idx).SamplingMode=fd;block.OutputPort(1).SamplingMode=fd;%endfunctionfunctionSetInpPortDims(block,idx,di)block.InputPort(idx).Dimensions=di;block.OutputPort(1).Dimensions=di;%endfunctionfunctionSetOutPortDims(block,idx,di)block.OutputPort(idx).Dimensions=di;block.InputPort(1).Dimensions=di;%endfunctionfunctionSetInpPortDataType(block,idx,dt)block.InputPort(idx).DataTypeID=dt;block.OutputPort(1).DataTypeID=dt;%endfunctionfunctionSetOutPortDataType(block,idx,dt)block.OutputPort(idx).DataTypeID=dt;block.InputPort(1).DataTypeID=dt;%endfunctionfunctionSetInpPortComplexSig(block,idx,c)block.InputPort(idx).Complexity=c;block.OutputPort(1).Complexity=c;%endfunctionfunctionSetOutPortComplexSig(block,idx,c)block.OutputPort(idx).Complexity=c;block.InputPort(1).Complexity=c;%endfunctionfunctionDoPostPropSetup(block)block.NumDworks=2;block.Dwork(1).Name='x1';block.Dwork(1).Dimensions=1;block.Dwork(1).DatatypeID=0;% double 类型block.Dwork(1).Complexity='Real';% 实数block.Dwork(1).UsedAsDiscState=true;% 用作离散状态block.Dwork(2).Name='numPause';block.Dwork(2).Dimensions=1;block.Dwork(2).DatatypeID=7;% uint32 类型block.Dwork(2).Complexity='Real';% 实数block.Dwork(2).UsedAsDiscState=true;% 用作离散状态% 将所有可调参数注册为运行时参数。block.AutoRegRuntimePrms;%endfunctionfunctionInitializeConditions(block)block.ContStates.Data=1;%endfunctionfunctionStart(block)block.Dwork(1).Data=0;block.Dwork(2).Data=uint32(1);%endfunctionfunctionWriteRTW(block)block.WriteRTWParam('matrix','M',[12;34]);block.WriteRTWParam('string','Mode','Auto');%endfunctionfunctionOutputs(block)block.OutputPort(1).Data=block.Dwork(1).Data+block.InputPort(1).Data;%endfunctionfunctionUpdate(block)block.Dwork(1).Data=block.InputPort(1).Data;%endfunctionfunctionDerivatives(block)block.Derivatives.Data=2*block.ContStates.Data;%endfunctionfunctionProjection(block)states=block.ContStates.Data;block.ContStates.Data=states+eps;%endfunctionfunctionSimStatusChange(block,s)block.Dwork(2).Data=block.Dwork(2).Data+1;ifs==0disp('仿真暂停。');elseifs==1disp('恢复仿真。');end%endfunctionfunctionTerminate(block)disp(['正在终止句柄为 'num2str(block.BlockHandle)' 的模块。']);%endfunctionfunctionoperPointData=GetOperatingPoint(block)% 将 DWork 数据打包作为此模块的整个工作点operPointData=block.Dwork(1).Data;%endfunctionfunctionSetOperatingPoint(block,operPointData)% 此模块的工作点就是 DWork 数据(此方法通常执行 GetOperatingPoint 方法的逆操作)block.Dwork(1).Data=operPointData;%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.NumInputPorts=1;block.NumOutputPorts=1;block.SetPreCompInpPortInfoToDynamic;% 设为动态继承block.InputPort(1).DatatypeID=0;% double 类型

定义模块有几个输入/输出,以及它们的数据类型。

2. 参数设置

通俗理解:就是你在 Simulink 模块双击打开设置对话框时,里面那些你可以填写的参数框

% 注册参数数量:告诉 Simulink 对话框里要有 3 个输入框block.NumDialogPrms=3;% 设置参数的可调性(在仿真过程中能否修改)block.DialogPrmsTunable={'Tunable','Nontunable','SimOnlyTunable'};

定义对话框中有 3 个参数,并指定它们的可调性。

三种可调性含义

类型含义
‘Tunable’仿真运行过程中可以随时修改(比如在线调参)
‘Nontunable’仿真开始后不能修改,必须在启动前设好
‘SimOnlyTunable’只能在仿真模式下调,代码生成时固定

3. 状态与采样时间

block.NumContStates=1;% 1 个连续状态block.SampleTimes=[00];% 连续采样时间

[0 0]表示连续系统;离散系统会用[周期, 偏移]。

4. 选项配置

通俗理解:选项不是给用户在对话框里填的,而是告诉 Simulink 引擎“我这个模块有什么特殊要求或行为模式”

block.SetAccelRunOnTLC(false);% 加速器模式是否用 TLCblock.OperatingPointCompliance='Default';

控制代码生成和运行时的行为。

5. 方法注册—— 最关键的部分

block.RegBlockMethod('CheckParameters',@CheckPrms);block.RegBlockMethod('SetInputPortDimensions',@SetInpPortDims);block.RegBlockMethod('Outputs',@Outputs);block.RegBlockMethod('Update',@Update);% ... 等等

这里注册了三大类方法

阶段注册的方法作用
编译/检查阶段CheckParametersSetInputPortDimensionsSetInputPortDataType验证参数、传播维度/类型
运行阶段InitializeConditionsOutputsUpdateDerivativesTerminate执行仿真逻辑
代码生成阶段WriteRTW生成.rtw文件供代码生成

2.3 局部函数实现

这些函数是真正干活的,每个函数对应一个注册的方法。它们按功能分组:

A. 参数与配置检查

functionCheckPrms(block)a=block.DialogPrm(1).Data;if~isa(a,'double')throw(MSLException(...));end

在编译时验证用户输入的参数是否合法。

B. 端口属性传播

functionSetInpPortDims(block,idx,di)block.InputPort(idx).Dimensions=di;block.OutputPort(1).Dimensions=di;

当输入维度改变时,自动将输出维度设为相同(维度继承)。

C. 工作区(DWork)设置

functionDoPostPropSetup(block)block.NumDworks=2;block.Dwork(1).Name='x1';block.Dwork(1).UsedAsDiscState=true;

定义内部工作向量(可作离散状态、缓存等)。

D. 仿真运行核心逻辑

functionOutputs(block)block.OutputPort(1).Data=block.Dwork(1).Data+block.InputPort(1).Data;

最关键:每个仿真步长调用,计算输出。

functionUpdate(block)block.Dwork(1).Data=block.InputPort(1).Data;

离散状态更新(下一个时刻的状态)。

functionDerivatives(block)block.Derivatives.Data=2*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 引擎控制,用户只需填充具体实现
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 3:09:35

芙蓉区口碑好的自动变速箱维修工厂哪家可靠

变速箱出问题,别再被“只换不修”坑了长沙芙蓉区的车主,如果你正为变速箱闯挡、顿挫或倒档延迟发愁,千万别急着去4S店花几万换总成。我自己那台跑了8万公里的别克君越,之前就是2升3挡时“咔咔”响,路边店说要大修&…

作者头像 李华
网站建设 2026/7/6 3:09:28

大模型 API 超时怎么办?接口响应慢的排查与优化

你是不是也遇到过这种情况:开发 AI 应用时,调了 GPT-4、文心一言或者通义千问的接口,结果等了半天没反应,前端那个 loading 图标转个不停,最后直接给你抛个超时错误。这时候你可能会习惯性地去查数据库慢查询、看网络带…

作者头像 李华
网站建设 2026/7/6 3:09:20

《智人之上》第二章「故事:无限联结」读后总结

Author:skatexgTime:2026/07/05🎯一、 核心观点“故事:无限的联结”赫拉利在这一章里提出一个非常关键的观点: 人类(智人)之所以能够统治世界,并不是因为个体智力比其他物种更强&…

作者头像 李华
网站建设 2026/7/6 3:09:04

Lemos:动态知识网络新范式

Ima 与 Lemos 在知识组织方式上的本质区别在于,Ima 追求精确、静态、可推理的知识结构,而 Lemos 则致力于构建动态、关联、可生长的智能知识网络。Lemos 的核心优势在于其“AI知识图谱”双引擎驱动的范式,将知识库从被动的存储中心转变为主动…

作者头像 李华
网站建设 2026/7/6 3:09:02

HarmonyOS ArkTS九宫数独项目架构设计

仓库源码地址:https://gitcode.com/feng8403000/math_app_study 一、项目概述 本项目是一个基于HarmonyOS ArkTS框架开发的数字能力训练应用,包含10款数字能力训练游戏和1款九宫数独终极挑战游戏。应用采用深色主题设计,通过关卡制度实…

作者头像 李华
网站建设 2026/7/6 3:08:01

STM32 02 多路流水灯

一、前言 承接上一篇单LED闪烁实验,今天在原有工程基础上修改代码,实现流水灯效果。 目前我依旧是刚入门阶段,不会复杂封装和工程分层,所有代码直接写在main.c里,写法直白简单,用来巩固多GPIO引脚同时控制…

作者头像 李华