搜档网
当前位置:搜档网 › 基于C语言的S-Function的用法

基于C语言的S-Function的用法

/*创建一个有3个标量输入,3个标量输出,无参数的s-function(用于模拟DSP的控制算法)。
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" /*包含头文件simstruc.h,该文件定义了一个名为 SimStruct 的数据结构,Simulink 使用它来维护 S-function 的有关信息。simstruc.h 文件也定义了一些宏,可让你的 MEX 文件在 SimStruct 中设置某些值,或从 SimStruct 中获取某些值。*/

/*程序里面要用到的头文件在这里引用,如“math.h”等。*/
float global_var=0; /*定义全局变量,并初始化*/
static void mdlInitializeSizes(SimStruct *S)
{
/*这个函数是用来设置输入、输出和参数的。*/
ssSetNumSFcnParams(S, 0); /*设置参数个数为0,那么在 S-function对话框的S-function parameters应为空。 */
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}/*判断参数个数是否匹配。若实际输入的参数个数不等于设置的参数个数,则返回。*/
ssSetNumContStates(S, 0);/*设置连续状态的个数,为缺省值0;*/
ssSetNumDiscStates(S, 0);/*设置离散状态的个数,为缺省值0;*/
if (!ssSetNumInputPorts(S, 1)) return;/*设置输入端口的个数,这里为1*/
ssSetInputPortWidth(S, 0, 3); /*设置输入端口0的端口宽度为3,该设置应用于输入端口只能接收向量(一维)信号,其中3即为向量的长度,实际使用时一般这样处理:将所有输入信号(均为标量,且数据类型均为默认的float)用MUX模块合并成一个作为S-Function模块的输入。注意:根据协定,端口的编号从 0开始,最后一个端口的编号为总端口数减1。*/
ssSetInputPortRequiredContiguous(S, 0, true); /*设置输入信号的访问方式,true表示输入是相邻的,即指定其输入信号的元素必须占据相邻的内存区间。如果输入是相邻的,可以使用ssGetInputPortSignal来访问输入。*/
ssSetInputPortDirectFeedThrough(S, 0, 1);//*设置输入信号是否为直接馈通,即输入信号是否在mdlOutputs或者mdlGetTimeOfNextVarHit函数使用,这儿设置为真(1)。*/
if (!ssSetNumOutputPorts(S, 1)) return;/*设置输出端口的个数为1。*/
ssSetOutputPortWidth(S, 0, 3);/*设置输出端口0的宽度为3。即输出为一个向量(一维)的信号,该向量信号

的每个元素对应每个输出标量*/
ssSetNumSampleTimes(S, 1); /*设置采样时间个数为1。*/
ssSetNumRWork(S, 0);
ssSetNumIWork(S, 0);
ssSetNumPWork(S, 0);
ssSetNumModes(S, 0);
ssSetNumNonsampledZCs(S, 0);
/* Specify the sim state compliance to be same as a built-in block */

// ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE); /*注释掉,不使用*/
ssSetOptions(S, 0);

}
static void mdlInitializeSampleTimes(SimStruct *S) /*设置采样时间。*/
{
ssSetSampleTime(S, 0, SAMPLE_TIME); /*设置离散时间系统的采样时间为SAMPLE_TIME,SAMPLE_TIME为时间的采样时间,单位为s。*/
ssSetOffsetTime(S, 0, 0.0);

}
#define MDL_INITIALIZE_CONDITIONS /* Change to #undef to remove function */
#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)//这里为相关的算法,每个采样周期由输入信号计算得到输出信号*/
{
const real_T *u = (const real_T*) ssGetInputPortSignal(S,0);/*获取输入信号。*/
real_T *y = ssGetOutputPortSignal(S,0);/*获取输出信号。*/
y[0]=2*u[0];
y[1]=2*u[1];
y[2]=2*u[2];

}
#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)
{
}

#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif //这些申明用来为特定的应用选择合适的代码:如果被编译为一个 MEX 文件,则包含simulink.c文件
如果该文件被用来与 Real-Time Workshop 连接以产生一个单机或实时可执行文件,则包含cg_sfun.h文件
2.编译
在matlab的command window 里面输入“mex test.c”,即可将test.c编译为mex文件。
3.调用s-function

在simulink空间里面拉入s-function,在s-function name里面填入test,参数里面填入要设定的参数,然后仿真即可。


相关主题