www.gusucode.com > ecoder 案例源码程序 matlab代码 > ecoder/ConfigGenCodeAccordingToICDExample.m
%% Configure Generated Code According to Interface Control Document % Import specifications from an interface control % document (ICD), configure code generation settings for a model according % to the specifications, and store the settings in data dictionaries. % % An ICD describes the data interface between two software components. To % exchange and share data, the components declare and define global % variables that store signal and parameter values. The ICD names the % variables and lists characteristics such as data type, physical units, % and parameter values. When you create models of the components in % Simulink, you can configure the generated code to conform to the % interface specification. % % In this example, the ICD is a Microsoft(R) Excel(R) workbook. %% Explore Interface Control Document % Navigate to the folder % |_matlabroot_/examples/ecoder| % (<matlab:cd(fullfile(matlabroot,'examples','ecoder')) open>). Copy these % files to a writable, working folder: % % * |ICD.xls| % * |importICD.m| % % In Microsoft(R) Excel(R) or another compatible program, open the |ICD.xls| workbook % and view the first worksheet, |Signals|. Each row of the worksheet % describes a signal that crosses the interface boundary. % % Inspect the cell values in the worksheet. The |Owner| column indicates % the name of the component that allocates memory for each signal. The % |DataType| column indicates the signal data type in memory. For example, % the worksheet uses the expression |Bus: EngSensors| to represent a % structure type named |EngSensors|. % % In the |Parameters| worksheet, the |Value| column indicates the value % of each parameter. If the value of the parameter is nonscalar, the value % is stored in its own separate worksheet, which has the same name as the % parameter. % % In the |Numeric Types| worksheet, each row represents a named numeric % data type. In this ICD, the data use fixed-point data types (Fixed-Point % Designer). The |IsAlias| column indicates whether the C code uses % the name of the data type (for example, |u8En7|) or uses the name of the % primitive integer data type that corresponds to the word length. The % |DataScope| column indicates whether the generated code exports or % imports the definition of the type. % % In the |Structure Types| worksheet, each row represents either a % structure type or a field of a structure type. For structure types, the % value in the |DataType| column is |struct|. Subsequent rows that do not % use |struct| represent fields of the preceding structure type. This ICD % defines a structure type, |EngSensors|, with four fields: |throttle|, % |speed|, |ego|, and |map|. % % In the |Enumerated Types| worksheet, similar to the |Structure Types| % worksheet, each row represents either an enumerated type or an % enumeration member. This ICD defines an enumerated type % |sldemo_FuelModes|. %% Write Custom Code % Some data items in the ICD belong to |other component|, which is a % component that exists outside of MATLAB. Create the custom code files % that define and declare this external data. % % Create the custom source file |inter_sigs.c| in your current folder. This % file defines the imported signal |sensors|. % % <include>inter_sigs.c</include> % % Create the custom header file |inter_sigs.h| in your current folder. % % <include>inter_sigs.h</include> % % Create the custom header file |inter_types.h| in your current folder. % This file defines the structure type |EngSensors| and numeric data types % such as |u8En7|. % % <include>inter_types.h</include> %% Explore Example Model % Run the script <matlab:run(fullfile(matlabroot,'examples','ecoder','prepare_sldemo_fuelsys_dd')) % |prepare_sldemo_fuelsys_dd|>. The script prepares a system model, % |sldemo_fuelsys_dd|, for this example. % % run(fullfile(matlabroot,'examples','ecoder','prepare_sldemo_fuelsys_dd')) prepare_sldemo_fuelsys_dd %% % Open the system model, <matlab:sldemo_fuelsys_dd |sldemo_fuelsys_dd|>. % % sldemo_fuelsys_dd open_system('sldemo_fuelsys_dd') %% % This system model references a controller model. In this example, you % generate code from the controller model. % % Open the controller model, <matlab:sldemo_fuelsys_dd_controller % sldemo_fuelsys_dd_controller>. % % sldemo_fuelsys_dd_controller open_system('sldemo_fuelsys_dd_controller') %% % Data items in the controller model refer to |Simulink.Signal| and % |Simulink.Parameter| objects in the base workspace. For example, the % input signal |sensors| refers to a |Simulink.Signal| object that has the % same name. These objects store settings such as data types, block % parameter values, and physical units. The names of these data items and % objects match the names of the signals and parameters in the ICD. %% Import ICD Specifications into Simulink % To configure code generation settings for the data items, import % the settings from the ICD. % % Open the example script % <matlab:edit('importICD') % |importICD|>. The script imports the data from each worksheet of the ICD % into variables in the base workspace. It then configures the properties % of the |Simulink.Signal| and |Simulink.Parameter| objects in the base % workspace by using the imported data. % % edit('importICD') % % If the base workspace already contains a data object that corresponds to % a target data item in the ICD, the script configures the properties of % the existing object. If the object does not exist, the script creates the % object. % % Run the |importICD| <matlab:run('importICD') script>. % % run('importICD') % % The script configures the data objects in the base workspace for code % generation according to the specifications in the ICD. The |Simulink.Bus| % object |EngSensors| represents the structure type from the ICD. The % |Simulink.NumericType| objects, such as |u8En7|, represent the % fixed-point data types. importICD %% Generate and Inspect Code % Configure the controller model to compile the generated code into an % executable by clearing the model configuration parameter *Generate code % only*. set_param('sldemo_fuelsys_dd_controller','GenCodeOnly','off') %% % Generate code from the controller model. rtwbuild('sldemo_fuelsys_dd_controller') %% % The generated header file |sldemo_FuelModes.h| defines the enumeration % |sldemo_FuelModes|. file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'sldemo_FuelModes.h'); rtwdemodbtype(file,'typedef enum {','} sldemo_FuelModes;',1,1) %% % The file |sldemo_fuelsys_dd_controller_types.h| includes (|#include|) the % custom header file |inter_types.h|, which defines data types such as % |u8En7| and the structure type |EngSensors|. file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'sldemo_fuelsys_dd_controller_types.h'); rtwdemodbtype(file,'#include "inter_types.h"','#include "inter_types.h"',1,1) %% % The file |sldemo_fuelsys_dd_controller_private.h| includes the custom % header file |inter_sigs.h|. This custom header file contains the |extern| % declaration of the signal |sensors|, which a different software component % owns. % % The data header file |global_data.h| declares the exported parameters and % signals that the ICD specifies. To share this data, other components can % include this header file. file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw','global_data.h'); rtwdemodbtype(file,'/* Exported data declaration */',... '/* Fuel rate setpoint. */',1,1) %% % The data definitions (memory allocation) appear in the source files that % the ICD specifies, |params.c| and |signals.c|. For example, |params.c| defines and % initializes the parameter |RampRateKiZ|. file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw','params.c'); rtwdemodbtype(file,'s16En15 RampRateKiZ[25]',... '/* Lookup table to determine throttle rate. */',1,1) %% % The algorithm is in the model |step| function in the file % |sldemo_fuelsys_dd_controller.c|. The algorithm uses the global data that % the ICD identifies. For example, the algorithm uses the value of the % signal |fuel_mode| in a |switch| block to control the flow of execution. file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'sldemo_fuelsys_dd_controller.c'); rtwdemodbtype(file,'/* SwitchCase: ''<S10>/Switch Case'' incorporates:',... '/* Sum: ''<S12>/Sum3'' incorporates:',1,0) %% Change Ownership of Data in ICD % When you make changes to the ICD, you can reuse the |importICD| script % to reconfigure the model. Change the ownership of the signal % |sensors|, the structure type, and the fixed-point data types from % |other_component| to |sldemo_fuelsys_dd_controller|. % % In the ICD, on the |signals| worksheet, for the signal |sensors|, set % these cell values: % % * |Owner| to |sldemo_fuelsys_dd_controller| % * |HeaderFile| to |global_data.h| % * |DefinitionFile| to |signals.c| % % On the |Numeric Types| worksheet, for all of the fixed-point data types, % set: % % * |DataScope| to |Exported| % * |HeaderFile| to |exported_types.h|. % % On the |Structure Types| worksheet, for the structure type |EngSensors|, % set: % % * |DataScope| to |Exported| % * |HeaderFile| to |exported_types.h|. % % Rerun the |importICD| script. [~, ~, sigsRaw] = xlsread(xlsFileName,'Signals',''); [~, ~, numTypesRaw] = xlsread(xlsFileName,'Numeric Types',''); [~, ~, structTypesRaw] = xlsread(xlsFileName,'Structure Types',''); sigsBackup = sigsRaw; numTypesBackup = numTypesRaw; structTypesBackup = structTypesRaw; sigsRaw{2,5} = 'sldemo_fuelsys_dd_controller'; sigsRaw{2,6} = 'global_data.h'; sigsRaw{2,7} = 'signals.c'; for i = 2:5 numTypesRaw{i,2} = 'Exported'; numTypesRaw{i,3} = 'exported_types.h'; end structTypesRaw{2,3} = 'Exported'; structTypesRaw{2,4} = 'exported_types.h'; xlswrite(xlsFileName,sigsRaw,'Signals'); xlswrite(xlsFileName,numTypesRaw,'Numeric Types'); xlswrite(xlsFileName,structTypesRaw,'Structure Types'); importICD; %% % Generate code from the model. rtwbuild('sldemo_fuelsys_dd_controller') %% % The generated file |exported_types.h| defines the structure type % |EngSensors| and the fixed-point data types. file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'exported_types.h'); rtwdemodbtype(file,'typedef int16_T s16En3;','#endif',1,0) %% % The file |signals.c| now includes the definition of the signal |sensors|. file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'signals.c'); rtwdemodbtype(file,'/* Exported data definition */','EngSensors sensors;',1,1) % This extra code is here to prevent Example Manager from uploading the % edited ICD.xls. xlswrite(xlsFileName,sigsBackup,'Signals'); xlswrite(xlsFileName,numTypesBackup,'Numeric Types'); xlswrite(xlsFileName,structTypesBackup,'Structure Types'); %% Migrate Base Workspace Data to Data Dictionary % Objects and variables that you create in the base workspace (for example, % |Simulink.Parameter| objects) are not saved with the model. When you end % your MATLAB session, the objects and variables do not persist. To % permanently store the objects and variables, link one or more models to % one or more data dictionaries. % % Data dictionaries also enable you to track changes made to the objects and % variables, which helps you to: % % * Reconcile the data stored in MATLAB with the data stored in the ICD. % * Export data from MATLAB to the ICD. % % # In the top model, |sldemo_fuelsys_dd|, select *File > Model Properties % > Link to Data Dictionary*. % # In the Model Properties dialog box, select *Data Dictionary*. Click % *New*. % # In the Create a new Data Dictionary dialog box, set *File name* to % |sysDict| and click *Save*. % # In the Model Properties dialog box, click *OK*. % # Click *Yes* in response to the message about migrating base workspace % data. % # Click *Yes* in response to the message about removing the imported % items from the base workspace. % # Click *OK* in response to the message about enumerated type migration. % % The variables and objects that the models use all exist in the new data % dictionary |sysDict.sldd|, which is in your current folder. All three % models in the model reference hierarchy are linked to this dictionary. usedVars = {Simulink.findVars('sldemo_fuelsys_dd',... 'SourceType','base workspace','SearchReferencedModels','on').Name}; sysDictObj = Simulink.data.dictionary.create('sysDict.sldd'); modelNames = find_mdlrefs('sldemo_fuelsys_dd'); for i = 1:length(modelNames) set_param(modelNames{i},'DataDictionary','sysDict.sldd') end importFromBaseWorkspace(sysDictObj,'clearWorkspaceVars',true,'varList',usedVars); %% Create Reference Dictionary % To establish clear ownership of the data that you store in a dictionary, % create reference dictionaries. % % # Open the controller model, |sldemo_fuelsys_dd_controller|. Select *File % > Model Properties > Link to Data Dictionary*. Click *New*. % # Set the name of the new dictionary to |ctrlDict.sldd| and click *Save*. % In the Model Properties dialog box, click *OK*. % # In response to the message about changing the dictionary or moving the % data, click *Move Data*. Click *Yes* in response to the message about % migrating data. % % The variables and objects that the controller model uses now exist in the % referenced dictionary |ctrlDict.sldd|. Because |sysDict.sldd| references % |ctrlDict.sldd|, you can view all of the data by opening |sysDict.sldd| % in the Model Explorer. % % Now that the model data acquire code generation settings from objects and % variables that are stored in data dictionaries, you can modify the % |importICD| script so it % accesses the dictionaries instead of the base workspace. % For more information about the programmatic interface for data % dictionaries, see <docid:simulink_ug.bunkch6-1>. ctrlDictObj = Simulink.data.dictionary.create('ctrlDict.sldd'); addDataSource(sysDictObj,'ctrlDict.sldd'); dDataSectObj = getSection(sysDictObj,'Design Data'); usedVars = {Simulink.findVars('sldemo_fuelsys_dd_controller',... 'SourceType','data dictionary').Name}; for i = 1:length(usedVars) entry = getEntry(dDataSectObj,usedVars{i}); entry.DataSource = 'ctrlDict.sldd'; end set_param('sldemo_fuelsys_dd_controller','DataDictionary','ctrlDict.sldd') saveChanges(ctrlDictObj) %% Store Enumerated Type Definition in Data Dictionary % You can import the definition of the enumerated type |sldemo_FuelModes| % into the controller dictionary. See <docid:simulink_ug.bukuj7i>. %% Store Signal and State Design Attributes Inside or Outside of Model File % In this example, you use |Simulink.Signal| objects to specify design % attributes such as data types, minimum and maximum values, and physical % units. The signal objects store these specifications outside of the model % file. % % Alternatively, you can store these specifications in the model file % by using block and port parameters, which you can access through the % Model Data Editor, the Property Inspector, and other dialog boxes. % % To % decide where to store the specifications, see % <docid:simulink_ug.bvcdbmy>.