本页对应的英文页面已更新,但尚未翻译。 若要查看最新内容,请点击此处访问英文页面。

使用变体模型生成使用 C 预处理器条件句的代码

此示例说明如何使用变体模型生成使用预处理器条件句的代码,以控制哪些代码链接到嵌入式可执行文件中。

变体模型概述

您可以使用 Model 模块从一个 Simulink® 模型(父模型)引用另一个 Simulink® 模型(子模型)。Variant Subsystem 模块可以有不同的变体。这些变体可以包括一组 Model 模块,Variant Subsystem 模块从该组模块中选择一个。下图是变体模型的概念性描述。在此示例中,Right Controller 模型模块可以从两个 Model 模块中进行选择。Model 模块所引用的模型基于规定的名义功能提供模块变体。

Variant Subsystem 模块在每个时刻只有一个变体处于激活状态。您可以使用 Variant Subsystem 模块对话框来选择激活变体。您也可以参数化激活变体的选择,并使其依赖于 MATLAB® 基础工作区中变量和对象的值。当您生成代码时,您可以生成所有变体的代码,并延迟选择激活变体,直到需要编译该代码时再选择。

指定变体模型

打开示例模型 rtwdemo_preprocessor 会运行在以下对话框中定义的 PostLoadFcn:“File:ModelProperties:Callbacks”对话框。这会用 Variant Subsystem 模块的控制变量填充基础工作区。

open_system('rtwdemo_preprocessor')

Left Controller 可变子系统包含两个子 Model 模块:LinearNonlinear。当 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 对象 LINEARNONLINEARLinearNonlinear 模型模块之间创建关联。这些对象具有一个名为 Condition 的属性,它是一个计算结果为布尔值的表达式,用于确定激活变体模型(LinearNonlinear)。条件也显示在子系统模块对话框中。在此示例中,LINEARNONLINEAR 的条件分别为 '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 ControllerRight Controller 引用相同的变体对象,所以您可以同时切换它们。

非线性控制器模型实现滞后,而线性控制器模型充当简单的低通滤波器。打开左侧通道的子系统。右侧通道的模型与之相似。

生成的代码作为用户定义的宏访问变体控制项变量 VSSMODE。在此示例中,rtwdemo_importedmacros.h 提供 VSSMODE。在 MATLAB 环境中,您是使用 Simulink.Parameter 对象指定 VSSMODE。当生成包括预处理器条件句的代码时,它的值将被忽略。但是,该值会用于仿真。传统头文件指定在编译生成的代码时要使用的宏的值,该值最终用于激活嵌入式可执行文件中两个指定的变体之一。

可采用下列存储类之一将变体控制项变量定义为 Simulink.Parameter 对象:

  • 指定了头文件的 DefineImportedDefine

  • CompilerFlag

  • SystemConstant (AUTOSAR)

  • 在指定的头文件中将数据定义为宏的用户自定义存储类

VSSMODE = Simulink.Parameter;
VSSMODE.Value = 1;
VSSMODE.DataType = 'int32';
VSSMODE.CoderInfo.StorageClass = 'Custom';
VSSMODE.CoderInfo.CustomStorageClass = 'ImportedDefine';
VSSMODE.CoderInfo.CustomAttributes.HeaderFile = 'rtwdemo_importedmacros.h';

使用不同变体对模型进行仿真

由于您将 VSSMODE 的值设置为 1,模型在仿真期间使用非线性控制器。

sim('rtwdemo_preprocessor')
youtnl = yout;

如果将 VSSMODE 的值更改为 0,则模型在仿真期间使用线性控制器。

VSSMODE.Value = int32(0);
sim('rtwdemo_preprocessor')
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 Code 选项卡中选择 Build

要激活预处理器条件句的代码生成,请检查是否符合以下条件:

  • 在 Configuration Parameters 对话框中的 Code Generation > System target file 中选择 Embedded Coder® 目标

  • 在 Variant Subsystem 模块参数对话框中,选择 Analyze all choices during update diagram and generate preprocessor conditionals 的选项。

在此示例中,生成的代码包括对 Simulink.Variant 对象 LINEARNONLINEAR 的引用,以及对应于那些变体的宏的定义。这些定义依赖于 VSSMODE 的值,该值在外部头文件 rtwdemo_importedmacros.h 中提供。通过对宏 (#define) LINEARNONLINEAR 使用预处理器条件句 (#if) 可确定激活变体。

rtwdemo_preprocessor_types.h 头文件中定义宏 LINEARNONLINEAR

  |#ifndef LINEAR|
  |#define LINEAR      (VSSMODE == 0)|
  |#endif|
  |#ifndef NONLINEAR|
  |#define NONLINEAR   (VSSMODE == 1)|
  |#endif|

在生成的代码中,与变体相关的代码带有 C 预处理器条件句。例如,在 rtwdemo_preprocessor.c 中,会根据条件来编译对每个变体的单步函数和初始化函数的调用:

关闭示例中的模型、图和工作区变量。

bdclose('rtwdemo_preprocessor')
close(findobj(0,'Tag','CloseMe'));
clear LINEAR NONLINEAR VSSMODE
clear tout yout youtl youtnl