В этом примере показано, как использовать блок C Caller с условным выполнением. Модель примера содержит два блока C Caller, выходы которых являются входными ветвями в блок Switch. Каждый блок C Caller вызывает одну из пользовательских функций Кода С sort_ascend()
и sort_descend()
. Только одно из значений из входа ветвей передается на выход сторону блока Switch. Блок C Function с теми же настройками также может использоваться вместо блока C Caller для вызова этих функций пользовательского кода.
Этот пример иллюстрирует следующие концепции:
Вызов пользовательского кода С из блока Simulink ® в контексте условного выполнения.
Конфигурирование детерминированных функций по функциям в пользовательском коде.
Эта модель вызывает пользовательский код через блок C Caller, который соединяется с входом ветвью блока Switch.
open_system('slexCCallerConditional'); % Create a temporary folder for the build and inspection process. currentDir=pwd; [~,cgDir]=rtwdemodir();
Пользовательские функции кода в этой модели не были идентифицированы как детерминированные функции. Когда код генерируется из модели, обе функции C выполняются во время симуляции и в сгенерированном коде, хотя блок Switch требует выхода только одной из функций.
slbuild(bdroot); cfile = fullfile(cgDir,'slexCCallerConditional_grt_rtw','slexCCallerConditional.c'); rtwdemodbtype(cfile,'/* Model step', '/* Matfile logging', 1, 0);
### Starting build procedure for: slexCCallerConditional ### Successful completion of build procedure for: slexCCallerConditional Build Summary Top model targets built: Model Action Rebuild Reason ======================================================================================================= slexCCallerConditional Code generated and compiled Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 25.644s /* Model step function */ void slexCCallerConditional_step(void) { real_T rtb_CCallerascend[6]; real_T rtb_CCallerdescend[6]; int32_T i; /* CCaller: '<Root>/C Caller (ascend)' incorporates: * Inport: '<Root>/In2' */ for (i = 0; i < 6; i++) { rtb_CCallerascend[i] = slexCCallerConditional_U.In2[i]; } sort_ascend(rtb_CCallerascend, 6); /* End of CCaller: '<Root>/C Caller (ascend)' */ /* CCaller: '<Root>/C Caller (descend)' incorporates: * Inport: '<Root>/In2' */ for (i = 0; i < 6; i++) { rtb_CCallerdescend[i] = slexCCallerConditional_U.In2[i]; } sort_descend(rtb_CCallerdescend, 6); /* End of CCaller: '<Root>/C Caller (descend)' */ for (i = 0; i < 6; i++) { /* Switch: '<Root>/Switch' incorporates: * Inport: '<Root>/In1' */ if (slexCCallerConditional_U.In1 > 0.0) { /* Outport: '<Root>/Out3' */ slexCCallerConditional_Y.Out3[i] = rtb_CCallerascend[i]; } else { /* Outport: '<Root>/Out3' */ slexCCallerConditional_Y.Out3[i] = rtb_CCallerdescend[i]; } /* End of Switch: '<Root>/Switch' */ }
Откройте диалоговое окно Параметры конфигурации.
На панели Simulation Target, в группе Import Custom Code, установите для функций Determinsitic значение By function
. Нажмите Specify by Function и добавьте функции sort_ascend
и sort_descend
в список. Это действие сообщает модели, что заданные пользовательские функции кода имеют детерминированное поведение, то есть те же входные значения функций всегда дают одинаковые выходы. Если функция настроена на детерминированность, ее не нужно вызывать, если она находится в входе ветви, соответствующей ложному значению блока Switch.
configset.highlightParameter(bdroot,'DefaultCustomCodeDeterministicFunctions'); set_param(bdroot,'DefaultCustomCodeDeterministicFunctions','ByFunction'); set_param(bdroot,'CustomCodeDeterministicFunctions','sort_ascend,sort_descend');
Теперь, когда вы определили детерминированные функции, сгенерированный код более эффективен, потому что выполняется только блок C Caller в истинной ветви блока Switch. Та же эффективность применяется и при симуляции модели в Simulink.
slbuild(bdroot); cfile = fullfile(cgDir,'slexCCallerConditional_grt_rtw','slexCCallerConditional.c'); rtwdemodbtype(cfile,'/* Model step', '/* Matfile logging', 1, 0); close_system(bdroot, 0);
### Starting build procedure for: slexCCallerConditional ### Successful completion of build procedure for: slexCCallerConditional Build Summary Top model targets built: Model Action Rebuild Reason ====================================================================================== slexCCallerConditional Code generated and compiled Generated code was out of date. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 10.423s /* Model step function */ void slexCCallerConditional_step(void) { real_T rtb_CCallerascend[6]; int32_T i; /* Switch: '<Root>/Switch' incorporates: * Inport: '<Root>/In1' */ if (slexCCallerConditional_U.In1 > 0.0) { /* CCaller: '<Root>/C Caller (ascend)' incorporates: * Inport: '<Root>/In2' */ for (i = 0; i < 6; i++) { rtb_CCallerascend[i] = slexCCallerConditional_U.In2[i]; } sort_ascend(rtb_CCallerascend, 6); /* End of CCaller: '<Root>/C Caller (ascend)' */ } else { /* CCaller: '<Root>/C Caller (descend)' incorporates: * Inport: '<Root>/In2' */ for (i = 0; i < 6; i++) { rtb_CCallerascend[i] = slexCCallerConditional_U.In2[i]; } sort_descend(rtb_CCallerascend, 6); /* End of CCaller: '<Root>/C Caller (descend)' */ } /* End of Switch: '<Root>/Switch' */ /* Outport: '<Root>/Out3' */ for (i = 0; i < 6; i++) { slexCCallerConditional_Y.Out3[i] = rtb_CCallerascend[i]; } /* End of Outport: '<Root>/Out3' */
C Caller | C Function | Детерминированные функции | Задайте функцией