s函数是simulink中扩展用户自定义功能最有效的模块之一,当我们所需的功能simulink基本模块没有提供时,一般可以通过基本模块的组合以完成所需功能。而当基本模块难以组成实现甚至无法实现时,我第一想到的就是使用s函数。

对于仿真来说,一般使用最多的就是level-1 s函数,因为其语法固定,使用起来也比较简单,一般通过更改Matlab提供的s函数模板。在Matlab命令窗口输入命令:edit sfuntmpl 可以打开s函数模板的m文件,如下:

function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag)%SFUNTMPL General MATLAB S-Function Template%   With MATLAB S-functions, you can define you own ordinary differential%   equations (ODEs), discrete system equations, and/or just about%   any type of algorithm to be used within a Simulink block diagram.%%   The general form of an MATLAB S-function syntax is:%       [SYS,X0,STR,TS,SIMSTATECOMPLIANCE] = SFUNC(T,X,U,FLAG,P1,...,Pn)%%   What is returned by SFUNC at a given point in time, T, depends on the%   value of the FLAG, the current state vector, X, and the current%   input vector, U.%%   FLAG   RESULT             DESCRIPTION%   -----  ------             --------------------------------------------%   0      [SIZES,X0,STR,TS]  Initialization, return system sizes in SYS,%                             initial state in X0, state ordering strings%                             in STR, and sample times in TS.%   1      DX                 Return continuous state derivatives in SYS.%   2      DS                 Update discrete states SYS = X(n+1)%   3      Y                  Return outputs in SYS.%   4      TNEXT              Return next time hit for variable step sample%                             time in SYS.%   5                         Reserved for future (root finding).%   9      []                 Termination, perform any cleanup SYS=[].%%%   The state vectors, X and X0 consists of continuous states followed%   by discrete states.%%   Optional parameters, P1,...,Pn can be provided to the S-function and%   used during any FLAG operation.%%   When SFUNC is called with FLAG = 0, the following information%   should be returned:%%      SYS(1) = Number of continuous states.%      SYS(2) = Number of discrete states.%      SYS(3) = Number of outputs.%      SYS(4) = Number of inputs.%               Any of the first four elements in SYS can be specified%               as -1 indicating that they are dynamically sized. The%               actual length for all other flags will be equal to the%               length of the input, U.%      SYS(5) = Reserved for root finding. Must be zero.%      SYS(6) = Direct feedthrough flag (1=yes, 0=no). The s-function%               has direct feedthrough if U is used during the FLAG=3%               call. Setting this to 0 is akin to making a promise that%               U will not be used during FLAG=3. If you break the promise%               then unpredictable results will occur.%      SYS(7) = Number of sample times. This is the number of rows in TS.%%%      X0     = Initial state conditions or [] if no states.%%      STR    = State ordering strings which is generally specified as [].%%      TS     = An m-by-2 matrix containing the sample time%               (period, offset) information. Where m = number of sample%               times. The ordering of the sample times must be:%%               TS = [0      0,      : Continuous sample time.%                     0      1,      : Continuous, but fixed in minor step%                                      sample time.%                     PERIOD OFFSET, : Discrete sample time where%                                      PERIOD > 0 & OFFSET < PERIOD.%                     -2     0];     : Variable step discrete sample time%                                      where FLAG=4 is used to get time of%                                      next hit.%%               There can be more than one sample time providing%               they are ordered such that they are monotonically%               increasing. Only the needed sample times should be%               specified in TS. When specifying more than one%               sample time, you must check for sample hits explicitly by%               seeing if%                  abs(round((T-OFFSET)/PERIOD) - (T-OFFSET)/PERIOD)%               is within a specified tolerance, generally 1e-8. This%               tolerance is dependent upon your model's sampling times%               and simulation time.%%               You can also specify that the sample time of the S-function%               is inherited from the driving block. For functions which%               change during minor steps, this is done by%               specifying SYS(7) = 1 and TS = [-1 0]. For functions which%               are held during minor steps, this is done by specifying%               SYS(7) = 1 and TS = [-1 1].%%      SIMSTATECOMPLIANCE = Specifices how to handle this block when saving and%                           restoring the complete simulation state of the%                           model. The allowed values are: 'DefaultSimState',%                           'HasNoSimState' or 'DisallowSimState'. If this value%                           is not speficified, then the block's compliance with%                           simState feature is set to 'UknownSimState'.%   Copyright 1990-2010 The MathWorks, Inc.%% The following outlines the general structure of an S-function.%switch flag,  %%%%%%%%%%%%%%%%%%  % Initialization %  %%%%%%%%%%%%%%%%%%  case 0,    [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes;  %%%%%%%%%%%%%%%  % Derivatives %  %%%%%%%%%%%%%%%  case 1,    sys=mdlDerivatives(t,x,u);  %%%%%%%%%%  % Update %  %%%%%%%%%%  case 2,    sys=mdlUpdate(t,x,u);  %%%%%%%%%%%  % Outputs %  %%%%%%%%%%%  case 3,    sys=mdlOutputs(t,x,u);  %%%%%%%%%%%%%%%%%%%%%%%  % GetTimeOfNextVarHit %  %%%%%%%%%%%%%%%%%%%%%%%  case 4,    sys=mdlGetTimeOfNextVarHit(t,x,u);  %%%%%%%%%%%%%  % Terminate %  %%%%%%%%%%%%%  case 9,    sys=mdlTerminate(t,x,u);  %%%%%%%%%%%%%%%%%%%%  % Unexpected flags %  %%%%%%%%%%%%%%%%%%%%  otherwise    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));end% end sfuntmpl%%=============================================================================% mdlInitializeSizes% Return the sizes, initial conditions, and sample times for the S-function.%=============================================================================%function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes%% call simsizes for a sizes structure, fill it in and convert it to a% sizes array.%% Note that in this example, the values are hard coded.  This is not a% recommended practice as the characteristics of the block are typically% defined by the S-function parameters.%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 neededsys = simsizes(sizes);%% initialize the initial conditions%x0  = [];%% str is always an empty matrix%str = [];%% initialize the array of sample times%ts  = [0 0];% Specify the block simStateCompliance. The allowed values are:%    'UnknownSimState', < The default setting; warn and assume DefaultSimState%    'DefaultSimState', < Same sim state as a built-in block%    'HasNoSimState',   < No sim state%    'DisallowSimState' < Error out when saving or restoring the model sim statesimStateCompliance = 'UnknownSimState';% end mdlInitializeSizes%%=============================================================================% mdlDerivatives% Return the derivatives for the continuous states.%=============================================================================%function sys=mdlDerivatives(t,x,u)sys = [];% end mdlDerivatives%%=============================================================================% mdlUpdate% Handle discrete state updates, sample time hits, and major time step% requirements.%=============================================================================%function sys=mdlUpdate(t,x,u)sys = [];% end mdlUpdate%%=============================================================================% mdlOutputs% Return the block outputs.%=============================================================================%function sys=mdlOutputs(t,x,u)sys = [];% end mdlOutputs%%=============================================================================% mdlGetTimeOfNextVarHit% Return the time of the next hit for this block.  Note that the result is% absolute time.  Note that this function is only used when you specify a% variable discrete-time sample time [-2 0] in the sample time array in% mdlInitializeSizes.%=============================================================================%function sys=mdlGetTimeOfNextVarHit(t,x,u)sampleTime = 1;    %  Example, set the next hit to be one second later.sys = t + sampleTime;% end mdlGetTimeOfNextVarHit%%=============================================================================% mdlTerminate% Perform any end of simulation tasks.%=============================================================================%function sys=mdlTerminate(t,x,u)sys = [];% end mdlTerminate

