主要内容

指定S函数采样时间

关于采样时间

可以在中指定S函数的采样时间行为MDL线性化采样次数. 您的S函数可以从驱动它的块继承它的速率,或者定义它自己的速率。

您可以将S函数速率(即采样时间)指定为

  • 基于块的样品时间

  • 基于端口的采样时间

  • 基于块和基于端口的混合采样时间

对于基于块的采样时间,S函数在模拟的初始化阶段为整个块指定一组操作速率。对于基于端口的采样时间,S函数在初始化期间为每个输入和输出端口分别指定采样时间。在模拟阶段,使用基于块的采样时间在这种情况下,S函数在块的每次采样命中时处理所有输入和输出。相比之下,对于基于端口的采样时间,块仅在该端口的采样命中时处理特定端口。

例如,考虑两个采样率,分别为0.5秒和0.25秒:

  • 在基于块的方法中,选择0.5和0.25将指示块以0.25秒的增量执行输入和输出。

  • 在基于端口的方法中,将输入端口设置为0.5,将输出端口设置为0.25会导致块处理2 Hz的输入和4 Hz的输出。

如果应用程序要求输入和输出执行的采样率不相等,或者不希望以块的最高采样率运行输入和输出端口时产生的开销,则应使用基于端口的采样时间。

在某些应用中,S功能块可能需要在内部以一个或多个采样率运行,同时以其他速率输入或输出信号。基于块和端口的混合指定采样率方法允许您创建这样的块。

在典型应用程序中,仅指定一个基于块的采样时间。高级S函数可能需要指定基于端口的采样时间或多个块采样时间。

基于块的样品时间

C MEX S函数在中指定基于块的采样时间信息

接下来的两节讨论如何为C MEX s -函数指定基于块的示例时间。第三部分给出了一个简单的示例,展示了如何指定示例时间MDL线性化采样次数. 有关详细示例,请参见mixedm.c

指定采样次数(以MDLinitalizeSizes为单位)

要为基于块的采样时间配置S函数,请使用

ssSetNumSampleTimes(年代,numSampleTimes);

哪里numSampleTimes > 0.这告诉Simulink金宝app®S函数具有基于块的采样时间的引擎。引擎调用MDL线性化采样次数,从而设置采样时间。

在mdlInitializeSampleTimes中设置采样时间和指定函数调用

MDL线性化采样次数指定两条执行信息:

您将样本次数指定为对采样时间、偏移时间,使用这些宏

