S-Function是system-function的缩写。当Matlab所提供的simulink模型不能完全满足用户需要时,就可以通过S-函数提供用户自己编写程序啦满足自己要求模型的接口。S-函数可以用Matlab、C、C++、Ada和Fortran语言编写,但是后四种语言编写的S-函数需要编译成MEX文件。在同名的M文件和MEX文件的S-函数情况下,Matlab和simulink优先调用MEX。S-函数主要用来实现下面几个方面的功能:(1)向simulink模块中增加一个通用目标的模型(2)使用S-函数的模块来充当硬件的驱动(3)在仿真中嵌入已经存在的C代码(4)将系统表示成一系列的数学方程(5)在simulink中使用动画使用S-函数的一个优点是,你可以建立一个通用目标的模块,在一个模型中可以多次调用,每一个模块可以有不同的参数。本教程的目录如下2#S-函数工作原理2.1模型的数学描述2.2S-函数仿真过程2.3S-函数回调方法3#M文件S-函数的编写和模板4#M文件S-函数实例4.1简单单摆仿真实验4.2混合系统M文件S-函数一、S-函数工作原理模型的数学描述simulink模块一般由若干输入、状态和输出组成,其中输出是时间、状态和输入的函数可以通过下面的几个数学表达式来描述上面的过程,具体如下:输出:y=f(x,u,t)状态:x'=g(x,u,t)S-函数仿真过程simulink模型的处理主要有两个过程:1第一个阶段是初始化这时侯的所有参数都将被确定,主要完成以下几个过程:(1)传递参数表达式给Matlab进行求解(2)得到的数值作为实际的参数使用(3)展开模型的层次,每个子系统被它们所包含的模块替代(4)检查好相邻模块间的连接(5)确定状态初值和采样时间2第二阶段是模型仿真运行仿真开始运行,仿真过程是求解器和simulink引擎交互控制的。求解器的作用是传递模块的输出,对状态导数进行积分,并确定采样时间,周而复始,直到仿真结束。仿真运行阶段的工作可以概括为:(1)计算模型输出(2)更新模型离散状态(3)计算模型连续状态,连续状态的计算过程(4)计算模型输出,过零可能被激活(过零点,就是输出y从正变到负或从负变到正)S-函数回调方法(具体看后面的实例)一个S-函数有对应的回调函数,这些回调函数(也叫方法)在模型仿真时,告诉simulink如何操作和计算。S-函数回调方法主要完成以下几个方面:(1)初始化模型(mdlInitializeSizes)在仿真之前,simulink在这个阶段初始化S-函数,主要有以下几个过程:注意:如果下面字段代表的向量宽度(也就是**的个数)为动态可变,则必须将它们赋值为-1①初始化结构体SimStruct,它包含了S-函数的所有信息②设置输入(NumOutputs)输出(NumInputs)端口数,也就是输入变量的个数③设置状态变量个数(NumStates),注意有连续和离散之分④设置是否有直接馈通(DirFeedthrough),简单的理解就是输入能否控制输入出,如果有则为1,否则为0,在以下两种情况需要直接馈通:a、某一时刻的系统输出y中包含某一时刻的系统输入ub、系统是一个变采样时间系统(variablesampletimesystem)且采样时间计算与输入u相关⑤设置采样时间个数(NumSampleTimes),也就是ts变量的行数,与用户对ts的定义有关(2)计算下一个采样时间(mdlGetTimeOfNextVarHit)在创建一个变时间样本时,这个步骤计算下一个样本的时间点,即计算下一步的仿真步长(3)计算下一个时间步的输出(mdlOutputs)当这一步完成后,此模块的所有端口对于当前时间按步都是合法的(4)更新模块状态(mdlUpdate)此过程在每一步长处都要执行一次,可以在这个过程中添加每一个仿真都需要更新的内容,此过程离散状态的更新(5)对状态变量进行积分(mdlDerivatives)用于连续状态的求解和非采样过零点,如果S-函数存在连续状态,simulink就在minorsteptime内调用mdlDrivatives和mdlOutput两个函数。如果存在非采样过零点,则调用mdlOutput和mdlZeroCrossing函数二、M文件S-函数的编写和模板Matlab中提供了直接的S-函数的模板,不需要我们直接编写原始文件,只需要根据我们的需要修改其中的一部分就可以了只有在Matlab中输入1.editsfuntmpl复制代码就会出现源文件,你将源模板另存,在根据需要编辑S-函数的参数形式如下[sys,x0,str,ts]=system_function_name(t,x,u,flag)t:时间变量,当前的时间数值x:状态变量,当前状态变量数值u:模块输入,外界输入的数据flag:所要执行的回调,根据flag决定到底调用哪个子函数,具体意义参加下表下面我提供了一个编辑好的S-函数模板,里面有详细的解释和使用说明,你只要根据需要更改我指出的那部分就可以了三、简单单摆S-函数仿真实验使用S-函数来对一个单摆系统进行仿真,主要演示以下三个方面:(1)利用S-函数对单摆系统进行建模(2)利用simulink进行仿真,研究单摆的位移(3)利用S-函数动画来演示单摆的运动(1)单摆的动力学方程为其中M是摆球质量,u是外力,Kd阻尼系数,Fg重力(2)将系统动力学方程转换为状态方程(3)根据状态方程,在模板的基础上编写S-函数我们根据状态方程并结合题目分析下输入:u,故1个输入:θ,故1个连续状态变量:x1=θ和x2=θ',故2个离散状态变量:由于是连续系统,故0个直通前向馈路:由于输出θ与输入u没有任何联系,故没有直接馈通,所有为0采样时间数量:在这个系统中我们统一成一个就可以了,故1个状态变量初值:也就是x1=θ和x2=θ'的初值,这里我们取初始角度60°,速度为0,故x0=[x1x2]=[600]采样时间:由于是连续系统,故ts=[00]1.function[sys,x0,str,ts]=Single_Pendulum_Demo(t,x,u,flag,M,xx0,Kd,g)2.%M=varargin{1};%摆球质量3.%xx0=varargin{2};%状态变量初值4.%Kd=varargin{3};%阻尼系数5.%g=varargin{4};%重力加速度6.7.switchflag,8.case0,9.[sys,x0,str,ts]=mdlInitializeSizes(xx0);10.case1,11.sys=mdlDerivatives(t,x,u,Kd,g,M);12.case2,13.sys=mdlUpdate(t,x,u);14.case3,15.sys=mdlOutputs(t,x,u);16.case4,17.sys=mdlGetTimeOfNextVarHit(t,x,u);18.case9,19.sys=mdlTerminate(t,x,u);20.otherwise21.DAStudio.error('Simulink:blocks:unhandledFlag',num2str(flag));22.end23.24.25.function[sys,x0,str,ts]=mdlInitializeSizes(xx0)26.sizes=simsizes;27.sizes.NumContStates=2;%2个连续状态28.sizes.NumDiscStates=0;%0个离散状态29.sizes.NumOutputs=1;%1个输出变量30.sizes.NumInputs=1;%1个输入变量31.sizes.DirFeedthrough=0;%没有直接馈通,简单的说就是输出y中有没有输入参数u32.sizes.NumSampleTimes=1;%采用时间个数33.sys=simsizes(sizes);34.x0=s0;%状态变量初值35.str=[];%Matlab自已预留的,全部保留空着,不要动36.ts=[00];%[00]适用于连续系统37.38.functionsys=mdlDerivatives(t,x,u,Kd,g,M)39.%状态变量一阶导数表达式40.sys=[x(2);-Kd*x(2)-M*g*sin(x(1))+u];41.42.functionsys=mdlUpdate(t,x,u)43.%由于是连续系统,故不需填写44.sys=[];45.46.47.functionsys=mdlOutputs(t,x,u)48.%输入变量是摆角θ,即x(1)49.sys=x(1);50.51.functionsys=mdlGetTimeOfNextVarHit(t,x,u)52.%由于是连续系统这个用不到,可以不理它53.sampleTime=1;54.sys=t+sampleTime;55.56.functionsys=mdlTerminate(t,x,u)57.%模块解决没有什么操作,也不需要理它58.sys=[];复制代码(4)使用simulink建模在sink中拖出scop,scouce中拖出sinewave,user-definedfunction中拖出S-function,并如下如连接三个模块双击sinewave输入设置属性双击S-Function,如下设置参数运行仿真,得到以下结果Single_Pendulum_Demo.m1.36KB,下载次数:133Sim_Single_Pendulum_Demo.mdl18.46KB,下载次数:105