使用变体模型生成使用 C 预处理器条件句的代码
此示例说明如何使用变体模型生成使用预处理器条件句的代码,以控制哪些代码链接到嵌入式可执行文件中。
变体模型概述
您可以使用 Model 模块从一个 Simulink® 模型(父模型)引用另一个 Simulink® 模型(子模型)。Variant Subsystem 模块可以有不同的变体。这些变体可以包括一组 Model 模块,Variant Subsystem 模块从该组模块中选择一个。Model 模块所引用的模型基于规定的名义功能提供模块变体。
Variant Subsystem 模块在每个时刻只有一个变体处于激活状态。您可以使用 Variant Subsystem 模块对话框来选择激活变体。您也可以参数化激活变体的选择,并使其依赖于 MATLAB® 基础工作区中变量和对象的值。当您生成代码时,您可以生成所有变体的代码,并延迟选择激活变体,直到需要编译该代码时再选择。
指定变体模型
打开示例模型 PreprocessorConditionalsUsingVariantModel
会运行在“ModelProperties > Callbacks”对话框中定义的 PostLoadFcn。这会用 Variant Subsystem 模块的控制项变量填充基础工作区。
open_system('PreprocessorConditionalsUsingVariantModel')
Left Controller
可变子系统包含两个子 Model 模块:Linear
和 Nonlinear
。当 Simulink.Variant
对象 LINEAR
的计算结果为 true
时,Left Controller/Linear
子模型执行;当 Simulink.Variant
对象 NONLINEAR
的计算结果为 true
时,Left Controller/Nonlinear
子模型执行。
通过右键点击 Left Controller
子系统并选择 Subsystem Parameters
(这会打开 Left Controller
Variant Subsystem 模块对话框),为 Left Controller
子系统指定 Simulink.Variant
对象。
Left Controller
子系统模块对话框使用基础工作区中的两个 Simulink.Variant
对象 LINEAR
和 NONLINEAR
在 Linear
和 Nonlinear
模型模块之间创建关联。这些对象具有一个名为 Condition
的属性,它是一个计算结果为布尔值的表达式,用于确定激活变体模型(Linear
或 Nonlinear
)。条件也显示在子系统模块对话框中。在此示例中,LINEAR
和 NONLINEAR
的条件分别为 'VSSMODE == 0'
和 'VSSMODE == 1'
。
在此示例中,Simulink.Variant
对象在基础工作区中创建。
LINEAR = Simulink.Variant; LINEAR.Condition = 'VSSMODE==0'; NONLINEAR = Simulink.Variant; NONLINEAR.Condition = 'VSSMODE==1';
指定变体控制项变量
变体对象允许您在整个模型中重用任意复杂的条件。多个 Variant Subsystem 模块可以使用相同的 Simulink.Variant
对象,从而允许您将多个变体模型作为一组来切换激活的变体。您可以在仿真之前在 MATLAB 环境中或在编译生成的代码时,通过更改 VSSMODE
的值来切换一组变体,如下一节所述。在此示例中,Left Controller
和 Right Controller
引用相同的变体对象,所以您可以同时切换它们。
非线性控制器模型实现滞后,而线性控制器模型充当简单的低通滤波器。打开左侧通道的子系统。右侧通道的模型与之相似。
生成的代码作为用户定义的宏访问变体控制项变量 VSSMODE
。在此示例中,variants_importedmacros.h
提供 VSSMODE
。在 MATLAB 环境中,您是使用 Simulink.Parameter
对象指定 VSSMODE
。当生成包括预处理器条件句的代码时,它的值将被忽略。但是,该值会用于仿真。传统头文件指定在编译生成的代码时要使用的宏的值,该值最终用于激活嵌入式可执行文件中两个指定的变体之一。
可采用下列存储类之一将变体控制项变量定义为 Simulink.Parameter
对象:
指定了头文件的
Define
或ImportedDefine
CompilerFlag
SystemConstant
(AUTOSAR)在指定的头文件中将数据定义为宏的用户自定义存储类
VSSMODE = Simulink.Parameter; VSSMODE.Value = 1; VSSMODE.DataType = 'int32'; VSSMODE.CoderInfo.StorageClass = 'Custom'; VSSMODE.CoderInfo.CustomStorageClass = 'ImportedDefine'; VSSMODE.CoderInfo.CustomAttributes.HeaderFile = 'variants_importedmacros.h';
使用不同变体对模型进行仿真
由于您将 VSSMODE
的值设置为 1
,模型在仿真期间使用非线性控制器。
sim('PreprocessorConditionalsUsingVariantModel')
youtnl = yout;
如果将 VSSMODE
的值更改为 0
,则模型在仿真期间使用线性控制器。
VSSMODE.Value = int32(0);
sim('PreprocessorConditionalsUsingVariantModel')
youtl = yout;
您可以绘制和比较线性与非线性控制器的响应:
figure('Tag','CloseMe'); plot(tout, youtnl.signals(1).values, 'r-', tout, youtl.signals(1).values, 'b-') title('Response of Left Channel Linear and Nonlinear Controllers'); ylabel('Response'); xlabel('Time (seconds)'); legend('nonlinear','linear') axis([0 100 -0.8 0.8]);
使用 C 预处理器条件句
此示例模型已配置为生成 C 预处理器条件句。要为模型生成代码,请在工具条的 C 代码选项卡中选择编译。
要激活预处理器条件句的代码生成,请检查是否符合以下条件:
在“配置参数”对话框中的代码生成 > 系统目标文件中选择 Embedded Coder® 目标
在 Variant Subsystem 模块参数对话框中,将变体激活时间参数设置为
code compile
。
在此示例中,生成的代码包括对 Simulink.Variant
对象 LINEAR
和 NONLINEAR
的引用,以及对应于那些变体的宏的定义。这些定义依赖于 VSSMODE
的值,该值在外部头文件 variants_importedmacros.h
中提供。通过对宏 (#define
) LINEAR
和 NONLINEAR
使用预处理器条件句 (#if
) 可确定激活变体。
在生成的 PreprocessorConditionalsUsingVariantModel_types.h
头文件中定义宏 LINEAR
和 NONLINEAR
:
|#ifndef LINEAR| |#define LINEAR (VSSMODE == 0)| |#endif|
|#ifndef NONLINEAR| |#define NONLINEAR (VSSMODE == 1)| |#endif|
在生成的代码中,与变体相关的代码带有 C 预处理器条件句。例如,在 PreprocessorConditionalsUsingVariantModel.c
中,会根据条件来编译对每个变体的单步函数和初始化函数的调用。
关闭示例中的模型、图和工作区变量。
bdclose('PreprocessorConditionalsUsingVariantModel') close(findobj(0,'Tag','CloseMe')); clear LINEAR NONLINEAR VSSMODE clear tout yout youtl youtnl