- 积分
- 83
- 注册时间
- 2003-11-14
- 仿真币
-
- 最后登录
- 1970-1-1
|
发表于 2008-3-31 03:09:15
|
显示全部楼层
来自 新疆乌鲁木齐
转贴一篇S-Function的文章
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.此处引用头文件,当我们需要其他头文件,例如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,或者其他值,
不然在下次仿真时候,全局变量还是上次仿真的值哦。 |
评分
-
1
查看全部评分
-
|