Main Content

条件包含 (#if / #endif)

通过在模型中实现变体,可以在代码中生成预处理器条件句指令。在生成的代码中,预处理器条件句指令选择一个要在编译时执行的代码节。

此示例使用 Simulink.Variant 对象来控制 Variant Subsystem 模块。有关控制变体的其他方式的信息,请参阅Variant Control Modes in Variant Blocks。有关除 Variant Subsystem 模块之外的变体类型的信息,请参阅什么是变体以及何时使用变体

检查模型

打开示例模型 PreprocessorConditionalsUsingVariantSubsystem

model = 'PreprocessorConditionalsUsingVariantSubsystem';
open_system(model);

Capture.PNG

此模型包含两个可变子系统 LeftController RightController,其中每个子系统包含两个子级子系统 LinearNonlinear。模型的 PostLoadFcn 回调函数加载 rtwdemo_preprocessor_data.mat。要查看该回调函数,请从 Simulink 工具条中,点击建模选项卡,然后在设置部分中,点击模型设置 > 模型属性。在“模型属性”对话框中,打开回调选项卡并选择 PostLoadFcn。或者,以编程方式查看该回调函数。

get_param(model,'PostLoadFcn')
ans = 
'load preprocessor_data.mat'

回调函数实例化两个 Simulink.Variant 对象,即 LINEARNONLINEAR,以及一个 Simulink.Parameter,即 VSSMODE。当 VSSMODE 等于 0 时,LINEAR 变体处于活动状态。当 VSSMODE 等于 1 时,NONLINEAR 变体处于活动状态。VSSMODE 初始化为 1。以编程方式验证这些设置。

LINEAR.Condition
ans = 
'VSSMODE==0'
NONLINEAR.Condition
ans = 
'VSSMODE==1'
VSSMODE.Value
ans = int32
    1

LeftControllerRightController 使用 LINEARNONLINEAR 分别作为其 LinearNonlinear 子系统的变体控制项表达式。要查看此配置,请右键点击 LeftController,然后点击模块参数(子系统)。或者,以编程方式查看该变体控制项表达式。

choices = get_param(append(model,'/LeftController'),'VariantChoices');
choices(1)
ans = struct with fields:
         Name: 'LINEAR'
    BlockName: 'PreprocessorConditionalsUsingVariantSubsystem/LeftController/Linear'

choices(2)
ans = struct with fields:
         Name: 'NONLINEAR'
    BlockName: 'PreprocessorConditionalsUsingVariantSubsystem/LeftController/Nonlinear'

配置模型

打开“配置参数”对话框。在左窗格中,点击代码生成,然后确认系统目标文件设置为 ert.tlc。或者,以编程方式设置该参数。

set_param(model,'SystemTargetFile','ert.tlc');

在左窗格中,点击接口。确认Ignore custom storage classes参数处于清除状态。或者,以编程方式清除该参数。

set_param(model,'IgnoreCustomStorageClasses','off');

要生成预处理器条件句,请使用自定义存储类。

打开 LeftController 子系统的“模块参数”对话框。验证Variant activation time参数设置为 code compile。或者,以编程方式设置该参数。

set_param(append(model,'/LeftController'),'VariantActivationTime','code compile');

打开 LeftController 子系统。对于每个子级子系统,点击该子系统,并在子系统模块选项卡中,确认原子子系统处于选中状态。或者,以编程方式设置这些参数。

set_param(append(model,'/LeftController/Linear'),'TreatAsAtomicUnit','on');
set_param(append(model,'/LeftController/Nonlinear'),'TreatAsAtomicUnit','on');

生成代码。

slbuild(model);
### Starting build procedure for: PreprocessorConditionalsUsingVariantSubsystem
### Successful completion of build procedure for: PreprocessorConditionalsUsingVariantSubsystem

Build Summary

Top model targets built:

Model                                          Action                        Rebuild Reason                                    
===============================================================================================================================
PreprocessorConditionalsUsingVariantSubsystem  Code generated and compiled.  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 14.584s

查看生成的代码。生成的代码包括 #if#endif 预处理器指令,这些指令使用 LINEARNONLINEAR 来选择一个变体进行编译。

cfile = fullfile('PreprocessorConditionalsUsingVariantSubsystem_ert_rtw','PreprocessorConditionalsUsingVariantSubsystem.c');
coder.example.extractLines(cfile,"  /* Outputs for Atomic SubSystem: '<Root>/LeftController' */", "  /* End of Outputs for SubSystem: '<Root>/LeftController' */", 1, 1);
  /* Outputs for Atomic SubSystem: '<Root>/LeftController' */
#if LINEAR

  /* Outputs for Atomic SubSystem: '<S1>/Linear' */
  /* VariantMerge generated from: '<S1>/Out1' incorporates:
   *  DiscreteFilter: '<S3>/Discrete Filter'
   */
  rtY.Out1 = rtb_Add - 0.5 * rtDWork.DiscreteFilter_states_a;

  /* Update for DiscreteFilter: '<S3>/Discrete Filter' */
  rtDWork.DiscreteFilter_states_a = rtY.Out1;

  /* End of Outputs for SubSystem: '<S1>/Linear' */
#elif NONLINEAR

  /* Outputs for Atomic SubSystem: '<S1>/Nonlinear' */
  /* VariantMerge generated from: '<S1>/Out1' incorporates:
   *  DiscreteFilter: '<S4>/Discrete Filter'
   *  Lookup_n-D: '<S4>/Lookup Table'
   *  Sum: '<Root>/Add'
   */
  rtY.Out1 = look1_binlxpw(rtb_Add, rtCP_LookupTable_bp01Data,
    rtCP_LookupTable_tableData, 4U) - 0.5 * rtDWork.DiscreteFilter_states_o;

  /* Update for DiscreteFilter: '<S4>/Discrete Filter' */
  rtDWork.DiscreteFilter_states_o = rtY.Out1;

  /* End of Outputs for SubSystem: '<S1>/Nonlinear' */
#endif

相关主题