为了不破坏原模板,将文件另存为my_sfuntmpl.m。可以看到s函数模板提供了大量的注释帮助,对于新手可以说是及其友好。但是当我们熟悉s函数的用法后,这些注释就显得很冗余。要想删除这些注释,可以手动删除,但工作量比较大还容易出错。对于我这样一个懒人的方法就是通过编程自动删除这些注释。直接上程序:

Fid=fopen('my_sfuntmpl.m','r');%以读的方式打开文件allst='';while ~feof(Fid)    FileRowStr = fgetl(Fid);%按行读取    st=strfind(FileRowStr,'%');    if ~isempty(st)        FileRowStr=blanks(0);%将含有'%'的一行置空    end    allst=strcat(allst,13,FileRowStr);%将有所行拼接为一行,并在每行后加入换行符    %    allst=[allst,13,FileRowStr];endfclose(Fid);%关闭文件Fid=fopen('my_sfuntmp2.m','wt');%已写的方式新建一个文件已保存处理后的s函数fprintf(Fid,'%s\n',allst);%写入处理后的s函数fclose(Fid);%关闭文件

程序已注释,不多说。处理后的my_sfuntmp2.m内容如下:

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));endfunction [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizessizes = simsizes;sizes.NumContStates  = 0;sizes.NumDiscStates  = 0;sizes.NumOutputs     = 0;sizes.NumInputs      = 0;sizes.DirFeedthrough = 1;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)sys = t + sampleTime;function sys=mdlTerminate(t,x,u)sys = [];

干净整洁,清晰明了的小清新代码,看起来那叫一个舒服啊,这时候就可以愉快的编写s函数了。