Можно использовать Variant Source и блоки Variant Sink, чтобы чувствовать несколько реализаций модели в одной, объединенной блок-схеме. Каждая реализация зависит от условий, которые вы устанавливаете для блоков Variant Sink и Variant Source. Simulink® распространяет эти условия с восходящими и нисходящими блоками включая корневой вход и корневые выходные порты.
Можно сгенерировать:
Код из модели Simulink, содержащей Variant Sink и блоки Variant Source.
Код, который содержит условные выражения препроцессора, которые управляют активацией каждого варианта.
Условные выражения препроцессора, которые не допускают активного варианта.
В этом примере показано, как Различные Исходные блоки делают условное выражение элементов модели.
От Библиотеки блока Simulink добавьте 1 блок Sine Wave Function, два блока Add, три блока Gain, два Outports и два блока Variant Source в новую модель.
Откройте блок Sine Wave Function. Для параметра Sine type выберите Sample based
. Для параметра Time (t) выберите Use simulation time
. Для параметра Sample time вставьте значение 0.2
.
Сделайте четыре копии блока Sine Wave Function.
Соедините и назовите блоки как показано.
Вставьте значения 2
, 3, и
4
в Gain2
, Gain3
, и Gain4
блоки, соответственно.
Дайте модели имя inline_variants_example
.
Откройте диалоговое окно Block Parameters для Variant Source
.
В столбце Variant control, для Порта 1, Variant_1
замены с
V==1
. Для Порта 2, замените Variant_2
с V==2
.
Откройте диалоговое окно Block Parameters для Variant Source1
.
В столбце Variant control замените Variant_1
с W==1
. Для Порта 2, замените Variant_2
с W==2
.
В Окне Команды MATLAB используйте эти команды, чтобы задать V
и W
как Simulink.Parameter
объекты.
V = Simulink.Parameter; V.Value = 1; V.DataType='int32'; V.CoderInfo.StorageClass = 'custom'; V.CoderInfo.CustomStorageClass = 'Define'; V.CoderInfo.CustomAttributes.HeaderFile='inline_importedmacro.h' W = Simulink.Parameter; W.Value = 2; W.DataType='int32'; W.CoderInfo.StorageClass = 'custom'; W.CoderInfo.CustomStorageClass = 'Define'; W.CoderInfo.CustomAttributes.HeaderFile='inline_importedmacro.h'
В этом примере различными контрольными переменными является Simulink.Parameter
объекты. Для генерации кода, если вы используете Simulink.Variant
объекты задать различные средства управления, используйте Simulink.Parameter
объекты или переменные MATLAB, чтобы задать их условия..
Различные контрольные переменные, заданные как Simulink.Parameter
объекты могут иметь один из этих классов памяти:
Define
с заданным заголовочным файлом
ImportedDefine
с заданным заголовочным файлом
CompilerFlag
SystemConstant (AUTOSAR)
Пользовательский пользовательский класс памяти, который задает данные как макрос в заданном заголовочном файле
Если вы используете скалярные различные контрольные переменные, чтобы симулировать модель, можно преобразовать те переменные в Simulink.Parameter
объекты. Смотрите Преобразуют Различные Контрольные переменные в Simulink. Объекты параметра (Simulink).
Симулируйте модель.
Input port 1 является активным выбором для Variant Source
потому что значение различной контрольной переменной V
1
. Input port 2 является активным выбором для Variant Source1
потому что значение различной контрольной переменной W
2. Неактивный выбор удален из выполнения, и их пути отображаются серым в схеме.
Можно сгенерировать код, в который каждый вариант заключен в условных выражениях препроцессора C #if
и #endif
. Компилятор выбирает активный вариант во время компиляции, и условные выражения препроцессора определяют который разделы кода выполниться.
Во вкладке Modeling панели инструментов Simulink нажмите Model Settings.
Выберите панель Code Generation и установите System target file на ert.tlc
.
В вашей модели откройте диалоговое окно параметров блоков для Variant Source
.
Выберите параметр Analyze all choices during update diagram and generate preprocessor conditionals. Во время схемы обновления или симуляции, когда вы выбираете этот параметр, Simulink анализирует все варианты. Этот анализ обеспечивает раннюю валидацию готовности генерации кода вариантов. Во время генерации кода, когда вы выбираете этот параметр, генератор кода генерирует условные выражения препроцессора, которые управляют активацией каждого варианта.
Очистите параметр Allow zero active variant controls.
Откройте диалоговое окно Block Parameters для Variant Source 1
. Повторите шаги 5 - 7.
Создайте модель. Когда генерация кода завершена, сгенерированный код отображен в Представлении кода.
В Представлении кода выберите inline_variants_example.c
файл.
В inline_variants_example.c
файл, вызовы inline_variants_example_step
функционируйте и inline_variants_example_initialize
функции условно скомпилированы как показано:
/* Model step function */ void inline_variants_example_step(void) { real_T rtb_Sine6; real_T rtb_VM_Conditional_Signal_Sum_1; /* Sin: '<Root>/Sine1' incorporates: * Sin: '<Root>/Sine2' * Sin: '<Root>/Sine3' * Sum: '<Root>/Add1' */ #if V == 1 rtb_Sine6 = sin(((real_T)slexVariantSourceAndSink_DW.counter + slexVariantSourceAndSink_P.Sine1_Offset) * 2.0 * 3.1415926535897931 / slexVariantSourceAndSink_P.Sine1_NumSamp) * slexVariantSourceAndSink_P.Sine1_Amp + slexVariantSourceAndSink_P.Sine1_Bias; #elif V == 2 /* Sum: '<Root>/Add1' incorporates: * Sin: '<Root>/Sine2' * Sin: '<Root>/Sine3' */ rtb_Sine6 = (sin(((real_T)slexVariantSourceAndSink_DW.counter_i + slexVariantSourceAndSink_P.Sine2_Offset) * 2.0 * 3.1415926535897931 / slexVariantSourceAndSink_P.Sine2_NumSamp) * slexVariantSourceAndSink_P.Sine2_Amp + slexVariantSourceAndSink_P.Sine2_Bias) + (sin(((real_T) slexVariantSourceAndSink_DW.counter_f + slexVariantSourceAndSink_P.Sine3_Offset) * 2.0 * 3.1415926535897931 / slexVariantSourceAndSink_P.Sine3_NumSamp) * slexVariantSourceAndSink_P.Sine3_Amp + slexVariantSourceAndSink_P.Sine3_Bias); #endif /* End of Sin: '<Root>/Sine1' */ /* Gain: '<Root>/Gain3' incorporates: * Outport: '<Root>/Out1' */ #if V == 1 || V == 2 slexVariantSourceAndSink_Y.Out1 = slexVariantSourceAndSink_P.Gain3_Gain * rtb_Sine6; #endif /* End of Gain: '<Root>/Gain3' */ /* Sin: '<Root>/Sine5' */ rtb_Sine6 = sin(((real_T)slexVariantSourceAndSink_DW.counter_d + slexVariantSourceAndSink_P.Sine5_Offset) * 2.0 * 3.1415926535897931 / slexVariantSourceAndSink_P.Sine5_NumSamp) * slexVariantSourceAndSink_P.Sine5_Amp + slexVariantSourceAndSink_P.Sine5_Bias; /* Gain: '<Root>/Gain5' incorporates: * Gain: '<Root>/Gain4' * SignalConversion generated from: '<Root>/Sum' * */ #if W == 1 rtb_Sine6 = slexVariantSourceAndSink_P.Gain4_Gain * rtb_Sine6 * slexVariantSourceAndSink_P.Gain5_Gain; rtb_VM_Conditional_Signal_Sum_1 = rtb_Sine6; #else /* SignalConversion generated from: '<Root>/Sum' */ rtb_VM_Conditional_Signal_Sum_1 = 0.0; #endif /* End of Gain: '<Root>/Gain5' */ /* Outport: '<Root>/Out2' incorporates: * Sin: '<Root>/Sine6' * Sum: '<Root>/Sum' */ slexVariantSourceAndSink_Y.Out2 = (sin(((real_T) slexVariantSourceAndSink_DW.counter_g + slexVariantSourceAndSink_P.Sine6_Offset) * 2.0 * 3.1415926535897931 / slexVariantSourceAndSink_P.Sine6_NumSamp) * slexVariantSourceAndSink_P.Sine6_Amp + slexVariantSourceAndSink_P.Sine6_Bias) + rtb_VM_Conditional_Signal_Sum_1; /* Outport: '<Root>/Out3' */ #if W == 1 slexVariantSourceAndSink_Y.Out3 = rtb_Sine6; #endif /* End of Outport: '<Root>/Out3' */ /* Update for Sin: '<Root>/Sine1' incorporates: * Sin: '<Root>/Sine2' * Sin: '<Root>/Sine3' */ #if V == 1 slexVariantSourceAndSink_DW.counter++; if (slexVariantSourceAndSink_DW.counter == slexVariantSourceAndSink_P.Sine1_NumSamp) { slexVariantSourceAndSink_DW.counter = 0; } #elif V == 2 /* Update for Sin: '<Root>/Sine2' */ slexVariantSourceAndSink_DW.counter_i++; if (slexVariantSourceAndSink_DW.counter_i == slexVariantSourceAndSink_P.Sine2_NumSamp) { slexVariantSourceAndSink_DW.counter_i = 0; } /* Update for Sin: '<Root>/Sine3' */ slexVariantSourceAndSink_DW.counter_f++; if (slexVariantSourceAndSink_DW.counter_f == slexVariantSourceAndSink_P.Sine3_NumSamp) { slexVariantSourceAndSink_DW.counter_f = 0; } #endif /* End of Update for Sin: '<Root>/Sine1' */ /* Update for Sin: '<Root>/Sine6' */ slexVariantSourceAndSink_DW.counter_g++; if (slexVariantSourceAndSink_DW.counter_g == slexVariantSourceAndSink_P.Sine6_NumSamp) { slexVariantSourceAndSink_DW.counter_g = 0; } /* End of Update for Sin: '<Root>/Sine6' */ /* Update for Sin: '<Root>/Sine5' */ slexVariantSourceAndSink_DW.counter_d++; if (slexVariantSourceAndSink_DW.counter_d == slexVariantSourceAndSink_P.Sine5_NumSamp) { slexVariantSourceAndSink_DW.counter_d = 0; } /* End of Update for Sin: '<Root>/Sine5' */ } }
Переменные rtb_Sine4
и rtb_VariantMerge_For_Variant_So
содержите входные значения с блоками Variant Source. Заметьте, что код для этих переменных является условным выражением. Переменные inline_variants_example_Y.Out1
и inline_variants_example_Y.Out2
содержите выходные значения блоков Variant Source. Заметьте, что код для этих переменных не является условным выражением.
Можно сгенерировать код, в котором блоки, соединенные с входом и выходом Различного Исходного блока, являются условным выражением.
Для Variant Source
, откройте диалоговое окно Block Parameters. Выберите параметр Allow zero active variant controls.
Для Variant Source 1
, откройте диалоговое окно Block Parameters. Выберите параметр Allow zero active variant controls.
Когда вы выбираете параметр Allow zero active variant controls, можно сгенерировать код для модели, содержащей Variant Source и блоки Variant Sink, даже когда вы задаете значение для различной контрольной переменной, которая не допускает активный вариант. Выбор значения для различной контрольной переменной, которая не допускает активный вариант и не выбор параметра Allow zero active variant controls, производит ошибку.
Сгенерируйте код для inline_variants_example
. Заметьте в inline_variants_example.c
файл, что код для переменных inline_variants_example_Y.Out1
и inline_variants_example_Y.Out2
условное выражение.
/* Model step function */ void inline_variants_example_step(void) { ... #if V == 1 || V == 2 inline_variants_example_Y.Out1 = 3.0 * rtb_Sine4; #endif /* V == 1 || V == 2 */ ... #if (V == 1 && W == 1) || (V == 2 && W == 1) || W == 2 inline_variants_example_Y.Out2 = 4.0 * rtb_VariantMerge_For_Variant_So; #endif /* (V == 1 && W == 1) || (V == 2 && W == 1) || W == 2 */ ...