MATLAB S函数 之 C Mex S函数结构分析

我在个人博客  F-16飞行器非线性Simulink模型 中,简单介绍了该F-16模型的主要情况、各个文件的功能等。

其中模型中的 F16_dyn.c 是最主要的调试文件,该文件由C语言完成,搭配S-Function使用,难点在于对C Mex S函数的理解和应用。在此对S函数进行一些简单的归纳分析:

首先看一下S函数的简介:

下面看一下该文件,其中有较详细的注释,程序以以下定义开头:

#define S_FUNCTION_NAME  F16_dyn
#define S_FUNCTION_LEVEL 2

第一条指定了 S-function 的名字(F16_dyn),第二条指定了该 S-function 是按照 level 2 的格式进行编写的。

在定义了这两条之后,该程序包含了 simstruc.h 文件,这是一个头文件,它给出了SimStruct 数据结构的访问通道,以及MATLAB 应用程序接口(API)函数。 

/* include files */
#include <math.h>
#include "simstruc.h"

#include "aerodata/mexndinterp.c"
#include "aerodata/hifi_f16_aerodata.c"     /* hifi lookup tables */
#include "aerodata/lofi_f16_aerodata.c"     /* lofi lookup tables */

#include "aerodata/ISA_atmos.c"             /* ISA atmosphere model */
#include "aerodata/engine_model.c"          /*engine model */

接下来是各种宏定义:包括输入量、状态量、状态量导数、系数、参数、常量。

下面看一下模型运行的过程:

     下图所示为 Simulink 调用S-function 回调函数的顺序。实线框部分表示在模型初始化和/或每个仿真步长内需使用的回调函数;虚线框部分表示在初始化阶段和/或在仿真循环的一些或所有采样步长内使用的回调函数。

 

这里摘出几个需要特别注意的模块:

 Simulink 调用 mdlInitializeSizes 来获取输入端口和输出端口的数量、端口宽度、以及S-function 所需的任何其它对象(诸如状态数量)等有关信息。

/*=============================*/
/* Function: mdlInitalizeSizes */
/*=============================*/
static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S, 1);  /* Number of expected parameters */

    ssSetNumContStates(S, 20);
    ssSetNumDiscStates(S, 0);

    ssSetNumInputPorts(S, 2);
    ssSetInputPortWidth(S, 0, 4);
    ssSetInputPortWidth(S, 1, 1);
//     ssSetInputPortWidth(S, 2, 1);

    /* ssSetInputPortDirectFeedThrough(S, 1, 1); */

    ssSetNumOutputPorts(S, 2);
    ssSetOutputPortWidth(S, 0, 23);
    ssSetOutputPortWidth(S, 1, 3);

    ssSetNumSampleTimes(S, 1);
    ssSetNumRWork(S, 23);
    ssSetNumIWork(S, 0);
    ssSetNumPWork(S, 0);
    ssSetNumModes(S, 0);
    ssSetNumNonsampledZCs(S, 0);

    ssSetOptions(S, 0);
}

 在每个采样时间步长内,Simulink 调用mdlOutputs 来计算块的输出。  其中利用 data_output[i] 增加了变量的输出。

/*======================*/
/* Function: mdlOutputs */
/*======================*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
    real_T *x = ssGetContStates(S);
    real_T *y = ssGetOutputPortRealSignal(S, 0);
    
	 int i;
	 
	 for (i = 0; i < ssGetNumContStates(S); i++)
	 {
		y[i] = x[i]; /* outputs are the states */
	 }
     
     for(i=0; i<3; i++)
     {
         y[i+ssGetNumContStates(S)] = data_output[i];
     }
     
    real_T *y1 = ssGetOutputPortRealSignal(S, 1);
     y1[0]   = X_output;
     y1[1]   = Y_output;
     y1[2]   = Z_output;
}

  其次是变量的定义:

  注意开始有输入端口的定义,需与 mdlInitializeSizes 中对应。

/*==========================*/
/* Function: mdlDerivatives */
/*==========================*/
#define MDL_DERIVATIVES  
#if defined(MDL_DERIVATIVES)
  static void mdlDerivatives(SimStruct *S)
  {
    real_T *x  = ssGetContStates(S);
    real_T *dx = ssGetdX(S);
    
    InputRealPtrsType u = ssGetInputPortRealSignalPtrs(S, 0);
    InputRealPtrsType u1 = ssGetInputPortRealSignalPtrs(S, 1);
//     InputRealPtrsType u3 = ssGetInputPortRealSignalPtrs(S, 2);
    
    /* Declare a lot of variables */
       
        变量定义

    /* end mdlDerivatives */

#endif 

 

 

 

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛仔很忙^

雪中送炭者,定当铭记在心!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值