Когда вы используете ссылку модели, чтобы повредить большую систему на компоненты, каждый компонент является отдельной моделью. Можно снова использовать компонент путем обращения к нему с несколькими блоками Model. Каждый блок Model является экземпляром компонента. Можно затем сконфигурировать параметры блоков (такие как параметр Gain блока Gain), чтобы использовать или то же значение или различное значение для каждого экземпляра компонента. Чтобы использовать различные значения, создайте и используйте аргумент модели, чтобы установить значение параметров блоков.
Когда вы генерируете код от иерархии модели, которая использует аргументы модели, аргументы появляются в коде, когда формальные параметры точки входа модели, на которую ссылаются, функционируют, такие как выход (step
функция. Сгенерированный код затем передает специфичные для экземпляра значения параметров, которые вы задаете в каждом блоке Model к соответствующим вызовам функции.
Используете ли вы или не используете аргументы модели, можно использовать классы памяти, чтобы сконфигурировать параметры блоков, чтобы появиться в сгенерированном коде как настраиваемые глобальные переменные. Можно также использовать классы памяти, чтобы сгенерировать настраиваемые значения аргументов модели, которые сгенерированный код хранит в памяти и передает вызовам функции. Можно затем изменить значения во время выполнения.
Сконфигурируйте модель, на которую ссылаются, чтобы принять данные о параметре через формальные параметры сгенерированной функции точки входа модели. Этот метод позволяет вам задать различное значение параметров для каждого экземпляра (блок Model) модели, на которую ссылаются.
Сконфигурируйте модель, на которую ссылаются, чтобы использовать аргументы модели
Откройте модель ex_arg_code_ref
. Эта модель представляет допускающий повторное использование алгоритм.
open_system('ex_arg_code_ref')
На вкладке Modeling нажмите Model Data Editor.
В редакторе Данных модели, в таблице данных, используют столбец Типа данных, чтобы установить тип данных Inport блока к single
. Из-за наследования типа данных, другие сигналы в модели используют совпадающий тип данных.
Выберите вкладку Parameters.
В модели выберите блок Gain.
В Model Data Editor используйте Столбец значений, чтобы установить значение параметра Усиления к gainArg
.
Рядом с gainArg
, кликните по кнопке действий (3 вертикальных точки) и выберите Create.
В диалоговом окне Create New Data, установленном Значении к Simulink.Parameter
и местоположение к Model Workspace
. Нажмите Create.
В диалоговом окне свойства, установленном Значении к номеру, например, 3.17
. Нажать ОК.
Используйте Model Data Editor, чтобы установить параметр Числителя при помощи Simulink.Parameter
возразите названному coeffArg
чьим значением является 1.05
. Как с gainArg
, сохраните объект параметра в рабочем пространстве модели.
В Model Data Editor нажмите кнопку дополнительной информации Show/refresh.
Используйте поле содержимого Фильтра, чтобы найти каждый объект параметра (gainArg
и coeffArg
). Для каждого объекта установите флажок в столбце Аргумента.
Сохраните ex_arg_code_ref
модель.
В качестве альтернативы в командной строке, можно использовать эти команды, чтобы сконфигурировать блоки и объекты параметра:
set_param('ex_arg_code_ref/In1','OutDataTypeStr','single') set_param('ex_arg_code_ref/Gain','Gain','gainArg') modelWorkspace = get_param('ex_arg_code_ref','ModelWorkspace'); assignin(modelWorkspace,'gainArg',Simulink.Parameter(3.17)); set_param('ex_arg_code_ref/Discrete Filter','Numerator','coeffArg') assignin(modelWorkspace,'coeffArg',Simulink.Parameter(1.05)); set_param('ex_arg_code_ref','ParameterArgumentNames','coeffArg,gainArg') save_system('ex_arg_code_ref')
Задайте специфичные для экземпляра значения параметров в блоках Model
Откройте модель ex_arg_code
. Эта модель использует несколько экземпляров (блоки Model) допускающего повторное использование алгоритма.
open_system('ex_arg_code')
В модели откройте вкладку Model Data Editor Parameters (Моделирующий> Model Data Editor). Model Data Editor показывает четыре строки, которые соответствуют аргументам модели, coeffArg
и gainArg
, то, что можно задать для этих двух блоков Model.
Используйте Model Data Editor, чтобы установить значения для аргументов модели в Model
. Например, используйте значения на рисунке. Для Model1
, не задавайте значение для аргументов модели. По умолчанию аргумент модели использует последнее значение, заданное ниже его в иерархии модели (обозначенный значением from below
).
В качестве альтернативы в командной строке, можно использовать эту команду, чтобы установить значения для Model
:
instSpecParams = get_param('ex_arg_code/Model','InstanceParameters'); instSpecParams(1).Value = '.98'; instSpecParams(2).Value = '2.98'; set_param('ex_arg_code/Model','InstanceParameters',instSpecParams);
Сгенерируйте код от топ-модели.
slbuild('ex_arg_code')
### Starting serial model reference code generation build ### Successfully updated the model reference code generation target for: ex_arg_code_ref ### Starting build procedure for: ex_arg_code ### Successful completion of build procedure for: ex_arg_code Build Summary Code generation targets built: Model Action Rebuild Reason ================================================================================= ex_arg_code_ref Code generated and compiled ex_arg_code_ref.c does not exist. Top model targets built: Model Action Rebuild Reason ============================================================================================ ex_arg_code Code generated and compiled Code generation information file does not exist. 2 of 2 models built (0 models already up to date) Build duration: 0h 0m 39.958s
Файл ex_arg_code_ref.c
задает функцию точки входа модели, на которую ссылаются, ex_arg_code_ref
. Функция имеет два формальных параметра, rtp_coeffArg
и rtp_gainArg
, это соответствует аргументам модели, coeffArg
и gainArg
. Формальные параметры используют тип данных real32_T
, который соответствует типу данных single
в Simulink.
file = fullfile('slprj','grt','ex_arg_code_ref','ex_arg_code_ref.c'); rtwdemodbtype(file,'/* Output and update for referenced model:',... 'real32_T rtp_gainArg)',1,1)
/* Output and update for referenced model: 'ex_arg_code_ref' */ void ex_arg_code_ref(const real32_T *rtu_In1, real32_T *rty_Out1, real32_T rtp_coeffArg, real32_T rtp_gainArg, DW_ex_arg_code_ref_f_T * localDW) { real32_T rtb_Sum; /* Sum: '<Root>/Sum' incorporates: * UnitDelay: '<Root>/Unit Delay' */ rtb_Sum = *rtu_In1 + localDW->UnitDelay_DSTATE; /* Gain: '<Root>/Gain' */ rtb_Sum *= rtp_gainArg; /* DiscreteFilter: '<Root>/Discrete Filter' */ localDW->DiscreteFilter_tmp = rtb_Sum - 0.5F * localDW->DiscreteFilter_states; *rty_Out1 = rtp_coeffArg * localDW->DiscreteFilter_tmp; /* Update for UnitDelay: '<Root>/Unit Delay' */ localDW->UnitDelay_DSTATE = rtb_Sum; /* Update for DiscreteFilter: '<Root>/Discrete Filter' */ localDW->DiscreteFilter_states = localDW->DiscreteFilter_tmp; } /* Model initialize function */ void ex_arg_code_ref_initialize(const char_T **rt_errorStatus, RT_MODEL_ex_arg_code_ref_T *const ex_arg_code_ref_M, DW_ex_arg_code_ref_f_T *localDW) { /* Registration code */ /* initialize error status */ rtmSetErrorStatusPointer(ex_arg_code_ref_M, rt_errorStatus); /* states (dwork) */ (void) memset((void *)localDW, 0, sizeof(DW_ex_arg_code_ref_f_T)); }
Файл ex_arg_code.c
содержит определение функции точки входа топ-модели, ex_arg_code
. Это вызовы функции функция точки входа модели, на которую ссылаются, ex_arg_code_ref
, и использует значения аргументов модели, которые вы задали (такие как 1.11
и 3.34
) как значения rtp_coeffArg
и rtp_gainArg
.
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code.c'); rtwdemodbtype(file,'/* ModelReference: ''<Root>/Model'' incorporates:',... '1.05F, 3.17F)',1,1)
/* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out1' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out1, 0.98F, 2.98F, &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* ModelReference: '<Root>/Model1' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out2' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out2, 1.05F, 3.17F, &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_UpdateTXYLogVars(ex_arg_code_M->rtwLogInfo, (&ex_arg_code_M->Timing.taskTime0)); /* signal main to stop simulation */ { /* Sample time: [0.2s, 0.0s] */ if ((rtmGetTFinal(ex_arg_code_M)!=-1) && !((rtmGetTFinal(ex_arg_code_M)-ex_arg_code_M->Timing.taskTime0) > ex_arg_code_M->Timing.taskTime0 * (DBL_EPSILON))) { rtmSetErrorStatus(ex_arg_code_M, "Simulation finished"); } } /* Update absolute time for base rate */ /* The "clockTick0" counts the number of times the code of this task has * been executed. The absolute time is the multiplication of "clockTick0" * and "Timing.stepSize0". Size of "clockTick0" ensures timer will not * overflow during the application lifespan selected. * Timer of this task consists of two 32 bit unsigned integers. * The two integers represent the low bits Timing.clockTick0 and the high bits * Timing.clockTickH0. When the low bit overflows to 0, the high bits increment. */ if (!(++ex_arg_code_M->Timing.clockTick0)) { ++ex_arg_code_M->Timing.clockTickH0; } ex_arg_code_M->Timing.taskTime0 = ex_arg_code_M->Timing.clockTick0 * ex_arg_code_M->Timing.stepSize0 + ex_arg_code_M->Timing.clockTickH0 * ex_arg_code_M->Timing.stepSize0 * 4294967296.0; } /* Model initialize function */ void ex_arg_code_initialize(void) { /* Registration code */ /* initialize non-finites */ rt_InitInfAndNaN(sizeof(real_T)); /* initialize real-time model */ (void) memset((void *)ex_arg_code_M, 0, sizeof(RT_MODEL_ex_arg_code_T)); rtmSetTFinal(ex_arg_code_M, 10.0); ex_arg_code_M->Timing.stepSize0 = 0.2; /* Setup for data logging */ { static RTWLogInfo rt_DataLoggingInfo; rt_DataLoggingInfo.loggingInterval = (NULL); ex_arg_code_M->rtwLogInfo = &rt_DataLoggingInfo; } /* Setup for data logging */ { rtliSetLogXSignalInfo(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogXSignalPtrs(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogT(ex_arg_code_M->rtwLogInfo, "tout"); rtliSetLogX(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogXFinal(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogVarNameModifier(ex_arg_code_M->rtwLogInfo, "rt_"); rtliSetLogFormat(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogMaxRows(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogDecimation(ex_arg_code_M->rtwLogInfo, 1); /* * Set pointers to the data and signal info for each output */ { static void * rt_LoggedOutputSignalPtrs[] = { &ex_arg_code_Y.Out1, &ex_arg_code_Y.Out2 }; rtliSetLogYSignalPtrs(ex_arg_code_M->rtwLogInfo, ((LogSignalPtrsType) rt_LoggedOutputSignalPtrs)); } { static int_T rt_LoggedOutputWidths[] = { 1, 1 }; static int_T rt_LoggedOutputNumDimensions[] = { 1, 1 }; static int_T rt_LoggedOutputDimensions[] = { 1, 1 }; static boolean_T rt_LoggedOutputIsVarDims[] = { 0, 0 }; static void* rt_LoggedCurrentSignalDimensions[] = { (NULL), (NULL) }; static int_T rt_LoggedCurrentSignalDimensionsSize[] = { 4, 4 }; static BuiltInDTypeId rt_LoggedOutputDataTypeIds[] = { SS_SINGLE, SS_SINGLE }; static int_T rt_LoggedOutputComplexSignals[] = { 0, 0 }; static RTWPreprocessingFcnPtr rt_LoggingPreprocessingFcnPtrs[] = { (NULL), (NULL) }; static const char_T *rt_LoggedOutputLabels[] = { "", "" }; static const char_T *rt_LoggedOutputBlockNames[] = { "ex_arg_code/Out1", "ex_arg_code/Out2" }; static RTWLogDataTypeConvert rt_RTWLogDataTypeConvert[] = { { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 }, { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 } }; static RTWLogSignalInfo rt_LoggedOutputSignalInfo[] = { { 2, rt_LoggedOutputWidths, rt_LoggedOutputNumDimensions, rt_LoggedOutputDimensions, rt_LoggedOutputIsVarDims, rt_LoggedCurrentSignalDimensions, rt_LoggedCurrentSignalDimensionsSize, rt_LoggedOutputDataTypeIds, rt_LoggedOutputComplexSignals, (NULL), rt_LoggingPreprocessingFcnPtrs, { rt_LoggedOutputLabels }, (NULL), (NULL), (NULL), { rt_LoggedOutputBlockNames }, { (NULL) }, (NULL), rt_RTWLogDataTypeConvert } }; rtliSetLogYSignalInfo(ex_arg_code_M->rtwLogInfo, rt_LoggedOutputSignalInfo); /* set currSigDims field */ rt_LoggedCurrentSignalDimensions[0] = &rt_LoggedOutputWidths[0]; rt_LoggedCurrentSignalDimensions[1] = &rt_LoggedOutputWidths[1]; } rtliSetLogY(ex_arg_code_M->rtwLogInfo, "yout"); } /* states (dwork) */ (void) memset((void *)&ex_arg_code_DW, 0, sizeof(DW_ex_arg_code_T)); /* external inputs */ ex_arg_code_U.In1 = 0.0F; /* external outputs */ (void)memset(&ex_arg_code_Y, 0, sizeof(ExtY_ex_arg_code_T)); /* Model Initialize function for ModelReference Block: '<Root>/Model' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model_InstanceData.rtm), &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* Model Initialize function for ModelReference Block: '<Root>/Model1' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model1_InstanceData.rtm), &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_StartDataLoggingWithStartTime(ex_arg_code_M->rtwLogInfo, 0.0, rtmGetTFinal (ex_arg_code_M), ex_arg_code_M->Timing.stepSize0, (&rtmGetErrorStatus (ex_arg_code_M))); /* SystemInitialize for ModelReference: '<Root>/Model' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model_InstanceData.rtdw)); /* SystemInitialize for ModelReference: '<Root>/Model1' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model1_InstanceData.rtdw)); } /* Model terminate function */ void ex_arg_code_terminate(void) { /* (no terminate code required) */ }
Формальные параметры используют тип данных real32_T
единственный
) потому что:
Параметры блоков в ex_arg_code_ref
определите их типы данных через внутренние правила. Например, в диалоговом окне блока Усиления, на вкладке Parameter Attributes, Тип данных параметров установлен в Inherit: Inherit via internal rule
(значение по умолчанию). В этом случае внутреннее правило выбирает совпадающий тип данных в качестве сигналов ввода и вывода, single
.
Аргументы модели в рабочем пространстве модели используют контекстно-зависимый ввод данных потому что значение DataType
свойство установлено в auto
(значение по умолчанию). С этой установкой аргументы модели используют совпадающий тип данных в качестве параметров блоков, single
.
Формальные параметры в сгенерированном коде используют совпадающий тип данных в качестве аргументов модели, single
.
Сгенерируйте настраиваемые значения аргументов
Можно сконфигурировать специфичные для экземпляра значения в блоках Model, чтобы появиться в сгенерированном коде как настраиваемые глобальные переменные. Этот метод позволяет вам сохранить значения параметров для каждого экземпляра в памяти и настроить значения во время выполнения кода.
В топ-модели ex_arg_code
, выберите вкладку Model Data Editor Parameters.
Используйте Model Data Editor, чтобы установить значения аргументов модели согласно этому рисунку.
Просмотрите содержимое ex_arg_code_ref
рабочее пространство модели в Model Explorer.
Скопируйте gainArg
и coeffArg
от ex_arg_code_ref
рабочее пространство модели к базовому рабочему пространству.
Переименуйте gainArg
как gainForInst1
. Переименуйте coeffArg
как coeffForInst1
.
gainForInst1 = getVariable(modelWorkspace,'gainArg'); gainForInst1 = copy(gainForInst1); coeffForInst1 = getVariable(modelWorkspace,'coeffArg'); coeffForInst1 = copy(coeffForInst1);
Скопируйте gainForInst1
и coeffForInst1
как gainForInst2
и coeffForInst2
.
gainForInst2 = copy(gainForInst1); coeffForInst2 = copy(coeffForInst1);
Установите специфичные для экземпляра значения параметров при помощи Value
свойство объектов параметра в базовом рабочем пространстве.
gainForInst1.Value = 2.98; coeffForInst1.Value = 0.98; gainForInst2.Value = 3.34; coeffForInst2.Value = 1.11;
Для каждого нового объекта параметра, на вкладке Code Generation, устанавливает StorageClass
к ExportedGlobal
. Эта установка заставляет объекты параметра появляться в сгенерированном коде как настраиваемые глобальные переменные.
gainForInst1.StorageClass = 'ExportedGlobal'; coeffForInst1.StorageClass = 'ExportedGlobal'; gainForInst2.StorageClass = 'ExportedGlobal'; coeffForInst2.StorageClass = 'ExportedGlobal'; instSpecParams = get_param('ex_arg_code/Model','InstanceParameters'); instSpecParams(1).Value = 'coeffForInst1'; instSpecParams(2).Value = 'gainForInst1'; instSpecParams1 = get_param('ex_arg_code/Model1','InstanceParameters'); instSpecParams1(1).Value = 'coeffForInst2'; instSpecParams1(2).Value = 'gainForInst2'; set_param('ex_arg_code/Model','InstanceParameters',instSpecParams); set_param('ex_arg_code/Model1','InstanceParameters',instSpecParams1);
Сгенерируйте код от топ-модели.
slbuild('ex_arg_code')
### Starting serial model reference code generation build ### Model reference code generation target for ex_arg_code_ref is up to date. ### Starting build procedure for: ex_arg_code ### Successful completion of build procedure for: ex_arg_code Build Summary Top model targets built: Model Action Rebuild Reason =========================================================================== ex_arg_code Code generated and compiled Generated code was out of date. 1 of 2 models built (1 models already up to date) Build duration: 0h 0m 12.501s
Файл ex_arg_code.c
задает глобальные переменные, которые соответствуют объектам параметра в базовом рабочем пространстве.
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code.c'); rtwdemodbtype(file,'/* Exported block parameters */',... '/* Block states (default storage) */',1,0)
/* Exported block parameters */ real32_T coeffForInst1 = 0.98F; /* Variable: coeffForInst1 * Referenced by: '<Root>/Model' */ real32_T coeffForInst2 = 1.11F; /* Variable: coeffForInst2 * Referenced by: '<Root>/Model1' */ real32_T gainForInst1 = 2.98F; /* Variable: gainForInst1 * Referenced by: '<Root>/Model' */ real32_T gainForInst2 = 3.34F; /* Variable: gainForInst2 * Referenced by: '<Root>/Model1' */
В каждом вызове ex_arg_code_ref
, алгоритм топ-модели использует глобальные переменные, чтобы установить значения формальных параметров.
rtwdemodbtype(file,'/* ModelReference: ''<Root>/Model'' incorporates:',... 'gainForInst2);',1,1)
/* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out1' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out1, coeffForInst1, gainForInst1, &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* ModelReference: '<Root>/Model1' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out2' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out2, coeffForInst2, gainForInst2, &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_UpdateTXYLogVars(ex_arg_code_M->rtwLogInfo, (&ex_arg_code_M->Timing.taskTime0)); /* signal main to stop simulation */ { /* Sample time: [0.2s, 0.0s] */ if ((rtmGetTFinal(ex_arg_code_M)!=-1) && !((rtmGetTFinal(ex_arg_code_M)-ex_arg_code_M->Timing.taskTime0) > ex_arg_code_M->Timing.taskTime0 * (DBL_EPSILON))) { rtmSetErrorStatus(ex_arg_code_M, "Simulation finished"); } } /* Update absolute time for base rate */ /* The "clockTick0" counts the number of times the code of this task has * been executed. The absolute time is the multiplication of "clockTick0" * and "Timing.stepSize0". Size of "clockTick0" ensures timer will not * overflow during the application lifespan selected. * Timer of this task consists of two 32 bit unsigned integers. * The two integers represent the low bits Timing.clockTick0 and the high bits * Timing.clockTickH0. When the low bit overflows to 0, the high bits increment. */ if (!(++ex_arg_code_M->Timing.clockTick0)) { ++ex_arg_code_M->Timing.clockTickH0; } ex_arg_code_M->Timing.taskTime0 = ex_arg_code_M->Timing.clockTick0 * ex_arg_code_M->Timing.stepSize0 + ex_arg_code_M->Timing.clockTickH0 * ex_arg_code_M->Timing.stepSize0 * 4294967296.0; } /* Model initialize function */ void ex_arg_code_initialize(void) { /* Registration code */ /* initialize non-finites */ rt_InitInfAndNaN(sizeof(real_T)); /* initialize real-time model */ (void) memset((void *)ex_arg_code_M, 0, sizeof(RT_MODEL_ex_arg_code_T)); rtmSetTFinal(ex_arg_code_M, 10.0); ex_arg_code_M->Timing.stepSize0 = 0.2; /* Setup for data logging */ { static RTWLogInfo rt_DataLoggingInfo; rt_DataLoggingInfo.loggingInterval = (NULL); ex_arg_code_M->rtwLogInfo = &rt_DataLoggingInfo; } /* Setup for data logging */ { rtliSetLogXSignalInfo(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogXSignalPtrs(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogT(ex_arg_code_M->rtwLogInfo, "tout"); rtliSetLogX(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogXFinal(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogVarNameModifier(ex_arg_code_M->rtwLogInfo, "rt_"); rtliSetLogFormat(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogMaxRows(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogDecimation(ex_arg_code_M->rtwLogInfo, 1); /* * Set pointers to the data and signal info for each output */ { static void * rt_LoggedOutputSignalPtrs[] = { &ex_arg_code_Y.Out1, &ex_arg_code_Y.Out2 }; rtliSetLogYSignalPtrs(ex_arg_code_M->rtwLogInfo, ((LogSignalPtrsType) rt_LoggedOutputSignalPtrs)); } { static int_T rt_LoggedOutputWidths[] = { 1, 1 }; static int_T rt_LoggedOutputNumDimensions[] = { 1, 1 }; static int_T rt_LoggedOutputDimensions[] = { 1, 1 }; static boolean_T rt_LoggedOutputIsVarDims[] = { 0, 0 }; static void* rt_LoggedCurrentSignalDimensions[] = { (NULL), (NULL) }; static int_T rt_LoggedCurrentSignalDimensionsSize[] = { 4, 4 }; static BuiltInDTypeId rt_LoggedOutputDataTypeIds[] = { SS_SINGLE, SS_SINGLE }; static int_T rt_LoggedOutputComplexSignals[] = { 0, 0 }; static RTWPreprocessingFcnPtr rt_LoggingPreprocessingFcnPtrs[] = { (NULL), (NULL) }; static const char_T *rt_LoggedOutputLabels[] = { "", "" }; static const char_T *rt_LoggedOutputBlockNames[] = { "ex_arg_code/Out1", "ex_arg_code/Out2" }; static RTWLogDataTypeConvert rt_RTWLogDataTypeConvert[] = { { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 }, { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 } }; static RTWLogSignalInfo rt_LoggedOutputSignalInfo[] = { { 2, rt_LoggedOutputWidths, rt_LoggedOutputNumDimensions, rt_LoggedOutputDimensions, rt_LoggedOutputIsVarDims, rt_LoggedCurrentSignalDimensions, rt_LoggedCurrentSignalDimensionsSize, rt_LoggedOutputDataTypeIds, rt_LoggedOutputComplexSignals, (NULL), rt_LoggingPreprocessingFcnPtrs, { rt_LoggedOutputLabels }, (NULL), (NULL), (NULL), { rt_LoggedOutputBlockNames }, { (NULL) }, (NULL), rt_RTWLogDataTypeConvert } }; rtliSetLogYSignalInfo(ex_arg_code_M->rtwLogInfo, rt_LoggedOutputSignalInfo); /* set currSigDims field */ rt_LoggedCurrentSignalDimensions[0] = &rt_LoggedOutputWidths[0]; rt_LoggedCurrentSignalDimensions[1] = &rt_LoggedOutputWidths[1]; } rtliSetLogY(ex_arg_code_M->rtwLogInfo, "yout"); } /* states (dwork) */ (void) memset((void *)&ex_arg_code_DW, 0, sizeof(DW_ex_arg_code_T)); /* external inputs */ ex_arg_code_U.In1 = 0.0F; /* external outputs */ (void)memset(&ex_arg_code_Y, 0, sizeof(ExtY_ex_arg_code_T)); /* Model Initialize function for ModelReference Block: '<Root>/Model' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model_InstanceData.rtm), &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* Model Initialize function for ModelReference Block: '<Root>/Model1' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model1_InstanceData.rtm), &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_StartDataLoggingWithStartTime(ex_arg_code_M->rtwLogInfo, 0.0, rtmGetTFinal (ex_arg_code_M), ex_arg_code_M->Timing.stepSize0, (&rtmGetErrorStatus (ex_arg_code_M))); /* SystemInitialize for ModelReference: '<Root>/Model' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model_InstanceData.rtdw)); /* SystemInitialize for ModelReference: '<Root>/Model1' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model1_InstanceData.rtdw)); } /* Model terminate function */ void ex_arg_code_terminate(void) { /* (no terminate code required) */ }
Глобальные переменные в сгенерированном коде используют тип данных real32_T
единственный
) потому что:
Объекты параметра в базовом рабочем пространстве используют контекстно-зависимый ввод данных потому что DataType
свойство установлено в auto
(значение по умолчанию). С этой установкой объекты параметра в базовом рабочем пространстве используют совпадающий тип данных в качестве аргументов модели, single
.
Глобальные переменные в сгенерированном коде используют совпадающий тип данных в качестве объектов параметра в базовом рабочем пространстве.
Аргументы многоуровневой модели группы в одну структуру
Используйте Model Explorer, чтобы скопировать gainArg
и coeffArg
от ex_arg_code_ref
рабочее пространство модели в базовое рабочее пространство.
temp = getVariable(modelWorkspace,'gainArg'); gainArg = copy(temp); temp = getVariable(modelWorkspace,'coeffArg'); coeffArg = copy(temp);
В командной строке объедините эти два объекта параметра в структуру, structArg
.
structArg = Simulink.Parameter(struct('gain',gainArg.Value,... 'coeff',coeffArg.Value));
Используйте Model Explorer, чтобы переместить structArg
в рабочее пространство модели.
assignin(modelWorkspace,'structArg',copy(structArg)); clear structArg gainArg coeffArg
В панели Содержимого сконфигурируйте structArg
в качестве единственного аргумента модели.
set_param('ex_arg_code_ref','ParameterArgumentNames','structArg')
В ex_arg_code_ref
модель, выберите вкладку Model Data Editor Parameters.
Используйте Model Data Editor, чтобы установить значение параметра Усиления к structArg.gain
и значение параметра Числителя к structArg.coeff
. Сохраните модель.
set_param('ex_arg_code_ref/Gain','Gain','structArg.gain') set_param('ex_arg_code_ref/Discrete Filter',... 'Numerator','structArg.coeff') save_system('ex_arg_code_ref')
В командной строке объедините эти четыре объекта параметра в базовом рабочем пространстве в две структуры. Каждая структура хранит значения параметров для одного экземпляра ex_arg_code_ref
.
structForInst1 = Simulink.Parameter(struct('gain',gainForInst1.Value,... 'coeff',coeffForInst1.Value)); structForInst2 = Simulink.Parameter(struct('gain',gainForInst2.Value,... 'coeff',coeffForInst2.Value));
В топ-модели ex_arg_code, используйте Model Data Editor, чтобы установить значения аргументов согласно этому рисунку.
instSpecParams = get_param('ex_arg_code/Model','InstanceParameters'); instSpecParams(1).Value = 'structForInst1'; instSpecParams1 = get_param('ex_arg_code/Model1','InstanceParameters'); instSpecParams1(1).Value = 'structForInst2'; set_param('ex_arg_code/Model','InstanceParameters',instSpecParams); set_param('ex_arg_code/Model1','InstanceParameters',instSpecParams1);
Нажмите кнопку дополнительной информации Show/refresh.
Для новых объектов параметра structForInst1
и structForInst2
, используйте Model Explorer, чтобы применить класс памяти ExportedGlobal
.
structForInst1.StorageClass = 'ExportedGlobal'; structForInst2.StorageClass = 'ExportedGlobal';
В командной строке используйте функциональный Simulink.Bus.createObject
создать Simulink.Bus
объект. Иерархия элементов в объекте совпадает с иерархией полей структуры. Именем по умолчанию объекта является slBus1
.
Simulink.Bus.createObject(structForInst1.Value);
Переименуйте объект шины как myParamStructType
путем копирования его.
myParamStructType = copy(slBus1);
В Model Data Editor для ex_arg_code
, используйте столбец Типа данных, чтобы установить тип данных structForInst1
и structForInst2
к Bus: myParamStructType
.
structForInst1.DataType = 'Bus: myParamStructType'; structForInst2.DataType = 'Bus: myParamStructType';
temp = getVariable(modelWorkspace,'structArg'); temp = copy(temp); temp.DataType = 'Bus: myParamStructType'; assignin(modelWorkspace,'structArg',copy(temp));
Сохраните ex_arg_code_ref
модель.
save_system('ex_arg_code_ref')
Когда вы используете структуры, чтобы сгруппировать значения параметров, вы не можете использовать в своих интересах контекстно-зависимый ввод данных, чтобы управлять типами данных полей структур (например, поля structForInst1
). Однако можно использовать свойства объекта шины управлять полевыми типами данных.
При команде PROMT, набор тип данных элементов в шине возражают против single
. Соответствующие поля в структурах (таких как structForInst1
и structArg
) используйте совпадающий тип данных.
myParamStructType.Elements(1).DataType = 'single'; myParamStructType.Elements(2).DataType = 'single';
Сгенерируйте код от топ-модели, ex_arg_code
.
slbuild('ex_arg_code')
### Starting serial model reference code generation build ### Successfully updated the model reference code generation target for: ex_arg_code_ref ### Starting build procedure for: ex_arg_code ### Successful completion of build procedure for: ex_arg_code Build Summary Code generation targets built: Model Action Rebuild Reason ============================================================================================= ex_arg_code_ref Code generated and compiled Model or library ex_arg_code_ref has changed. Top model targets built: Model Action Rebuild Reason =========================================================================== ex_arg_code Code generated and compiled Referenced models were updated. 2 of 2 models built (0 models already up to date) Build duration: 0h 0m 17.044s
Файл ex_arg_code_types.h
задает тип структуры myParamStructType
, который соответствует Simulink.Bus
объект.
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code_types.h'); rtwdemodbtype(file,'typedef struct {','} myParamStructType;',1,1)
typedef struct { real32_T gain; real32_T coeff; } myParamStructType;
В файле ex_arg_code_ref.c
, функция точки входа модели, на которую ссылаются, имеет формальный параметр, rtp_structArg
, это соответствует аргументу structArg
модели.
file = fullfile('slprj','grt','ex_arg_code_ref','ex_arg_code_ref.c'); rtwdemodbtype(file,'/* Output and update for referenced model:',... '*rtp_structArg)',1,1)
/* Output and update for referenced model: 'ex_arg_code_ref' */ void ex_arg_code_ref(const real32_T *rtu_In1, real32_T *rty_Out1, const myParamStructType *rtp_structArg, DW_ex_arg_code_ref_f_T *localDW) { real32_T rtb_Sum; /* Sum: '<Root>/Sum' incorporates: * UnitDelay: '<Root>/Unit Delay' */ rtb_Sum = *rtu_In1 + localDW->UnitDelay_DSTATE; /* Gain: '<Root>/Gain' */ rtb_Sum *= rtp_structArg->gain; /* DiscreteFilter: '<Root>/Discrete Filter' */ localDW->DiscreteFilter_tmp = rtb_Sum - 0.5F * localDW->DiscreteFilter_states; *rty_Out1 = rtp_structArg->coeff * localDW->DiscreteFilter_tmp; /* Update for UnitDelay: '<Root>/Unit Delay' */ localDW->UnitDelay_DSTATE = rtb_Sum; /* Update for DiscreteFilter: '<Root>/Discrete Filter' */ localDW->DiscreteFilter_states = localDW->DiscreteFilter_tmp; } /* Model initialize function */ void ex_arg_code_ref_initialize(const char_T **rt_errorStatus, RT_MODEL_ex_arg_code_ref_T *const ex_arg_code_ref_M, DW_ex_arg_code_ref_f_T *localDW) { /* Registration code */ /* initialize error status */ rtmSetErrorStatusPointer(ex_arg_code_ref_M, rt_errorStatus); /* states (dwork) */ (void) memset((void *)localDW, 0, sizeof(DW_ex_arg_code_ref_f_T)); }
Файл ex_arg_code.c
задает глобальные переменные структуры, которые соответствуют объектам параметра в базовом рабочем пространстве.
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code.c'); rtwdemodbtype(file,'/* Exported block parameters */',... '/* Block states (default storage) */',1,0)
/* Exported block parameters */ myParamStructType structForInst1 = { 2.98F, 0.98F } ; /* Variable: structForInst1 * Referenced by: '<Root>/Model' */ myParamStructType structForInst2 = { 3.34F, 1.11F } ; /* Variable: structForInst2 * Referenced by: '<Root>/Model1' */
Алгоритм топ-модели в файле ex_arg_code.c
передает адреса переменных структуры к функции точки входа модели, на которую ссылаются.
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code.c'); rtwdemodbtype(file,'/* ModelReference: ''<Root>/Model'' incorporates:',... '&structForInst2);',1,1)
/* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out1' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out1, &structForInst1, &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* ModelReference: '<Root>/Model1' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out2' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out2, &structForInst2, &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_UpdateTXYLogVars(ex_arg_code_M->rtwLogInfo, (&ex_arg_code_M->Timing.taskTime0)); /* signal main to stop simulation */ { /* Sample time: [0.2s, 0.0s] */ if ((rtmGetTFinal(ex_arg_code_M)!=-1) && !((rtmGetTFinal(ex_arg_code_M)-ex_arg_code_M->Timing.taskTime0) > ex_arg_code_M->Timing.taskTime0 * (DBL_EPSILON))) { rtmSetErrorStatus(ex_arg_code_M, "Simulation finished"); } } /* Update absolute time for base rate */ /* The "clockTick0" counts the number of times the code of this task has * been executed. The absolute time is the multiplication of "clockTick0" * and "Timing.stepSize0". Size of "clockTick0" ensures timer will not * overflow during the application lifespan selected. * Timer of this task consists of two 32 bit unsigned integers. * The two integers represent the low bits Timing.clockTick0 and the high bits * Timing.clockTickH0. When the low bit overflows to 0, the high bits increment. */ if (!(++ex_arg_code_M->Timing.clockTick0)) { ++ex_arg_code_M->Timing.clockTickH0; } ex_arg_code_M->Timing.taskTime0 = ex_arg_code_M->Timing.clockTick0 * ex_arg_code_M->Timing.stepSize0 + ex_arg_code_M->Timing.clockTickH0 * ex_arg_code_M->Timing.stepSize0 * 4294967296.0; } /* Model initialize function */ void ex_arg_code_initialize(void) { /* Registration code */ /* initialize non-finites */ rt_InitInfAndNaN(sizeof(real_T)); /* initialize real-time model */ (void) memset((void *)ex_arg_code_M, 0, sizeof(RT_MODEL_ex_arg_code_T)); rtmSetTFinal(ex_arg_code_M, 10.0); ex_arg_code_M->Timing.stepSize0 = 0.2; /* Setup for data logging */ { static RTWLogInfo rt_DataLoggingInfo; rt_DataLoggingInfo.loggingInterval = (NULL); ex_arg_code_M->rtwLogInfo = &rt_DataLoggingInfo; } /* Setup for data logging */ { rtliSetLogXSignalInfo(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogXSignalPtrs(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogT(ex_arg_code_M->rtwLogInfo, "tout"); rtliSetLogX(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogXFinal(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogVarNameModifier(ex_arg_code_M->rtwLogInfo, "rt_"); rtliSetLogFormat(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogMaxRows(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogDecimation(ex_arg_code_M->rtwLogInfo, 1); /* * Set pointers to the data and signal info for each output */ { static void * rt_LoggedOutputSignalPtrs[] = { &ex_arg_code_Y.Out1, &ex_arg_code_Y.Out2 }; rtliSetLogYSignalPtrs(ex_arg_code_M->rtwLogInfo, ((LogSignalPtrsType) rt_LoggedOutputSignalPtrs)); } { static int_T rt_LoggedOutputWidths[] = { 1, 1 }; static int_T rt_LoggedOutputNumDimensions[] = { 1, 1 }; static int_T rt_LoggedOutputDimensions[] = { 1, 1 }; static boolean_T rt_LoggedOutputIsVarDims[] = { 0, 0 }; static void* rt_LoggedCurrentSignalDimensions[] = { (NULL), (NULL) }; static int_T rt_LoggedCurrentSignalDimensionsSize[] = { 4, 4 }; static BuiltInDTypeId rt_LoggedOutputDataTypeIds[] = { SS_SINGLE, SS_SINGLE }; static int_T rt_LoggedOutputComplexSignals[] = { 0, 0 }; static RTWPreprocessingFcnPtr rt_LoggingPreprocessingFcnPtrs[] = { (NULL), (NULL) }; static const char_T *rt_LoggedOutputLabels[] = { "", "" }; static const char_T *rt_LoggedOutputBlockNames[] = { "ex_arg_code/Out1", "ex_arg_code/Out2" }; static RTWLogDataTypeConvert rt_RTWLogDataTypeConvert[] = { { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 }, { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 } }; static RTWLogSignalInfo rt_LoggedOutputSignalInfo[] = { { 2, rt_LoggedOutputWidths, rt_LoggedOutputNumDimensions, rt_LoggedOutputDimensions, rt_LoggedOutputIsVarDims, rt_LoggedCurrentSignalDimensions, rt_LoggedCurrentSignalDimensionsSize, rt_LoggedOutputDataTypeIds, rt_LoggedOutputComplexSignals, (NULL), rt_LoggingPreprocessingFcnPtrs, { rt_LoggedOutputLabels }, (NULL), (NULL), (NULL), { rt_LoggedOutputBlockNames }, { (NULL) }, (NULL), rt_RTWLogDataTypeConvert } }; rtliSetLogYSignalInfo(ex_arg_code_M->rtwLogInfo, rt_LoggedOutputSignalInfo); /* set currSigDims field */ rt_LoggedCurrentSignalDimensions[0] = &rt_LoggedOutputWidths[0]; rt_LoggedCurrentSignalDimensions[1] = &rt_LoggedOutputWidths[1]; } rtliSetLogY(ex_arg_code_M->rtwLogInfo, "yout"); } /* states (dwork) */ (void) memset((void *)&ex_arg_code_DW, 0, sizeof(DW_ex_arg_code_T)); /* external inputs */ ex_arg_code_U.In1 = 0.0F; /* external outputs */ (void)memset(&ex_arg_code_Y, 0, sizeof(ExtY_ex_arg_code_T)); /* Model Initialize function for ModelReference Block: '<Root>/Model' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model_InstanceData.rtm), &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* Model Initialize function for ModelReference Block: '<Root>/Model1' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model1_InstanceData.rtm), &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_StartDataLoggingWithStartTime(ex_arg_code_M->rtwLogInfo, 0.0, rtmGetTFinal (ex_arg_code_M), ex_arg_code_M->Timing.stepSize0, (&rtmGetErrorStatus (ex_arg_code_M))); /* SystemInitialize for ModelReference: '<Root>/Model' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model_InstanceData.rtdw)); /* SystemInitialize for ModelReference: '<Root>/Model1' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model1_InstanceData.rtdw)); } /* Model terminate function */ void ex_arg_code_terminate(void) { /* (no terminate code required) */ }
Когда вы используете аргументы модели, можно применить тип данных к:
Параметры блоков, которые используют аргументы (для определенных блоков, таких как те в библиотеке Discrete).
Аргументы в рабочем пространстве модели, на которое ссылаются.
Значения аргументов, которые вы задаете в блоках Model.
Чтобы сгенерировать эффективный код путем устранения ненужных преобразований типа и сдвигов C, рассмотрите использование наследованного и контекстно-зависимого ввода данных, чтобы совпадать с типами данных.
В рабочем пространстве модели используйте MATLAB® переменная, типом данных которой является double
или объект параметра, чей DataType
свойство установлено в auto
. В этом случае переменная или объект используют совпадающий тип данных в качестве параметров блоков.
Когда вы устанавливаете значения аргументов в блоках Model, используете в своих интересах контекстно-зависимый ввод данных. Чтобы установить значение аргумента, используйте невведенное значение.
Литеральный номер, такой как 15.23
. Не используйте введенное выражение, такое как single(15.23)
.
Переменная MATLAB, типом данных которой является double
.
Simulink.Parameter
возразите чей DataType
свойство установлено в auto
.
В этих случаях, номере, переменной или объекте использует совпадающий тип данных в качестве аргумента модели в рабочем пространстве модели, на которое ссылаются. Если вы также конфигурируете аргумент модели, чтобы использовать контекстно-зависимый ввод данных, можно управлять типами данных параметров блоков, аргумента и значения аргумента путем определения типа только для параметров блоков.
Для основной информации об управлении типами данных параметров смотрите Типы данных параметров в Сгенерированном коде.
Если вы используете аргумент модели, чтобы установить несколько значений параметров блоков, и типы данных параметров блоков отличаются, вы не можете использовать контекстно-зависимый ввод данных (double
или auto
) для аргумента в рабочем пространстве модели. Необходимо явным образом задать тип данных для аргумента. Например, если аргумент в рабочем пространстве модели является объектом параметра (таким как Simulink.Parameter
), установите DataType
свойство к значению кроме auto
. Для получения дополнительной информации об этой ситуации, смотрите Данные о Параметре Повторного использования в Контекстах Другого типа данных.
В этом случае можно продолжить использовать в своих интересах контекстно-зависимый ввод данных, чтобы управлять типом данных значений аргументов, которые вы задаете в блоках Model. Каждое значение аргумента использует тип данных, который вы задаете для соответствующего аргумента в рабочем пространстве модели.