zoukankan      html  css  js  c++  java
  • matlab 调用C程序进行simulink仿真

    simulink仿真

    simulink仿真中需要使用S-Function模块,可以实现调用C程序进行仿真,下面先建立一个简单的仿真;
    具体如下图所示;

    在这里插入图片描述

    创建C程序

    需要在S-Function模块的S-Function name一栏填写需要调用C程序文件名,注意不需要带文件名后缀;
    在这里插入图片描述
    之后,新建文件sfun_myc.cppsfun_myc.h,放置在simulink仿真的同一级目录下,如下图所示;
    在这里插入图片描述
    sfun_myc.h如下;

    /* Copyright 2003-2004 The MathWorks, Inc. */
    
    #ifndef _SFUN_MYC_CPP_
    #define _SFUN_MYC_CPP_
    
    // Define a generic template that can accumulate
    // values of any numeric data type
    template <class DataType> class GenericAdder {
    private:
        DataType Peak;
    public:
        GenericAdder() {
            Peak = 0;
        }
        DataType AddTo(DataType Val) {
            Peak += Val;
            return Peak;
        }
        DataType GetPeak() const {
        	return Peak;
        }
        void SetPeak(DataType v) {
        	Peak = v;
        }
    };
    
    // Specialize the generic adder to a 'double'
    // data type adder
    class DoubleAdder : public GenericAdder<double> {};
    
    #endif
    

    sfun_myc.cpp如下;

    /* Copyright 2003-2004 The MathWorks, Inc. */
    
    // *******************************************************************
    // **** To build this mex function use: mex sfun_cppcount_cpp.cpp ****
    // *******************************************************************
    
    #include "sfun_myc.h"
    
    #define S_FUNCTION_LEVEL 2
    #define S_FUNCTION_NAME  sfun_myc
    
    // Need to include simstruc.h for the definition of the SimStruct and
    // its associated macro definitions.
    #include "simstruc.h"
    
    #define IS_PARAM_DOUBLE(pVal) (mxIsNumeric(pVal) && !mxIsLogical(pVal) &&
    !mxIsEmpty(pVal) && !mxIsSparse(pVal) && !mxIsComplex(pVal) && mxIsDouble(pVal))
    
    // Function: mdlInitializeSizes ===============================================
    // Abstract:
    //    The sizes information is used by Simulink to determine the S-function
    //    block's characteristics (number of inputs, outputs, states, etc.).
    static void mdlInitializeSizes(SimStruct *S)
    {
        // No expected parameters
        ssSetNumSFcnParams(S, 0);
    
        // Parameter mismatch will be reported by Simulink
        if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
            return;
        }
    
        // Specify I/O
        if (!ssSetNumInputPorts(S, 1)) return;
        ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
        ssSetInputPortDirectFeedThrough(S, 0, 1);
        if (!ssSetNumOutputPorts(S,1)) return;
        ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);
    
        ssSetNumSampleTimes(S, 1);
    
        // Reserve place for C++ object
        ssSetNumPWork(S, 1);
    
        ssSetSimStateCompliance(S, USE_CUSTOM_SIM_STATE);
    
        ssSetOptions(S,
                     SS_OPTION_WORKS_WITH_CODE_REUSE |
                     SS_OPTION_EXCEPTION_FREE_CODE);
    
    }
    
    
    // Function: mdlInitializeSampleTimes =========================================
    // Abstract:
    //   This function is used to specify the sample time(s) for your
    //   S-function. You must register the same number of sample times as
    //   specified in ssSetNumSampleTimes.
    static void mdlInitializeSampleTimes(SimStruct *S)
    {
        ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
        ssSetOffsetTime(S, 0, 0.0);
        ssSetModelReferenceSampleTimeDefaultInheritance(S); 
    }
    
    // Function: mdlStart =======================================================
    // Abstract:
    //   This function is called once at start of model execution. If you
    //   have states that should be initialized once, this is the place
    //   to do it.
    #define MDL_START
    static void mdlStart(SimStruct *S)
    {
        // Store new C++ object in the pointers vector
        DoubleAdder *da  = new DoubleAdder();
        ssGetPWork(S)[0] = da;
    }
    
    // Function: mdlOutputs =======================================================
    // Abstract:
    //   In this function, you compute the outputs of your S-function
    //   block.
    static void mdlOutputs(SimStruct *S, int_T tid)
    {
        // Retrieve C++ object from the pointers vector
        DoubleAdder *da = static_cast<DoubleAdder *>(ssGetPWork(S)[0]);
        
        // Get data addresses of I/O
        InputRealPtrsType  u = ssGetInputPortRealSignalPtrs(S,0);
                   real_T *y = ssGetOutputPortRealSignal(S, 0);
    
        // Call AddTo method and return peak value
        // y[0] = da->AddTo(*u[0]);
        y[0] = *u[0] + 100;
    }
    
    /* Define to indicate that this S-Function has the mdlG[S]etSimState mothods */
    #define MDL_SIM_STATE
    
    /* Function: mdlGetSimState =====================================================
     * Abstract:
     *
     */
    static mxArray* mdlGetSimState(SimStruct* S)
    {
        // Retrieve C++ object from the pointers vector
        DoubleAdder *da = static_cast<DoubleAdder*>(ssGetPWork(S)[0]);
        return mxCreateDoubleScalar(da->GetPeak());
    }
    /* Function: mdlGetSimState =====================================================
     * Abstract:
     *
     */
    static void mdlSetSimState(SimStruct* S, const mxArray* ma)
    {
        // Retrieve C++ object from the pointers vector
        DoubleAdder *da = static_cast<DoubleAdder*>(ssGetPWork(S)[0]);
        da->SetPeak(mxGetPr(ma)[0]);
    }
    
    // Function: mdlTerminate =====================================================
    // Abstract:
    //   In this function, you should perform any actions that are necessary
    //   at the termination of a simulation.  For example, if memory was
    //   allocated in mdlStart, this is the place to free it.
    static void mdlTerminate(SimStruct *S)
    {
        // Retrieve and destroy C++ object
        DoubleAdder *da = static_cast<DoubleAdder *>(ssGetPWork(S)[0]);
        delete da;
    }
    
    
    // Required S-function trailer
    #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
    
    

    最终在static void mdlOutputs(SimStruct *S, int_T tid)函数中对输入的数据进行处理即可;

    static void mdlOutputs(SimStruct *S, int_T tid)
    {
        // Retrieve C++ object from the pointers vector
        DoubleAdder *da = static_cast<DoubleAdder *>(ssGetPWork(S)[0]);
        
        // Get data addresses of I/O
        InputRealPtrsType  u = ssGetInputPortRealSignalPtrs(S,0);	//	输入
                   real_T *y = ssGetOutputPortRealSignal(S, 0);		//	输出
    
        // Call AddTo method and return peak value
        // y[0] = da->AddTo(*u[0]);
        y[0] = *u[0] + 100;	//增加100的偏移量
    }
    

    编译C程序

    查看当前路径下是否已经存在C文件,sfun_myc.hsfun_myc.cpp
    在这里插入图片描述
    使用mex指令编译sfun_myc.cpp;
    在这里插入图片描述

    运行结果

    最终的运行结果,经过S-Function模块处理的波形比原来的波形偏移了100了,期望结果符合程序的逻辑,具体如下图所示;
    在这里插入图片描述

    链接:百度云下载
    提取码:jnmg

  • 相关阅读:
    页面 笔记
    快速统计一个数二进制中1的个数
    [JAVA] String 拼接效率
    [JAVA] String常用方法
    [letcode] 832 Flipping an Image
    [java]冒泡排序
    SharedPreferences
    归并排序
    安全退出调用多个Activity的Application
    Activity生命周期
  • 原文地址:https://www.cnblogs.com/unclemac/p/12783348.html
Copyright © 2011-2022 走看看