ssSetSampleTime(年代,sampleTimePairIndex采样时间ssSetOffsetTime(年代,offsetTimePairIndex, offset_time

哪里sampleTimePairIndexoffsetTimePairIndex从0开始。

有效的示例时间对是(大写值是定义在simstruc.h):

[continuous_sample_time, 0.0] [continuous_sample_time, fixed_in_minor_step_offset]discrete_sample_period,抵消][变量样本时间,0.0]

或者,您可以指定样本时间是从驱动块继承的,在这种情况下,s函数只能有一个样本时间对,

(INHERITED_SAMPLE_TIME, 0.0)

[继承的\u采样\u时间,固定的\u在\u次要\u步长\u偏移]

请注意

如果你的s函数继承了它的样本时间,你应该指定在一个被引用的模型中使用s函数是否安全,例如,一个被另一个模型引用的模型。看到指定模型引用样本时间继承为更多的信息。

以下准则可能有助于指定采样时间:

  • 在较小的集成步骤中发生更改的连续函数应该注册[连续采样时间,0.0]样品时间。

  • 在次要集成步骤中不会更改的连续函数应注册[CONTINUOUS_SAMPLE_TIME, FIXED_IN_MINOR_STEP_OFFSET]样品时间。

  • 以指定速率变化的离散函数应寄存器离散采样时间对

    discrete_sample_period,抵消

    哪里

    discrete_sample_period> 0.0

    0.0 <=抵消<discrete_sample_period
  • 一个以可变速率变化的离散函数应该注册可变步长离散函数[变量样本时间,0.0]样品时间。在C MEX s -函数中mdlGetTimeOfNextVarHit函数以获取可变步长离散任务的下一个样本命中时间VARIABLE_SAMPLE_TIME只能与可变步长解算器一起使用。

如果函数没有固有的采样时间,则必须根据以下准则指示它是继承的:

  • 即使在较小的集成步骤中,随着输入的更改而更改的函数也应注册[继承的样本时间,0.0]样品时间。

  • 一个函数,当其输入发生变化时会发生变化,但在次要集成步骤中不会发生变化(意思是在次要步骤中保持不变),应该注册[继承的\u采样\u时间,固定的\u在\u次要\u步长\u偏移]样品时间。

在执行期间检查是否命中样本(在计算输出mdlUpdate),用取样命中ssIsContinuousTask宏。例如,使用以下代码片段检查连续的示例命中:

如果(ssIsContinuousTask(S,tid)){}

要确定第三个(离散)任务是否命中,请使用以下代码片段:

如果(取样命中(S, 2, tid) {}

Simu金宝applink引擎始终为指定索引0到连续采样率,如果它存在,但是你得到不正确的结果,如果你使用ssIsSampleHit(S,0,tid)

示例:MDLinitalizeSampleTimes

此示例指定有两个离散的采样时间,周期分别为0.01秒和0.5秒。

静态空隙MDL线性化采样次数(SimStruct *S) {ssSetSampleTime(S, 0, 0.01);ssSetOffsetTime(年代,0,0.0);ssSetSampleTime (S, 1, 0.5);ssSetOffsetTime (S, 1, 0.0);} /* mdlInitializeSampleTimes结束。*/

指定基于端口的采样时间

不能对既没有输入端口也没有输出端口的S函数使用基于端口的采样时间。如果S函数使用基于端口的采样时间且没有端口,则S函数在更新或运行Simulink模型时会产生错误。如果S函数上的输入或输出端口数可变,则应向S函数中添加额外的保护,以确保端口总数不会变为零。金宝app

要在C MEX s -函数中使用基于端口的样本次数,必须在s -函数中指定基于端口的样本次数中密度方法:

ssSetNumSampleTimes(年代,PORT_BASED_SAMPLE_TIMES)

您还必须指定s函数中每个输入和输出端口的采样时间中密度方法,使用以下宏

ssSetInputPortSampleTime(S,idx,period)ssSetInputPortOffsetTime(年代,idx抵消)ssSetOutputPortSampleTime(S,idx,period)ssSetOutputPortOffsetTime(年代,idx抵消)

呼吁ssSetNumSampleTimes是否可以放置在基于端口的样品时间实际指定的之前或之后中密度.然而,如果ssSetNumSampleTimes没有将s功能配置为使用基于端口的采样次数,端口上设置的任何采样次数都将被忽略。

对于任何给定的端口,可以指定

  • 一个特定的采样时间和周期

    例如,以下代码将S函数第一个输入端口的采样时间设置为0.1以及偏移时间0

    ssSetInputPortSampleTime(S,0,0.1);ssSetInputPortOffsetTime(S,0,0);
  • 继承样本时间(-1),即端口从其连接的端口继承其采样时间(请参阅指定端口继承样例时间

  • 恒定采样时间(Inf),即来自端口的信号是恒定的(见为端口指定恒定采样时间(Inf)

    请注意

    要在被触发的子系统中可用,所有的s功能端口必须继承(–1)或常数采样时间(Inf)。有关详细信息,请参阅配置在触发子系统中使用的基于端口的示例时间

指定端口继承样例时间

若要指定端口的示例时间在C MEX s -函数中继承,则中密度方法应将其周期设置为-1和它的偏移量0.例如,以下代码为C MEX s -函数的第一个输入端口指定继承的示例时间:

ssSetInputPortSampleTime (0, 1);ssSetInputPortOffsetTime (0, 0);

指定基于端口的采样时间时,Simulink引擎将调用金宝appmdlSetInputPortSampleTimemdlSetOutputPortSampleTime来确定遗传信号的速率。

一旦确定了所有的速率,引擎就会调用MDL线性化采样次数.尽管此时不需要初始化基于端口的示例时间,但引擎会调用此方法,以便为S-function提供配置函数调用连接的机会。因此,无论s -函数是使用基于端口的示例时间还是使用函数调用连接,都必须为该方法提供实现。尽管可以提供空实现,但您可能希望使用它来检查在示例时间传播期间块继承的示例时间的适当性。使用ssGetInputPortSampleTimessGetOutputPortSampleTime在里面MDL线性化采样次数获取继承的采样时间的值MDL线性化采样次数检查s函数的第一个输入是否继承了连续的采样时间。

如果(!ssGetInputPortSampleTime(S,0)) {ssSetErrorStatus(S,"Cannot inherit a continuous sample time.")};

请注意

如果您指定您的s函数端口继承它们的示例时间,那么您还应该指定在引用的模型中使用s函数是否安全,例如,由另一个模型引用的模型。看到指定模型引用样本时间继承为更多的信息。

如果编写TLC代码以从S函数生成内联代码,并且TLC代码包含输出函数,如果这些条件为真,则必须修改TLC代码:

  • 输出端口有一个恒定值。它使用或继承的示例时间Inf

  • s函数是一个多速率s函数或使用基于端口的采样时间。

在这种情况下,TLC代码必须使用该函数为常量输出端口生成代码输出端口而不是函数输出. 有关详细信息,请参阅为端口指定恒定采样时间(Inf)

防止端口继承的采样时间Inf,设置选项SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME在S函数代码中。在这种情况下,可以使用TLC函数输出为常量输出端口生成代码。

指定恒定采样时间(Inf)港口

如果s函数使用基于端口的采样时间,则可以将采样时间设置为Inf在它的任何端口上。基于端口的时间采样Inf表示进入或离开端口的信号保持不变。

要使端口输出为常量值,S函数必须:

  • 使用ssSetOptions在其中密度方法添加对示例时间的支持金宝appInf

    ssSetOptions(S、SS\U选项\U允许\U常量\U端口\U采样时间);

    请注意

    这个选项使S-function的端口支持的示例时间为金宝appInf,包括从其他块继承样本时间的端口。如果继承采样时间的S-function端口不能有采样时间Inf,则发生错误。控件设置这些端口的采样时间mdlSetInputPortSampleTimemdlSetOutputPortSampleTime方法。

  • 设置端口的采样时间为Inf和它的偏移量0,例如:。,

    ssSetInputPortSampleTime(S,0,mxGetInf());ssSetInputPortOffsetTime(S,0,0);
  • 检查计算输出方法是否有效tid参数等于恒量如果是,则设置端口的输出值(如果它是输出端口)。

要查看如何创建输出常量值的端口的示例,请参阅sfun_port_constant.c的源文件sfcndemo_port_constant实例

如果编写TLC代码以从S函数生成内联代码,并且TLC代码包含输出函数,如果这些条件都为真,则修改TLC代码:

  • 输出端口有一个恒定值。它使用或继承的示例时间Inf

  • s函数是一个多速率s函数或使用基于端口的采样时间。

在这种情况下,TLC代码必须使用该函数为常量输出端口生成代码输出端口而不是函数输出.这个函数输出端口为S函数的常量值组件生成输出代码。如果将模型配置为生成多任务代码,输出端口也生成s函数的周期分量的输出代码。

例如,查看TLC文件sfun_端口_常数.tlc对于C-S函数sfun_port_constant.c在模型中sfcndemo_port_constant.在模型中,S-Function2块的输入值在整个仿真过程中都是常数。在s函数代码中,第一个输出端口继承了输入端口的采样时间,因此输出端口也有一个恒定值。s -功能代码直接为第二个输出端口指定一个常量。

在TLC代码中,如果端口具有常量值,则函数输出不为第一个输出端口生成代码。该函数在任何情况下都不会为第二个输出端口生成代码,因为该端口始终具有常量值。

对于这个功能,输出端口为具有常量值的输出端口生成代码。代码生成器调用函数输出端口,并设置参数tid对应于常量值的任务标识符。仅当输出端口的任务标识符对应于常量值时,输出端口然后为端口生成代码。

配置在触发子系统中使用的基于端口的示例时间

要在触发子系统中使用C MEX s -函数,基于端口的示例时间s -函数必须执行以下任务。

  • 使用ssSetOptions中密度方法表示s函数可以在被触发的子系统中运行:

    ssSetOptions(S、SS\U选项\U允许\U端口\U采样\U时间\U触发);
  • 将其所有端口设置为继承(-1)或常数采样时间(Inf)在其中密度方法

  • 处理被触发样例时间的继承mdlSetInputPortSampleTimemdlSetOutputPortSampleTime方法如下。

    由于S函数端口继承其采样时间,Simulink引擎调用金宝appmdlSetInputPortSampleTimemdlSetOutputPortSampleTime在样本时间传播过程中。宏SSSampleAndOffsetRetrigged可在这些方法中使用,以确定S功能是否位于触发子系统中。如果S函数确实位于触发子系统中,则无论调用哪种方法,都必须设置调用该函数的端口的采样时间和偏移量INHERITED_SAMPLE_TIME-1).

    将端口的采样时间和偏移量设置为INHERITED_SAMPLE_TIME指示端口的采样时间被触发,即只有当它所在的子系统被触发时,它才产生输出或接受输入。然后,该方法还必须设置所有其他s函数输入和输出端口的采样时间和偏移量,以触发或常量采样时间(Inf),以合适者为准,例如:

    静态无效mdlSetInputPortSampleTime(SimStruct*S、int\T portIdx、real\u T sampleTime real\u T offsetime){/*如果S函数位于触发子系统中,则传递给此方法的采样时间和偏移量都等于继承的_sample_时间。因此,如果触发,以下几行将输入端口的采样时间和偏移量设置为继承的_sample_时间。*/ssSetInputPortSampleTime(S,portIdx,sampleTime);ssSetInputPortOffsetTime(S,PortitDX,offsetTime);/*如果触发,将输出端口设置为inherited,以及*/If(SSSampleAndOffsetRetried(sampleTime,offsetTime)){ssSetOutputPortSampleTime(S,0,inherited_SAMPLE_TIME);ssSetOutputPortOffsetTime(S,0,inherited_SAMPLE_TIME);/*注意,如果此S函数上有其他输入和输出端口,则此时也应将它们设置为继承端口或常量。*/}

    驻留在触发子系统中的S函数无法预测Simulink引擎是否将调用金宝appmdlSetInputPortSampleTimemdlSetOutputPortSampleTime设置端口采样时间。由于这个原因,两个方法都必须能够正确地设置所有端口的样本时间,这样引擎一次只能调用其中一个方法。

  • 在里面mdlUpdate计算输出使用ssGetPortBasedSampleTimeBlockIsTriggered要检查S函数是否位于触发子系统中,如果是,请使用适当的算法计算其状态和输出。

看到sfun_端口_已触发。c的源文件sfcndemo_端口_已触发示例模型,以说明如何创建可在触发子系统中使用的s -函数。

基于块和基于端口的混合采样时间

混合采样时间分配方法结合了基于块和基于端口的方法。首先指定in中密度,块运行时的速率总数,包括块速率、输入速率和输出速率,使用ssSetNumSampleTimes

然后设置SS_OPTION_PORT_SAMPLE_TIMES_ASSIGNED选项,使用ssSetOptions,告诉模拟引擎您将使用基于端口的方法分别指定输入端口和输出端口的速率。接下来,与基于块的方法一样,使用下面的方法指定所有块的内部和外部速率的周期和偏移量

ssSetSampleTime ssSetOffsetTime

最后,与基于端口的方法一样,使用

ssSetInputPortSampleTime(S, idx, period) ssSetInputPortOffsetTime(S, idx, offset) ssSetOutputPortSampleTime(S, idx, period) ssSetOutputPortOffsetTime(S, idx, offset) ssSetOutputPortSampleTime(S, idx, period) ssSetOutputPortOffsetTime(S, idx, offset)

请注意,每个分配的端口速率必须与先前声明的一个块速率相同。有关示例S函数,请参阅mixedm.c

请注意

如果你使用SS_OPTION_PORT_SAMPLE_TIMES_ASSIGNED选项,则S函数不能继承采样时间。相反,您必须指定每个输入和输出端口的运行速率。

多速率S功能块

在多速率S函数块中,您可以封装定义函数中每个行为的代码计算输出mdlUpdate函数的一个语句,该语句确定是否发生了样本命中。在C MEX s -函数中取样命中宏决定当前时间是否为指定的采样时间的采样命中。宏的语法如下:

ssIsSampleHit(S、st_索引、tid)

哪里年代SimStructst_index标识特定的采样时间索引,以及tid为任务ID (tid这是一个论据计算输出mdlUpdate功能)。

例如,C MEX S函数中的这些语句指定了三个采样时间:一个用于连续行为,两个用于离散行为。

ssSetSampleTime(S,0,连续采样时间);ssSetSampleTime(S,1,0.75);ssSetSampleTime(S,2,1.0);

mdlUpdate函数,下面的语句封装了定义0.75秒采样时间的行为的代码。

如果(ssIsSampleHit(S,1,tid)){}

第二个参数,1,对应于第二个采样时间,0.75秒。

使用下面的代码行来封装定义连续示例命中行为的代码:

如果(ssIsContinuousTask(S,tid)){}

为连续块定义采样时间的示例

此示例定义了连续块的采样时间。

/*初始化采样时间和偏移量。*/static void mdlinializeSampleTimes(SimStruct*S){ssSetSampleTime(S,0,连续采样时间);ssSetOffsetTime(S,0,0.0);}

您必须将此语句添加到中密度函数。

ssSetNumSampleTimes(S,1);

为混合块定义采样时间的示例

此示例定义了混合S功能块的采样时间。

/*初始化采样时间和偏移量。*/静态void mdlinializeSampleTimes(SimStruct*S){/*连续状态采样时间和偏移量。*/ssSetSampleTime(S,0,连续采样时间);ssSetOffsetTime(S,0,0.0);/*离散状态采样时间和偏移量。*/ssSetSampleTime(S,1,0.1);ssSetOffsetTime(S,1,0.025);}

在第二个采样时间,偏移量会导致Simulink引擎调用金宝appmdlUpdate在以下时刻起作用:0.025秒、0.125秒、0.225秒,等等,以0.1秒为增量。

下面的语句指示定义了多少个采样时间,它也出现在中密度函数。

ssSetNumSampleTimes(S,2);

多速率S函数与采样时间命中计算

对于固定步长解算器,Simulink使用整数算法金宝app而不是浮点算法来计算采样时间命中。因此,任务时间是其相应采样时间段的整数倍。

如果考虑在多速率S-函数中基于任务时间执行布尔逻辑,则这种计算方法变得重要。例如,考虑具有两个采样时间的S函数。事实上,(SSISSAMPHILT(S,IDX1)=Trand和SSISSAMPHILT(S,IDX2)=true)不保证SSGETTASKTIME(S,IDX1)=SSGETTASKTIME(S,IDX2)。

同步多速率s -功能块

如果不同速率的任务需要共享数据,则必须确保一个任务生成的数据在另一个不同速率的任务访问时是有效的。你可以使用特殊采样中的宏mdlUpdate计算输出多速率S函数的例程,以确保共享数据有效。此宏返回符合事实的如果样本命中在同一时间步中以一种速率发生,而样本命中也以另一种速率发生。因此,它允许较高速率的任务以较慢速率的任务可以适应的速率提供较慢速率的任务所需的数据。使用特殊采样宏,较慢的采样时间必须是较快的采样时间的整数倍。

例如,假设您的模型有一个以一种速率运行的输入端口(采样时间索引为0)和一个以较慢速率运行的输出端口(采样时间索引为1)。此外,假设您希望输出端口输出当前输入上的值。以下示例说明了此宏的用法。

if(ssIsSampleHit(S,0,tid){if(ssIsSpecialSampleHit(S,0,1,tid){/*将输入传输到输出内存。*/..}}if(ssIsSampleHit(S,1,tid){/*发出输出。*/..}

在本例中,当以输入速率发生采样命中时,第一个块将运行。如果命中也以输出速率发生,则块将输入传输到输出存储器。第二个块在样本命中以输出速率发生时运行。它将其内存区域中的输出传输到块的输出。

请注意,速率较高的任务总是在速率较低的任务之前运行。因此,前面示例中的输入任务总是在输出任务之前运行,确保输出端口始终存在有效数据。

指定模型引用样本时间继承

如果您的C MEX s -函数从驱动它的块继承了它的样本时间,那么您的s -函数应该指定包含您的s -函数的引用模型是否可以从它们的父模型继承样本时间。如果s函数输出不依赖于它继承的样本时间,则使用ssSetModelReferenceSampleTimeInheritanceRule宏设置s -函数样本时间继承规则为使用\u默认\u进行\u离散\u继承. 否则,将规则设置为不允许\u样本\u时间\u继承对于包含S函数(其输出取决于继承的采样时间)的参考模型,禁止采样时间继承,从而避免意外的模拟错误。

请注意

如果您的s -函数没有设置此标志,那么Simulink引擎将假定它不排除包含该标志的引用模型继金宝app承示例时间。但是,引擎会有选择地警告您,所引用的模型包含没有指定示例时间继承规则的S-functions(请参阅其输出取决于继承的采样时间的块).

如果不确定现有S函数输出是否取决于其继承的采样时间,请检查它是否调用以下任何C宏:

  • ssGetSampleTime

  • ssGetInputPortSampleTime

  • ssGetOutputPortSampleTime

  • ssGetInputPortOffsetTime

  • ssGetOutputPortOffsetTime

  • ssGetInputPortSampleTimeIndex

  • ssGetOutputPortSampleTimeIndex

或TLC功能:

  • LibBlockSampleTime

  • CompiledModel.SampleTime

  • LibBlockInputSignalSampleTime

  • LibBlockInputSignalOffsetTime

  • LibBlockOutputSignalSampleTime

  • LibBlockOutputSignalOffsetTime

如果您的s函数没有调用这些宏或函数中的任何一个,那么它的输出不依赖于它所继承的样本时间,因此它可以安全地用于继承它们的样本时间的引用模型中。

示例时间继承规则示例

作为阻止被引用模型继承其样本时间的s函数的例子,考虑一个s函数具有以下内容计算输出方法:

static void mdlOutputs(SimStruct *S, int_T tid) {const real_T* u = (const real_T*) ssGetInputPortSignal(S,0);real_T *y = ssGetOutputPortSignal(S,0); / /输出y[0] = ssGetSampleTime(S,tid) * u[0]; / /时间}

此S函数的输出是其继承的采样时间,因此其输出取决于其继承的采样时间,因此在引用的模型中使用是不安全的。因此,此S函数应指定其模型引用继承规则,如下所示:

ssSetModelReferenceSampleTimeInheritanceRule(年代,DISALLOW_SAMPLE_TIME_INHERITANCE);

另请参阅

||

相关话题