S-函数是 System function 系统函数的简称,是指采用非图形化(即计算机语言,而非Simulink系统模块)的方式描述的功能模块。在 MATLAB 中,用户除了可以使用MATLAB 代码编写 S-函数以外,还可以使用 C、C++、FORTRAN 或 Ada 语言编写 S-函数,只不过用这些语言编写程序时需要用编译器生成动态连接库(DLL)文件,然后在Simulink 中直接调用。
在Simulik Library的 Simulink 仿真框图中添加 S-function 模块,并进行正确的设置;
创建 S-函数源文件。创建 S-函数源文件的方法有多种。用户可以按照 S-函数的语法格式自行编写代码,但是这样做很麻烦,容易出错。Simulink 在 S-function Examples 模型库中为用户提供了针对不同语言的很多 S-函数模板和例子,用户可以根据自己的需要修改相应的模板或例子即可完成 S-function源文件的编写工作。直接在命令行输入:edit sfuntmpl.m,便可以调用模板修改。
在系统的 Simulink 仿真框图中按照定义好的功能连接输入输出端口。这里需要说明的是,S-function 模块中 S-函数名称必须与用户建立的 S-函数源文件,S-函数的名称完全相同,S-function 模块中的 S-函数参数列表必须按照 S-函数源文件中的参数顺序赋值,且参数之间需要用逗号隔开。另外,用户也可以使用子系统封装技术对 S-函数进行封装,这样做的好处是可以增强系统模型的可读性。
function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag)
switch flag,
case 0,
[sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;
case 1,
sys=mdlDerivatives(t,x,u);
case 2,
sys=mdlUpdate(t,x,u);
case 3,
sys=mdlOutputs(t,x,u);
case 4,
sys=mdlGetTimeOfNextVarHit(t,x,u);
case 9,
sys=mdlTerminate(t,x,u);
otherwise
DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
end
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
sizes = simsizes;
sizes.NumContStates = 0;
sizes.NumDiscStates = 0;
sizes.NumOutputs = 0;
sizes.NumInputs = 0;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1; % at least one sample time is needed
sys = simsizes(sizes);
x0 = [];
str = [];
ts = [0 0];
simStateCompliance = 'UnknownSimState';
function sys=mdlDerivatives(t,x,u)
sys = [];
function sys=mdlUpdate(t,x,u)
sys = [];
function sys=mdlOutputs(t,x,u)
sys = [];
function sys=mdlGetTimeOfNextVarHit(t,x,u)
sampleTime = 1; % Example, set the next hit to be one second later.
sys = t + sampleTime;
function sys=mdlTerminate(t,x,u)
sys = [];
function [sys,x0,str,ts,simStateCompliance] = Gain(t,x,u,flag,gain)
%主函数
%主函数包含四个输出:
% sys数组包含某个子函数返回的值
% x0为所有状态的初始化向量
% str是保留参数,总是一个空矩阵
% Ts返回系统采样时间
%函数的四个输入分别为采样时间t、状态x、输入u和仿真流程控制标志变量flag
%输入参数后面还可以接续一系列的附带参数simStateCompliance
switch flag,
case 0,
[sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;
case 1,
sys=mdlDerivatives(t,x,u);
case 2,
sys=mdlUpdate(t,x,u);
case 3,
sys=mdlOutputs(t,x,u,gain);
case 4,
sys=mdlGetTimeOfNextVarHit(t,x,u);
case 9,
sys=mdlTerminate(t,x,u);
otherwise
DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
end
%主函数结束
%下面是各个子函数,即回调过程
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
%初始化回调函数
%提供状态、输入、输出、采样时间和初始状态的值
%初始化阶段,标志量flag首先被置零,当S-function首次被调用
%该子函数首先被调用,且为 S-Function的模板中提供如下的信息
%该子函数必须存在
sizes = simsizes;
%生成sizes的数据结构体,信息被包含其中
sizes.NumContStates = 0;
%连续状态数,缺省为0
sizes.NumDiscStates = 0;
%离散状态数,缺省为0
sizes.NumOutputs = 1;
%输出的个数,缺省为0
sizes.NumInputs = 1;
%输入的个数,缺省为0
sizes.DirFeedthrough = 0;
%是否在前项通道上,1存在,0不存在
sizes.NumSampleTimes = 1;
%采样时间个数,至少为一个
sys = simsizes(sizes);
%返回size数据结构所包含的信息
x0 = []; %设置初始状态
str = []; %保留变量置空
ts = [0 0];%设置采样时间
simStateCompliance = 'UnknownSimState';
function sys=mdlDerivatives(t,x,u)
%计算导数的回调子函数
% 给定t,x,u,则计算连续状态的导数,可以给出系统的连续状态方程
%该子函数可以不存在
sys = []; %此时sys表示状态的导数,即dx
function sys=mdlUpdate(t,x,u)
%状态回调子函数
%给定t,x,u计算离散状态的更新
%每个仿真步长必然调用子函数,不论是否具有意义
%除了在此描述系统的离散状态方程外,还可以在此基础添加其他仿真内都必须执行的代码
sys = [];%sys表示输出,即y
function sys=mdlOutputs(t,x,u,gain)
%计算输出回调函数
%给定t,x,u计算输出,可以描述系统的输出方程
%%该子系统必须存在
sys =gain*u; %即y
function sys=mdlGetTimeOfNextVarHit(t,x,u)
%计算下一个采样时间
%仅在系统是变采样时间系统时调用
sampleTime = 1;
%设置下一次采样时间是在一秒以后
sys = t + sampleTime;
%sys表示下一个采样时间点
function sys=mdlTerminate(t,x,u)
%仿真结束时要调用的回调函数
%在仿真结束时,可以在此完成仿真结束所需的必要工作
sys = [];