条件包含 (#if / #endif)
通过在模型中实现变体,可以在代码中生成预处理器条件句指令。在生成的代码中,预处理器条件句指令选择一个要在编译时执行的代码节。
此示例使用 Simulink.Variant
对象来控制 Variant Subsystem 模块。有关控制变体的其他方式的信息,请参阅Variant Control Modes in Variant Blocks。有关除 Variant Subsystem 模块之外的变体类型的信息,请参阅什么是变体以及何时使用变体。
检查模型
打开示例模型 PreprocessorConditionalsUsingVariantSubsystem
。
model = 'PreprocessorConditionalsUsingVariantSubsystem';
open_system(model);
此模型包含两个可变子系统 LeftController
和 RightController
,其中每个子系统包含两个子级子系统 Linear
和 Nonlinear
。模型的 PostLoadFcn
回调函数加载 rtwdemo_preprocessor_data.mat
。要查看该回调函数,请从 Simulink 工具条中,点击建模选项卡,然后在设置部分中,点击模型设置 > 模型属性。在“模型属性”对话框中,打开回调选项卡并选择 PostLoadFcn。或者,以编程方式查看该回调函数。
get_param(model,'PostLoadFcn')
ans = 'load preprocessor_data.mat'
回调函数实例化两个 Simulink.Variant
对象,即 LINEAR
和 NONLINEAR
,以及一个 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
LeftController
和 RightController
使用 LINEAR
和 NONLINEAR
分别作为其 Linear
和 Nonlinear
子系统的变体控制项表达式。要查看此配置,请右键点击 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
预处理器指令,这些指令使用 LINEAR
和 NONLINEAR
来选择一个变体进行编译。
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