(仿真函数篇二)S-Function

时间:2022-12-05 00:14:09

from:http://www.baisi.net/viewthread.php?tid=17841

 

只是怕以后用的着的时候找不到,借过来的

 

在User-Defined Function里面还有
matlab function模块,这个模块支持matlab函数和
自定义的函数,缺点就是input,output都是一个端口,
模块上不能显示输入输出的label。
还有fcn模块,它支持简易的函数表达式。

S-Function
S-Function,在library里面有很多模板,有C,C++,M,Ada,Fortran的版本,
其实都大同小异,只要了解几个函数就很容易使用了,当然初学者也可以用S-Function Builder
来构建。
当然了解了代码后,那个Builder生成的代码就更容易懂了。
下面咱们以一个例子开始把
任务:
构建一个C的S-Function。
2个input,2个output,2个parameter
input都为3*1向量,output也是3*1向量。
从S-function模块中选择C-file examples里面的Basic C-MEX template。
打开它,另存为我们的模块名字就ok了。
我们存为test.c把

下面我们来分析代码:
1.
#define S_FUNCTION_NAME  sfuntmpl_basic
#define S_FUNCTION_LEVEL 2
#define INPUT_NUM 2
#define OUTPUT_NUM 2
这儿我们需要修改下文件名了。把sfuntmpl_basic 改为 test
2.
#include "simstruc.h"
此处引用头文件,当我们需要其他头文件,例如math.h,stdio.h等,看你需要啥函数了。

3.
static void mdlInitializeSizes(SimStruct *S)
这个函数我们用来设置输入,输入,和参数的。
参数就是,我们点击模块时候,那个对话框里面需要设置的。参数之间空格隔开
4.
    ssSetNumSFcnParams(S, PARA_NUM);  /* Number of expected parameters */
    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
        /* Return if number of expected != number of actual parameters */
        return;
    }
PARA_NUM 就是你自己需要设置的参数个数
5.
    ssSetNumContStates(S, 0);  
    ssSetNumDiscStates(S, 0);
设置连续状态和离散状态个数。缺省都为0
6.
    if (!ssSetNumInputPorts(S, INPUT_NUM)) return;
    ssSetInputPortWidth(S, 0,3);  //设置端口的维数,现在为3*1
    ssSetInputPortRequiredContiguous(S, 0, true); /*direct input signal access*/
    ssSetInputPortWidth(S, 1,3);  //设置端口的维数,现在为3*1
    ssSetInputPortRequiredContiguous(S, 1, true); /*direct input signal access*/
    ssSetInputPortDirectFeedThrough(S, 0, 1);
    ssSetInputPortDirectFeedThrough(S, 1, 1);
   
INPUT_NUM就是输入端口的个数,分别设置每个端口的维数,注意端口号从0开始的。
ssSetInputPortRequiredContiguous是设置input的访问方式,true就是临近访问,这样指针的增量后
就可以直接访问下个input端口了。
ssSetInputPortDirectFeedThrough设置输入端口的信号是否mdlOutputs函数中使用,这儿设置为true。

7.
    if (!ssSetNumOutputPorts(S, OUTPUT_NUM)) return;
    ssSetOutputPortWidth(S, 0, 3);
    ssSetOutputPortWidth(S, 1, 3);
同样设置2个输出端口,以及维数
8.
    ssSetNumSampleTimes(S, 1);
    ssSetNumRWork(S, 0);
    ssSetNumIWork(S, 0);
    ssSetNumPWork(S, 0);
    ssSetNumModes(S, 0);
    ssSetNumNonsampledZCs(S, 0);
设置采样时间,此处为1s。
ssSetNumRWork,设置浮点向量的大小,0表示继承信号大小,DYNAMICALLY_SIZED表示可用
mdlSetWorkWidths来自己设置。
下面的函数依次是设置整型,指针,模式向量的大小。模式向量是专用模块的编写的。
ssSetNumNonsampledZCs设置采样点之间的zero crossing的模块的状态个数
9.
mdlInitializeSizes函数搞定。
其他
mdlInitializeSampleTimes
mdlInitializeConditions
mdlStart
我们暂时不管了,一些初始化的东西,大家可以放在这里。
我们直接奔
mdlOutputs函数把。

10.
在这个函数里面,我们执行我们的复杂逻辑关系,和我们的代码了。
首先,我们得到我们参数,输入,输出的指针把。这样我们才能操作。
     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那么在matlab得command window里面用语句“mex test.c”编译把

11.
mdlUpdate
mdlDerivatives
这几个函数以后再探讨了
mdlTerminate
这个函数必须提下,当你在s-funtion里面定义全局变量后,一定要在这里赋值为0,或者其他值,
不然在下次仿真时候,全局变量还是上次仿真的值哦。