您可以检查Simulink如何金宝app®引擎与两个视角的S函数交互:
过程的角度,也就是说,在模拟的某个点上,引擎调用s函数。
数据透视,即发动机和s功能在模拟过程中如何交换信息。
下面的图显示了Simulink引擎在s函数中调用回调方法的顺序。金宝app实矩形表示总是在模型初始化期间或在每个时间步骤中发生的回调。虚线矩形表示可能在初始化和/或在模拟循环期间的某些或所有时间步骤中发生的回调。请参阅每个回调方法的文档,以确定引擎调用回调的确切环境。
请注意
流程视图图表示包含连续和离散状态、支持过零检测并驻留在使用可变步长求解器的模型中的s函数的执行。不同的求解器会在图中省略某些步骤。为了更好地理解Simulink引擎如何执行特定的s函数,请使用Simulin金宝appk调试器运行包含s函数的模型。有关更多信息,请参见调试器简介.
在下面的模型初始化循环中,Simulink引擎为即将进行的仿真配置s函数。金宝app引擎总是对mdlinitializatize
和mdlInitializeSampleTime
建立s函数的基本属性,包括输入输出端口、s函数对话参数、工作向量、采样次数等。
引擎根据需要调用其他方法来完成S-function初始化。例如,如果s函数使用功向量,引擎调用mdlSetWorkWidths
.同样,如果mdlinitializatize
方法延迟设置输入和输出端口属性时,引擎调用完成端口初始化所需的任何方法,例如mdlSetInputPortWidth
,在信号传播期间。的mdlStart
方法调用的mdlCheckParameters
和mdlProcessParameters
方法如果S函数使用对话框参数。
请注意
的mdlinitializatize
当您在“s -函数块参数”对话框中输入已编译s -函数的名称时,回调方法也会运行。
初始化之后,Simulink引擎执行以下仿真循环。金宝app如果模拟循环被中断,无论是手动或错误发生时,引擎直接跳转到mdlterminate.
方法。如果模拟是手动停止的,那么引擎在调用之前首先完成当前时间步骤mdlterminate.
.
如果您的模型在给定的模型层次结构级别上包含多个S-Function块,那么引擎将在继续执行下一个方法之前为每个S-Function调用特定的方法。例如,引擎调用所有的mdlinitializatize
在调用之前的方法mdlinitializateMpletimes
方法。该引擎使用块排序顺序来确定执行S函数的顺序。要了解有关引擎如何确定块执行顺序的更多信息,请参阅控制和显示执行顺序.
如果你使用金宝appSimulink Coder™产品为包含S-functions的模型生成代码时,Simulink引擎不会执行上面列出的整个调用序列。金宝app初始化继续进行,直到引擎到达mdlStart
方法。引擎然后调用如下图所示的S-function方法mdlRTW
方法是独一无二的金宝app仿真软件编码器产品。
如果S函数驻留在有条件执行的子系统中,则可以生成的代码交错呼叫mdlInitializeConditions
和mdlStart
.考虑以下Simulink模型。金宝app
模型包含两个部分nonvirtual子系统,有条件执行的启用子系统名为Reset,原子子系统名为atomic。每个子系统都包含一个调用S-Function的S-Function块dsfunc.c
,它模拟了一个具有两种状态的离散状态空间系统。enabled子系统Reset复位子系统启用时的状态值和子系统禁用时的输出值。
使用通用实时(GRT)目标,生成的代码适用于模型范围开始
函数调用这件事开始
两个子系统的函数,然后调用模型范围MdlInitialize
函数,如下代码所示:
void MdlStart(void){/*剪接*/ /*启动启用的子系统:'/Reset' */ sfcndemo_enablesub_Reset_Start();/* end of Start for子系统:' /Reset' */ /* Start for原子子系统:' / atomic ' */ sfcndemo_enablesub_Atomic_Start();/* end of Start for子系统:' /Atomic' */ MdlInitialize();
的开始
函数调用子系统的InitializeConditions
功能:
void sfcndemo_enablesub_Reset_Start(void) {sfcndemo_enablesub_Reset_Init();/*剪切*/}
的MdlInitialize
函数,在MdlStart
,包含对此的呼叫InitializeConditions
原子子系统的函数:
void MdlInitialize(void){/*原子子系统的初始化条件:'<根>/原子' */ sfcndemo_enablesub_Atomic_Init();}
因此,model-wide开始
功能交织呼叫到开始
和InitializeConditions
两个子系统的函数和它们所包含的s函数。
有关的更多信息金宝app仿真软件编码器产品以及它是如何与s功能相互作用的,看s -函数和代码生成(金宝app仿真软件编码器).
在外部模式下运行Simulink模型时,S函数金宝app例程的调用序列如下图所示更改。
引擎调用mdlRTW
一次,当它进入外部模式时,以及每次参数更改或单击时再次更新模型在建模选项卡。
请注意
在外部模式下运行Si金宝appmulink模型需要金宝app仿真软件编码器产品。
s功能块具有输入和输出信号、参数和内部状态,以及其他通用工作区。通常,块输入和输出被写入和从块I/O向量中读取。输入也可以来自
通过root Inport块外部输入
接地(输入信号未接或接地)
块输出也可以通过根Outport块转到外部输出。除了输入和输出信号外,s函数还可以有
持续的状态
离散状态
其他工作区域,如真实,整数或指针工作向量
您可以使用“s -功能块参数”对话框将参数传递给s -功能块。
下图显示了这些不同类型数据之间的一般映射。
一个函数的mdlinitializatize
例程设置各种信号和向量的大小。在仿真环路期间调用的S函数方法可以确定信号的大小和值。
s函数法可以通过两种方式访问输入信号:
通过指针
使用连续的输入
在仿真循环中,使用
InputRealPtrstype Uptrs = SSGetInputPortRealSignalPtrs(S,portindex.)
这将返回带有索引的输入端口的指针数组portindex.
,在那里portindex.
从0开始。每个输入端口都有一个指针数组。要访问该数组的元素,必须使用
* uPtrs(元素)
下图描述了如何访问具有两个输入的s函数的输入信号。
如上图所示,输入数组指针可以指向内存中不相邻的位置。
您可以使用此代码检索输出信号。
real_T *y = ssGetOutputPortSignal(S,outputPortIndex);
一个函数的mdlinitializatize
方法可以指定其输入信号的元素必须占用连续的内存区域,使用sssetInputPortRequiredContiful.
.如果输入是连续的,则可以使用其他方法ssgetInputportSignal.
来访问输入。
介绍如何访问特定端口的所有输入信号,并将其写入输出端口。上图显示了指针的输入数组可以指向块I/O向量中的不连续项。特定端口的输出信号形成一个连续的向量。因此,访问输入元素并将它们写入输出元素(假设输入端口和输出端口宽度相等)的正确方法是使用此代码。
int_T元素;int_T porttwidth = ssgetinputporttwidth (S,inputPortIndex); / /输入端口索引InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,inputPortIndex);real_T *y = ssGetOutputPortSignal(S,outputPortIdx);(元素= 0;元素< portWidth;元素++){y[element] = *uPtrs[element];}
一个常见的错误是试图通过指针运算来访问输入信号。例如,如果你要放置
real_T *u = *uPtrs;/ * * /不正确
的初始化下方Uptrs.
并更换上述环的内部
* y ++ = * u ++;/ * * /不正确
代码被编译,但是MEX文件可能会使Simulink软件崩溃。金宝app这是因为有可能访问无效内存(这取决于您如何构建模型)。当不正确地访问输入信号时,当进入S-function块的信号不是连续的时,就会发生崩溃。当信号通过虚拟连接块(如Mux或Selector块)时,就会发生不连续的信号数据。
要验证您的S功能是否正确访问了宽输入信号,请将复制信号传递给S函数的每个输入端口。为此,创建一个Mux块,其中输入端口数等于进入S函数的所需信号的宽度。然后,将驱动源连接到每个S函数输入端口,如下图所示。最后,使用此输入信号运行S-函数以验证它不会崩溃并产生预期的结果。