Simulink之S-function函数笔记之三(sfuntmpl_doc.c)
2017-09-04 09:55
1266 查看
s-function学习之sfuntmpl_doc.c
本文章用来做simulink的S-function函数的学习笔记:#define S_FUNCTION_NAME your_sfunction_name_here #define S_FUNCTION_LEVEL 2 // simstruc.h包含tmwtypes.h(general types)、mex.h、matrix.h #include "simstruc.h" //异常处理: // ssSetErrorStatus(S, "error encountered due to ..."); // return; // ssSetErrorStatus的处理方法建议使用mexErrMsgTxt,mexErrMsgTxt立即终止s-function的执行和返回。如果不使用mexRrrMsgTxt或任何其他引起异常的方式,则应该使用SS_OPTION_EXCEPTION_FREE_CODE。 // ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE); //设置此选项会允许simulink绕过异常处理的设置。但当使用这个选项时,必须格外小心验证代码是无异常的。如果s函数生成异常的时候该选项开启,将出现不可预测的结果。 // 在内存分配的问题上使用mxCalloc可能会照成不可预知的问题,如果必须使用内存分配,建议直接使用stdlib.h分配 //以下不会抛出异常:mxGetPr, mxGetData, mxGetNumberOfDimensions, mxGetM, mxGetN, mxGetNumberOfElements. //如果你所有使用的方法都不会抛出异常,则可以使用: // ssSerOptions(S, SS_OPTION_RUNTIME_EXCEPTION_FREE_CODE); // 警告 & Printf's // 输出警告: ssWarning(S, msg), 当s-function编译之后,ssWarning等同于mexWarnMsgTxt。 //Printf's: ssPrintf(fmt, ...), 当s-function编译之后,ssPrintf等同于mexPrintf。 //你可以通过这种方法来实现标准I/O: #if defined(SS_STDIO_AVAILABLE) if ((fp=fopen(file, "w")) == NULl){ ssSetErrorStatus(S, "open failed"); return ; } ... #endif //s-function methods: 注意: 以下许多方法只适用于level 2 C-MEX S-function **表示该函数必须存在 , []表示该函数可供选择。
Model Initialization in Simulink:
**mdlInitializeSizes: 初始化Simstruct数组大小
**mdlInitializeSampleTimes: 初始化采样时间和可选择的函数调用连接
[mdlInputPortComplexSignal]/[mdlOutputPortComplexSignal]: 检查并设置输入/输出端口复杂属性(COMPLEX_YES,C OMPLEX_NO)。
[mdlSetWorkWidths]: 设置状态,iwork,rwork,pwork,dwork etc.
[mdlSetSimState]: 当初始化模拟状态时,s-function将ssSetSimStateCompliance 设置为 UES_CUSTOM_SIM_STATE,并把完整的模拟状态加载到此模块中。see also mdlGetSimState。
Model simulation loop in simulink:
**mdlOutputs: 更新输出信号。
**mdlTerminate: 终止模型管理,如释放内存等。
参数处理方法(这些方法不适用于RTW):
#define MDL_CHECK_PARAMETERS //#undef则去除函数方法 #if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE) //mdlCheckParameters: 这个函数应该在mdlInitalizeSizes后被调用。如果你想使用ssSetNumSFcnParams(S, n): #if defined(MATLAB_MEX_FILE) if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) { mdlCheckParamters(S); if (ssGetErrorStatus(S) != NULL) return; } else{ return;//simulink will report a parameter mismatch error } #endif 详例见 Matlabbroot/simulink/src/sfun_errhdl.c static void mdlCheckParameters(SimStruct *S) { } #endif //MDL_CHECK_PARAMETERS
#define MDL_PROCESS_PARAMETERS #if defined(MDL_PROCESS_PARAMETERS) && defined(MATLAB_MEX_FILE) //mdlProcessParameters: 这个函数将在mdlCheckParameters之后被调用,处理新更新的参数。 static void mdlProcessParameters(SimStruct *S) { } #endif //MDL_PROCESS_PARAMETERS
Configuration and execution methods:
//mdlInitializeSizes: Direct Feedthough: 直接反馈的值可以为1或者0,如果为输入,则必须置为1,‘u’可被用于mdlOutput或者mdlGetTImeOfNextVarHit()。若置为0,‘u’则不能被用于这两个函数。如:要使用ssGetInputPortSignal(S, inputPortIndex),则需要ssSetInputPortDirectFeedThrough(S, inputPortIdx, 1); //如果需要debug s-function则:mex -g sfunction_name.c static void mdlInitializeSizes(SimStruct *S) { int_T nInputPorts = 1;//输入端口的参数个数 int_T nOutputPorts = 1;//输出端口的参数个数 int_T needsInput = 1;//直接反馈? int_T inputPortIdx = 0; int_T outputPortIdx = 0; ssSetNumSFcnParams(S, 0);//预期参数个数 if (ssGetNumSFcnParams(S) != ssGetNumParamsCount(S)) { //如果预期参数个数与所获参数个数不一样,则返回参数不匹配错误。 return; } //任何参数在模拟中是可以更改的,但若想将参数设置为不可更改,则使用: ssSetSFcnParamTunable(S, 0, 0); ssSetNumContStates( S, 0);//连续参数的个数 ssSetNumDiscStates( S, 0);//离散参数的个数 //设置输入端口的个数: if(! ssSetNumInputPorts(S, nInputPorts)) return; if(!ssSetInputPortDimensionInfo(S, inputPortIdx, DYNAMIC_DIMENSION)) return; // 1.若输入端口维数未知,则用:ssSetInputPortDimensionInfo(S, inputPortIdx, DYNAMIC_DIMENSION)。 2.若输入信号是无定向矢量,输入端口宽度为w(DYNAMICALLY_SIZED或大于0),则用:ssSetInputPortVectorDimension(S, inputPortIdx, w)或 ssSetInputPortWidth(S, inputPortIdx, w)。 3.若输入信号为m*n的矩阵,m,n(DYNAMICALLY_SIZED或大于0),则用: ssSetInputPortMatrixDimensions(S, inputPortIdx, m, n)。 4.其他情况,则用:ssSetInputPortDimensionInfo(S, inputPortIdx, dimsInfo)。dimsInfo结构体包含:width, number of dimensions, dimensions of the port。 ssSetInputPortDirectFeedThrough(S, inputPortIdx, needsInput); // mdlOutputs,mdlGetTimeOfNextVarHit //详见 sfuntmpl_directfeed.txt if(!ssSetNumOutputPorts(S, nOutputPorts)) return; //设置输出端口的个数 if(!ssSetOutputPortDimensionInfo(S, outputPortIdx, DYNAMIC_DIMENSION)) return; //与input相似 ssSetNumSampleTimes( S, 1); //设置采样时间(大于0的整数或PORT_BASED_SAMPLE_TIMES) ssSetNumRWork( S, 0);//number of real work vector elements ssSetNumIWork( S, 0);//number of integer work vector elements ssSetNumPWork( S, 0);//number of pointer work vector elements ssSetNumModes( S, 0);//number of mode work vector elements ssSetNumNonsampledZCs( S, 0);//number of nonsampled zero crossings ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE); //详见sfun_simstate.c ssSetOptions( S, 0); //ssSetOptions(S, (SS_OPTION_name1 | SS_OPTION_name2)) }//mdlInitializeSizes结束
#define MDL_SET_INPUT_PORT_FRAME_DATA #if defined(MDL_SET_INPUT_PORT_FRAME_DATA) && defined(MATLAB_MEX_FILE) static void mdlSetInputPortFrameData(SimStruct *S, int portIndex, Frame_T frameData) { //这个函数为输入端口的候选框设置(FRAME_YES,FRAME_NO),如果设置成功,则函数可继续并设置ssSetInputPortFrameData(S, portIndex, frameData);如果设置失败,则通过ssSetErrorStatus生成错误。任何的其他动态输入输出都会调用ssSetInputPortFrameData,ssSetOutputPortFrameData。 } #endif //MDL_SET_INPUT_PORT_FRAME_DATA
#define MDL_SET_INPUT_PORT_WIDTH #if defined(MDL_SET_INPUT_PORT_WIDTH) && defined(MATLAB_MEX_FILE) static void mdlSetInputPortWidth(SimStruct *S, int portIndex, int width) { //端口宽度动态调节ssSetInputPortWidth,ssSetOutputPortWidth } #endif //MDL_SET_INPUT_PORT_WIDTH
#define MDL_SET_OUTPUT_PORT_WIDTH #if defined(MDL_SET_OUTPUT_PORT_WIDTH) && defined(MATLAB_MEX_FILE) static void mdlSetOutputPortWidth(SimStruct *S, int portIndex, int width) { //端口宽度动态调节ssSetInputPortWidth,ssSetOutputPortWidth } #endif //MDL_SET_OUTPUT_PORT_WIDTH
#define MDL_SET_INPUT_PORT_DIMENSION_INFO #if defined(MDL_SET_INPUT_PORT_DIMENSION_INFO) && defined(MATLAB_MEX_FILE) static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T portIndex, const DimsInfo_T) { //为未知维度的输入端口做备选设置。例详见:matlabroot/simulink/src/sfun_matadd.c } #endif //MDL_SET_INPUT_PORT_DIMENSION_INFO
#define MDL_SET_OUTPUT_PORT_DIMENSION_INFO #if defined(MDL_SET_OUTPUT_PORT_DIMENSION_INFO) && defined(MATLAB_MEX_FILE) static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T portIndex, const DimsInfo_T) { //为未知维度的输入端口做备选设置。例详见:matlabroot/simulink/src/sfun_matadd.c } #endif //MDL_SET_OUTPUT_PORT_DIMENSION_INFO
#define MDL_SET_INPUT_PORT_SAMPLE_TIME #if defined(MDL_SET_INPUT_PORT_SAMPLE_TIME) && defined(MATLAB_MEX_FILE) static void mdlSetInputPortSampleTime(SimStruct *S, int_T portIdx, real_T sampleTime, real_T offsetTime) { // } #endif //MDL_SET_INPUT_PORT_SMAPLE_TIME
#define MDL_SET_OUTPUT_PORT_SAMPLE_TIME #if defined(MDL_SET_OUTPUT_PORT_SAMPLE_TIME) && defined(MATLAB_MEX_FILE) static void mdlSetOutputPortSampleTime(SimStruct *S, int_T portIdx, real_T sampleTime, real_T offsetTime) { // } #endif //MDL_SET_OUTPUT_PORT_SMAPLE_TIME
static void mdlInitializeSampleTimes(SimStruct *S) { //设置采样时间,如果未设置,则假定有个继承的采样时间。 //格式:[sample_time, offset_time] //ssSetSampleTime(S, sampleTimePairIndex, sample_time) //ssSetOffsetTime(S, offsetTimePairIndex, offset_time) ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME); ssSetOffsetTime(S, 0, 0.0); }//end mdlInitializeSampleTimes
#define MDL_SET_INPUT_PORT_DATA_TYPE #if defined(MDL_SET_INPUT_PORT_DATA_TYPE) && defined(MATLAB_MEX_FILE) static void mdlSetInputPortDataType(SimStrcut *S, int portIndex, DTypeId dType) { // 该方法和动态的输入端口候选数据一起调用。详见matlabroot/simulink/include/simstruc_types.h 中的内置类型定义:SS_DOUBLE, SS_BOOLEAN, etc; 例详见:matlabroot/simulink/src/sfun_dtype_io.c 。 } #endif//MDL_SET_INPUT_PORT_DATA_TYPE
bdc7
#define MDL_SET_OUTPUT_PORT_DATA_TYPE #if defined(MDL_SET_OUTPUT_PORT_DATA_TYPE) && defined(MATLAB_MEX_FILE) static void mdlSetOutputPortDataType(SimStrcut *S, int portIndex, DTypeId dType) { // 同上 } #endif//MDL_SET_OUTPUT_PORT_DATA_TYPE
#define MDL_SET_DEFAULT_PORT_DATA_TYPE #if defined(MDL_SET_DEFAULT_PORT_DATA_TYPE) && defined(MATLAB_MEX_FILE) static void mdlSetDefaultPortDataTypes(SimStruct *S) { //当你的信息不足以确定唯一的输入输出数据类型时调用此函数。 } #endif //MDL_SET_DEFAULT_PORT_DATA_TYPE
#define MDL_SET_INPUT_PORT_COMPLEX_SIGNAL #if defined(MDL_SET_INPUT_PORT_COMPLEX_SIGNAL) && defined(MATLAB_MEX_FILE) static void mdlSetInputPortComplexSignal(SimStruct *S, int portIndex, CSignal_T cSignalSetting) { //用于候选复杂信号设置(COMPLEX_YES,COMPLEX_NO)。 //ssSetInputPortComplexSignal , ssSetOutputPortComplexSignal } #endif //MDL_SET_INPUT_PORT_COMPLEX_SIGNAL
#define MDL_SET_OUTPUT_PORT_COMPLEX_SIGNAL #if defined(MDL_SET_OUTPUT_PORT_COMPLEX_SIGNAL) && defined(MATLAB_MEX_FILE) static void mdlSetOutputPortComplexSignal(SimStruct *S, int portIndex, CSignal_T cSignalSetting) { //同上。 //ssSetInputPortComplexSignal , ssSetOutputPortComplexSignal } #endif //MDL_SET_OUTPUT_PORT_COMPLEX_SIGNAL
#define MDL_SET_DEFAULT_PORT_COMPLEX_SIGNALS #if defined(MDL_SET_DEFAULT_PORT_COMPLEX_SIGNALS) && defined(MATLAB_MEX_FILE) static void mdlSetDefaultPortComplexSignals(SimStruct *S) { //当信息不足时调用 } #endif// MDL_SET_DEFAULT_PORT_COMPLEX_SIGNALS
#define MDL_INITIALIZE_CONDITIONS #if defined(MDL_INITIALIZE_CONDITIONS) static void mdlInitializeConditions(SimStruct *S) { //初始化连续变量和离散变量。 } #endif //MDL_INITIALIZE_CONDITIONS
#define MDL_START #if defined(MDL_START) static void mdlStart(SimStruct *S) { //在模块执行时调用一次(初始化)。 } #endif //MDL_START
#define MDL_SIM_STATE #if defined(MDL_SIM_STATE) static mxArray* mdlGetSimState(SimStruct *S) { //inSinState MATLAB data structure } #endif//MDL_SIM_STATE
#define MDL_GET_TIME_OF_NEXT_VAR_HIT #if defined(MDL_GET_TIME_OF_NEXT_VAR_HIT) && (defined(MATLAB_MEX_FILE)) || defined(NRT)) static void mdlGetTimeOfNextVarHit(SimStruct *S) { time_T timeOfNextHit = ssGetT(S) ssSetTNext(S, timeOfNextHit); } #endif//MDL_GET_TIME_OF_NEXT_VAR_HIT
static void mdlOutputs(SimStruct *S, int_T tid) { }
#define MDL_UPDATE #if defined(MDL_UPDATE) static void mdlUpdate(SimStruct *S, int_T tid) { //更新离散变量 } #endif //MDL_UPDATE
static void mdlTerminate(SimStruct *S) { //在这个函数中,执行模拟终止所需操作。如释放内存。 }
}
#ifdef MATLAB_MEX_FILE #include "simulink.c" #else #include "cg_sfun.h" #endif
如果有什么错误望指教。
参考Matlab官方文档sfuntmpl_doc.c
相关文章推荐
- Simulink之S-function函数笔记之一
- Simulink之S-function函数笔记之二
- 31.笔记go语言——go doc命令
- matlab(Simulink)中S-function函数编写规则
- Simulink学习笔记2--simulink模块操作
- [DOC]Aspack2.11脱壳笔记
- Espresso学习笔记--google doc前四篇部分翻译和理解
- React Doc阅读笔记一 — Why React ? && Displaying Data
- matlab-simulink中s-function函数…
- MFC Doc/View笔记(一) 打开文件代码跟踪
- 13.scala编程思想笔记——ScalaDoc
- python笔记13 - 系统模块,自定义模块的编写,模块的搜索路径,PYTHONPATH环境变量,模块的属性:__doc__, __all__,__file__,标准库模块,包
- Simulink学习笔记1--simulink基础
- python-property、docstring--笔记
- matlab(Simulink)中S-function函数编写规则
- 深度学习笔记——Word2vec和Doc2vec原理理解并结合代码分析
- Java学习笔记——生成doc说明文档的方法
- perl笔记--http://perldoc.perl.org/perlintro.html
- 深度学习笔记——基于Word2vec和Doc2vec的句子对匹配方法
- MATLAB学习笔记(Simulink仿真)