www.gusucode.com > ecoder 案例源码程序 matlab代码 > ecoder/VariantModelBlocksControlledByCPreprocessorConditionalsExample.m

    %% Use Model Variants to Generate Code That Uses C Preprocessor Conditionals
% This example shows you how to use model variants to generate code that 
% uses preprocessor conditionals to control which code is linked into 
% the embedded executable.

% Copyright 2014 The MathWorks, Inc.

%% Overview of Model Variants
% You can use a model block to reference one Simulink(R) model (the _child model_)
% from another Simulink(R) model (the _parent model_). A model block can also
% have different _variants_ when the user uses to reference a set of potential
% child models from the model block. The variants comprise a set of models
% that the model block can potentially reference. The figure 
% below is a conceptual depiction of model variants. 
% For example, in this example the 
% |Right Controller| model block can potentially reference two models.
% Those models provide variations upon a nominal, prescribed functionality.
%
% <<../rtwdemo_preprocessor_variants.jpg>>
%
% For a given model block, only one variant can be active. 
% You can use the model block dialog to choose which variant is active.
% However, you can also choose to parameterize the choice of the active variant, and make it dependent on the
% values of variables and objects in the base MATLAB(R) workspace.
% When you generate code, you can generate code for the
% variants, and defer the choice of active variant until it is time to compile
% that code.

%% Specifying Variants for a Model Block
% Use the |rtwdemo_preprocessor| model to see how to construct a
% parent model that generates code for the model variants. 
% Preprocessor conditionals guard the 
% code for the variants. Macros define and activate the variants when
% the code is compiled.
%
% Open the model:
open_system('rtwdemo_preprocessor')

%%
% Right-click the |Left Controller| model block and select
% *ModelReference Parameters...* to open the model reference dialog.
%
% <<../rtwdemo_preprocessor_dialog.jpg>>
%
% The dialog specifies two potential variants. The two variants are in turn
% associated with two distinct Simulink.Variant objects |LINEAR| and |NONLINEAR|, 
% which exist in the base workspace. These objects have a property named 
% |Condition|, an expression that evaluates to a Boolean and that determines 
% which variant is active. The condition is also shown in the model reference 
% dialog. In this example, the conditions of |LINEAR| and |NONLINEAR| are
% 'VSSMODE == 0' and 'VSSMODE == 1', respectively. 
%
% The |Simulink.Variant| objects of this example have been created in the
% base workspace.
LINEAR = Simulink.Variant;
LINEAR.Condition = 'VSSMODE==0';
NONLINEAR = Simulink.Variant;
NONLINEAR.Condition = 'VSSMODE==1';

%%
% Variant objects allow you to reuse arbitrarily complex conditions 
% throughout a model. Multiple model blocks can use the same variant
% objects, allowing you to toggle their child model
% references as a set. The set can be toggled at simulation time by 
% changing the value of |VSSMODE| in the MATLAB(R) environment or when compiling the
% generated code, as explained in the next section. 
% In this example, |Left Controller|
% and |Right Controller| reference the same variant objects, so that you
% can toggle them simultaneously.
%
% <<../rtwdemo_preprocessor_variants_big.jpg>>
%
% The nonlinear controller
% models implement hysteresis, while the linear controller models act
% as simple low-pass filters. Open the 
% models for the left channel as |rtwdemo_nlinl| and |rtwdemo_linl|. The
% models for the right channel are similar.

%%
open_system('rtwdemo_nlinl')

%%
open_system('rtwdemo_linl')

%% Specifying a Variant Control Variable
% The generated code accesses the variant control variable |VSSMODE| 
% as a user-defined macro. In this example, |rtwdemo_importedmacros.h| supplies
% |VSSMODE|. Within the MATLAB(R) environment, you specify |VSSMODE| using a 
% |Simulink.Parameter| object. Its value will be ignored 
% when generating code including preprocessor conditionals. However, 
% the value is used for simulation. The legacy header file specifies the 
% value of the macro to be used when compiling the generated code, which 
% ultimately activates one of the two specified variants in the embedded
% executable.
% Variant control variables are defined as Simulink.Parameter objects with one of these storage classes:
%
% * |Define| or |ImportedDefine| with header file specified 
% * |CompilerFlag|
% * |SystemConstant (AUTOSAR)|
% * User-defined custom storage class that defines data as a macro in a specified header file

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

%%
% <<../rtwdemo_preprocessor_MODE.png>>

%% Simulating the Model with Different Variants
% Since you set the value of |VSSMODE| to 1, the model uses the 
% nonlinear controllers during simulation.
sim('rtwdemo_preprocessor')
youtnl = yout;

%%
% If the value of |VSSMODE| is changed to 0, the model uses the 
% linear controllers during simulation. 
VSSMODE.Value = int32(0);
sim('rtwdemo_preprocessor')
youtl = yout;

%%
% You can plot and compare the response of the linear and nonlinear
% controllers:
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]);

%% Configuring the Parent Model to Generate Variants of the Model Block
% On each model block's Model Reference dialog, clear the checkbox 
% *Override variant conditions and use following variant*, and select 
% the check box *Generate preprocessor conditionals*.
%
% <<../rtwdemo_preprocessor_blk.jpg>>
%

%% Analyzing the Generated Code
% The generated code includes references to the variants |LINEAR| and
% |NONLINEAR|, as well as the definitions of macros corresponding to those 
% variants. Those definitions depend on the value of |VSSMODE|, which is 
% supplied in an external header file |rtwdemo_importedmacros.h|.
% The active variant is determined by checks on the macros |LINEAR| and 
% |NONLINEAR|. These checks also verify that exactly one variant is active
% in the embedded application.
%
% The macros |LINEAR| and |NONLINEAR| are defined in |rtwdemo_preprocessor_types.h|, 
% along with the check for exclusive activation.
%
% <<../rtwdemo_preprocessor_types_h.jpg>>
% 
% In |rtwdemo_preprocessor_types.h|, the main block states data structure
% (dwork) for the model
% conditionally compiles substructures for the variants' dworks. The
% active variant is determined by the macros |LINEAR| and |NONLINEAR|, which
% are in turn determined by the value of |VSSMODE|, as supplied in the legacy
% header file |rtwdemo_importedmacros.h|.
%
% <<../rtwdemo_preprocessor_h.jpg>>
%
% In |rtwdemo_preprocessor.c|, the calls to the variants' step and 
% initialization functions are again conditionally compiled; a portion of
% the step function is shown below.
%
% <<../rtwdemo_preprocessor_c.jpg>>
%
% The Simulink(R) Coder(TM) code report contains a section dedicated to 
% the model variants, so
% that you can easily determine which parts of the model are activated 
% conditionally upon the value of the macros in the legacy header files.
%
% <<../rtwdemo_preprocessor_report.jpg>>

%% Further Information
%
% See <matlab:helpview(fullfile(docroot,'toolbox','ecoder','helptargets.map'),'ecoder_preprocessor_conditionals') Generating Preprocessor Conditionals> in the Embedded Coder(R) documentation.

%%
% Close the model, figure and workspace variables associated with example
bdclose('rtwdemo_preprocessor')
bdclose('rtwdemo_nlinl')
bdclose('rtwdemo_linl')
close(findobj(0,'Tag','CloseMe'));
clear LINEAR NONLINEAR VSSMODE