matlab中的sfunction的用法(C语言)
已有 1148 次阅读2010-7-9 11:38|个人分类:学习笔记|系统分类:科研笔记|关键词:matlab,sfunction,C
创建一个有1输入(2维),2输出(1维),3个参数,还有全局变量的s-function。
1.新建sfunction的C语言文件
打开simulink,点击User-Defined Functions里面的
S-Function Examples。这个里面有多个语言版本的模板,有C,C++,Ada,Fortran 和M语言的版本,其实都大同小异,只要了解几个函数就很容易使用了。
选择C语言的版本:从S-function模块中选择C-file S-functions里面的Basic C-MEX template。打开后,另存为自己的模块名字,如test.c。
下面我们来分析代码:
#define S_FUNCTION_NAME  test//这里把文件名sfuntmpl_basic修改为test #define S_FUNCTION_LEVEL 2
#include "simstruc.h"
//程序里面要用到的头文件在这里引用,如“math.h”等。
float global_var; //定义全局变量
static void mdlInitializeSizes(SimStruct *S)
{
//这个函数用来设置输入、输出和参数的。
ssSetNumSFcnParams(S, 3);  /*设置参数个数,这里为3 */
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
ssSetNumContStates(S, 0);//设置连续状态的个数,缺省为0;
ssSetNumDiscStates(S, 0);//设置离散状态的个数,缺省为0;
if (!ssSetNumInputPorts(S, 1)) return;//设置输入变量的个数,这里为1
ssSetInputPortWidth(S, 0, 2); //设置输入变量0的维数为2 ssSetInputPortRequiredContiguous(S, 0, true); //设置input0的访问方式,true就是临近访问,这样指针的增量后就可以直接访问下个input端口了。ssSetInputPortDirectFeedThrough(S, 0, 1);// 设置输入端口的信号是否mdlOutputs函数中使用,这儿设置为true。
if (!ssSetNumOutputPorts(S, 2)) return;//设置输出变量的个数ssSetOutputPortWidth(S, 0, 1);//设置输出变量0的维数为1维
ssSetOutputPortWidth(S, 1, 1);//设置输出变量1的维数为1维ssSetNumSampleTimes(S, 1); //设置采样时间,此处为1s。
ssSetNumRWork(S, 0);//不管
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
ssSetOptions(S, 0);
//下面可以写全局变量的初始化程序
global_var=1;
}
static void mdlInitializeSampleTimes(SimStruct *S)//暂时不管
{
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
#define MDL_INITIALIZE_CONDITIONS  /* Change to #undef to remove fun ction */
#if defined(MDL_INITIALIZE_CONDITIONS)
static void mdlInitializeConditions(SimStruct *S)//暂时不管
{
}
#endif /* MDL_INITIALIZE_CONDITIONS */
#define MDL_START  /* Change to #undef to remove function */
#if defined(MDL_START)
static void mdlStart(SimStruct *S)//暂时不管
{
}
#endif /*  MDL_START */
static void mdlOutputs(SimStruct *S, int_T tid)//这里填入相关的运算、算法等
{
real_T *para1 = mxGetPr(ssGetSFcnParam(S,0));
real_T *para2 = mxGetPr(ssGetSFcnParam(S,1));
real_T *para3 = mxGetPr(ssGetSFcnParam(S,2));
const real_T *u = (const real_T*) ssGetInputPortSignal(S,0);
real_T      *y1 = ssGetOutputPortSignal(S,0);
real_T      *y2 = ssGetOutputPortSignal(S,1);
y1[0]=u[0]*para1[0]+u[1]*para2[0];
y2[0]=u[1]*para3[0]+u[0]*para1[0];
}
#define MDL_UPDATE  /* Change to #undef to remove function */
#if defined(MDL_UPDATE)
static void mdlUpdate(SimStruct *S, int_T tid)
{
}
#endif /* MDL_UPDATE */
#define MDL_DERIVATIVES  /* Change to #undef to remove function */ #if defined(MDL_DERIVATIVES)
static void mdlDerivatives(SimStruct *S)
{
}
#endif /* MDL_DERIVATIVES */
static void mdlTerminate(SimStruct *S)//这里需要把global变量全部初始化,否则下次运行程序时,全局变量还是之前的值。
{
}
#ifdef  MATLAB_MEX_FILE    /* Is this file being compiled as a MEX-fi le? */
#include "simulink.c"      /* MEX-file interface mechanism */
#else
#include "cg_sfun.h"      /* Code generation registration function * /
#endif
2.编译
在matlab的command window 里面输入“mex test.c”,即可将test.c编译为mex文件。
3.调用sfunction
在simulink空间里面拉入sfunction,在s-function name里面填入test,参数里面填入要设定的参数,然后仿真即可。
[原创]matlab每日一贴(仿真函数篇二)S-Function
在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.
ssSetNumSFcnPa rams(S, PAR A_NUM);  /* Number of expected pa rameters */
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
/* Return if number of expected != number of actual parameters */
return;
}
matlab定义函数表达式PAR A_NUM 就是你自己需要设置的参数个数
5.
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
设置连续状态和离散状态个数。缺省都为0
6.
if (!ssSetNumInputPorts(S, INPUT_NUM)) return;
ssSetInputPort Width(S, 0,3);  //设置端口的维数,现在为3*1
ssSetInputPortRequire dContiguous(S, 0, true); /*direct input signal access*/
ssSetInputPort Width(S, 1,3);  //设置端口的维数,现在为3*1
ssSetInputPortRequire dContiguous(S, 1, true); /*direct input signal access*/
ssSetInputPortDirect FeedThrough(S, 0, 1);
ssSetInputPortDirect FeedThrough(S, 1, 1);
INPUT_NUM就是输入端口的个数,分别设置每个端口的维数,注意端口号从0开始的。
ssSetInputPortRequiredContiguous是设置input的访问方式,true就是临近访问,这样指针的增量后
就可以直接访问下个input端口了。
ssSetInputPortDirectFeedThrough设置输入端口的信号是否mdl Outputs函数中使用,这儿设置为true。
7.
if (!ssSetNumOutputPorts(S, OUTPUT_NUM)) return;
ssSetOutputPortWidt h(S, 0, 3);
ssSetOutputPortWidt h(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];

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。