S函数模板

本文为simulink中s函数模板的翻译版。可直接拷入m文件编辑。

function [sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag)

%[sys,x0,str,ts,simStateCompliance] = sfuntmpl(t,x,u,flag,p1,…pn)

% flag result 描述
% —– —— ——————————————–
% 0 [sizes,x0,str,Ts] 初始化,返回SYS的大小,初始状态x0,str,采样时间Ts
% 1 DX 返回连续状态微分SYS.
% 2 DS 更新离散状态 SYS = X(n+1)
% 3 Y 返回输出SYS.
% 4 TNEXT Return next time hit for variable step sample time in SYS.
% 5 Reserved for future (root finding).
% 9 [] 结束 perform any cleanup SYS=[].

% 当flag=0时,以下信息必须赋值回传
% SYS(1) = 连续状态个数
% SYS(2) = 离散状态个数
% SYS(3) = 输出量个数
% SYS(4) = 输入量个数 注:上述4个变量可以赋值为-1,表示其值可变
% SYS(5) = 保留值。为0.
% SYS(6) = 直接馈通标志(1=yes, 0=no).如果u在flag=3时被使用,说明S函数是直接馈通,赋值为1. 否则为0.
% SYS(7) = 采样时间个数,Ts的行数
%
% X0 = 初始状态。没有则赋值为[].除flag=0外,被忽略。
% STR = 系统保留,设为[].
% TS = m*2 矩阵。(采样周期,偏移量)
% TS = [0 0, : 连续采样
% 0 1, : 在1个Ts后连续采样
% PERIOD OFFSET, : Discrete sample time where
% PERIOD > 0 & OFFSET < PERIOD.
% -2 0]; : 变步长离散采样,
% flag=4用于决定下一个采样时刻
% 注:
% 若希望每个时间步都运行,则设Ts=[0,0]
% 若希望继承采样时间运行,则设Ts=[-1,0]
% 若希望继承采样时间运行,且希望在微步内不变化,应该设Ts=[-1,1]
% 若希望仿真开始0.1s后每隔0.25秒运行,则设Ts=[0.25,0.1]
% 若希望按照不同速率执行不同任务,则Ts应按照升序排列。
% 即:每隔0.25秒执行一个任务,同时在开始0.1秒后,每隔1秒执行另一个任务
% Ts=[0.25,0; 1.0,0.1],则simulink将在下列时刻执行s函数[0,0.1,0.25,0.5,0.75,1,1.1,…]

% 以下是S函数的主函数
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 % 未知flag值
DAStudio.error(‘Simulink:blocks:unhandledFlag’, num2str(flag));
end % S函数主程序结束

%=============================================================================
% mdlInitializeSizes
% 返回s函数的sizes、初始条件、采样时刻
%=============================================================================
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
% 调用simsizes函数为sizes结构赋值
% simsizes函数是S函数模块特有的。它的结构和代码是固定的。

sizes = simsizes;
sizes.NumContStates = 0; %连续状态个数
sizes.NumDiscStates = 0; %离散状态个数
sizes.NumOutputs = 0; %输出量个数
sizes.NumInputs = 0; %输入量个数
sizes.DirFeedthrough = 1; %直接馈通标志
sizes.NumSampleTimes = 1; % 至少有一个采样时刻
sys = simsizes(sizes);

x0 = 0; % 状态初始化
str = []; % str 始终为空
ts = [0 0];% 初始化采样时间

% 指定simStateCompliance的值.
% ‘UnknownSimState’, < 默认值; 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 state
simStateCompliance = ‘UnknownSimState’;
% 子函数mdlInitializeSizes 结束

%=============================================================================
% mdlDerivatives
% 返回连续状态量的导数
%=============================================================================
function sys=mdlDerivatives(t,x,u)

sys = [];

% 子函数mdlDerivatives结束

