MATLAB S函数编写教程(MATLAB2010b)

文章目录

M语言S函数

在命令行输入命令“edit sfuntmpl”即可打开M语言s函数模板。
M语言S函数是以flag为标志进行运算的。flag==0时,初始化参数;flag==1时,计算微分;flag==2时,状态更新;flag==3时,计算输出;flag==4时适用于变步长结算;其他参数不常用。

(1)flag==0时,调用mdlInitializeSizes函数,sizes结构及解释如下:

1
2
3
4
5
6
7
8
9
sizes.NumContStates  = 0;   //连续变量个数
sizes.NumDiscStates  = 0;   //离散变量个数
sizes.NumOutputs     = 0;    //输出个数
sizes.NumInputs      = 0;    //输入个数
sizes.DirFeedthrough = 1;  //是否直通,当在输出里包含了输入时,为直通
sizes.NumSampleTimes = 1;  //采样时间
 
对状态变量进行初始化,如果初始条件是0初始条件,则
x0=[0 0]

(2)flag==1时,调用mdlDerivatives(t,x,u)函数计算微分,如有一系统为状态方程为x’=2x+u,y=5x+u时,编写如下:sys=2*x+u;

(3)flag==3时,计算输出,如上例系统,则编写如下:sys=5*x+u;

ok,下面只需要将编写好的s函数名称写入s-function模块。
例子:对如下系统(零初始条件)

1
2
3
x1'=-3x1-x2+u;
x2'=2x1;
y=x2;

编写s函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
function [sys,x0,str,ts,simStateCompliance] = sfun_m_hyj(t,x,u,flag)
 
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
    DAStudio.error('Simulink:blocks:unhandledFlag', num2str(flag));
end
function [sys,x0,str,ts,simStateCompliance]=mdlInitializeSizes
sizes = simsizes;
 
sizes.NumContStates  = 2;
sizes.NumDiscStates  = 0;
sizes.NumOutputs     = 1;
sizes.NumInputs      = 1;
sizes.DirFeedthrough = 1;
sizes.NumSampleTimes = 1;   % at least one sample time is needed
sys = simsizes(sizes);
x0  = [0 0];
str = [];
ts  = [0 0];
simStateCompliance = 'UnknownSimState';
function sys=mdlDerivatives(t,x,u)
sys = [-3*x(1)-x(2)+u;2*x(1)]; //注意此处传递的是x向量,包含了x1和x2,引用时使用x(1),x(2),下标从1开始
function sys=mdlUpdate(t,x,u)
sys = [];
function sys=mdlOutputs(t,x,u)
sys = [x(2)]; //x向量
function sys=mdlGetTimeOfNextVarHit(t,x,u)
sampleTime = 1;    %  Example, set the next hit to be one second later.
sys = t + sampleTime;
function sys=mdlTerminate(t,x,u)
sys = [];

C语言S函数

让我们做一个两个输入,两个输出,两个参数的例子。在MATLAB命令行输入edit sfuntmpl_basic.c即可打开C语言S函数模板。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#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,先获得变量,再进行编程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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];
}

使用mex编译并加入s-function模块即可,编译方法如下所示:

1、先通过matlab命令行设置matlab的mex编译器

matlab-mex

2、用mex 命令来编译代码
命令格式:mex cppfile(模块对应的代码的文件名),编译成功会有相应的提示

3、编译成功会产生一个后缀为mexw32的mex程序,有了这个程序,用户自定义模块就可以工作了

参考文章:MATLAB S函数编写示范(MATLAB2010a)



本文出自 TENNFY WU,转载时请注明出处及相应链接。

本文永久链接: http://www.tennfy.com/2155.html

下一篇文章:

上一篇文章:

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

3 + 8 = ?


您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

返回顶部