%=============================================================================
% mdlUpdate
%更新离散时间状态,采样时刻和主时间步的要求。
%=============================================================================
function sys=mdlUpdate(t,x,u)

sys = [];
% 子函数 mdlUpdate 结束

%=============================================================================
% mdlOutputs
% 计算并返回模块输出量
%=============================================================================
function sys=mdlOutputs(t,x,u)

sys = [];

% 子函数 mdlOutputs 结束

%=============================================================================
% mdlGetTimeOfNextVarHit
% 返回下一个采样时刻。注意返回结果是一个绝对时间,只在Ts=[-2,0]时使用。
%=============================================================================
function sys=mdlGetTimeOfNextVarHit(t,x,u)

sampleTime = 1; % 例子。设置下一个采样时刻为1s后。
sys = t + sampleTime;

% 子函数 mdlGetTimeOfNextVarHit 结束

%=============================================================================
% mdlTerminate
% 仿真结束
%=============================================================================
%
function sys=mdlTerminate(t,x,u)

sys = [];

% 子函数 mdlTerminate结束


.C语言S函数
让我们做一个两个输入,两个输出,两个参数的例子。在MATLAB命令行输入edit sfuntmpl_basic.c即可打开C语言S函数模板。
#define S_FUNCTION_NAME test //更改名字
#define S_FUNCTION_LEVEL 2
#define INPUT_NUM 2 //输入输出个数
#define OUTPUT_NUM 2

      #include "simstruc.h"
      //
      //用到的头文件
      #include "math.h"
      #include "stdio.h"

static void mdlInitializeSizes(SimStruct *S)
{
/* See sfuntmpl_doc.c for more details on the macros below */
ssSetNumSFcnParams(S, 2); /* Number of expected parameters *///输入参数个数
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
/* Return if number of expected != number of actual parameters */
return;
}
ssSetNumContStates(S, 0);//连续、离散状态个数
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, INPUT_NUM)) return;
ssSetInputPortWidth(S, 0, 3);//设置端口维数,更改为3x1
ssSetInputPortRequiredContiguous(S, 0, true); /direct input signal access/
//第二个输入端口
ssSetInputPortWidth(S,1,3);
ssSetInputPortRequiredContiguous(S,1,true);

sSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 1, 1);
if (!ssSetNumOutputPorts(S, OUTPUT_NUM)) return;
ssSetOutputPortWidth(S, 0, 3);//输出端口维数3x1
ssSetOutputPortWidth(S, 1, 3);//第二个输出
ssSetNumSampleTimes(S, 0.001);//采样时间0.001s
ssSetNumRWork(S, 0);//设置浮点向量大小,0表示继承信号大小
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);//设置采样点之间的zero crossing的模块的状态个数
/* Specify the sim state compliance to be same as a built-in block */
ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
ssSetOptions(S, 0);
对于输出函数mdlOutputs,先获得变量,再进行编程
static void mdlOutputs(SimStruct *S, int_T tid)
{
//获得参数指针
real_T *para1=mxGetPr(ssGetSFcnParam(S,0));
real_T *para2=mxGetPr(ssGetSFcnParam(S,1));

const real_T *u1 = (const real_T*) ssGetInputPortSignal(S,0);
const real_T *u2 = (const real_T*) ssGetInputPortSignal(S,1);

real_T       *y1 = ssGetOutputPortSignal(S,0);
real_T       *y2 = ssGetOutputPortSignal(S,1);

//将输入乘以参数1或者参数2,然后赋值给输出
y1[0] = para1[0]*u1[0];
y1[1] = para1[0]*u1[1];
y1[2] = para1[0]*u1[2];
y2[0] = para2[0]*u2[0];
y2[1] = para2[0]*u2[1];
y2[2] = para2[0]*u2[2];

}
ok,使用mex编译并加入s-function模块,就可以。


3.s-function builder
s function builder可以很方便的自动生成c语言s函数。

你可能感兴趣的:(matlab)