Используйте блок вызывающей стороны C с условным выполнением

В этом примере показано, как использовать блок C Caller с условным выполнением. Модель в качестве примера содержит два блока Вызывающей стороны C, выходные параметры которых вводятся ветви в блок switch. Каждый блок C Caller вызывает одну из пользовательских функций кода С sort_ascend() и sort_descend(). Только одно из значений от входных ветвей передается выходной стороне блока switch. Функциональный блок C с теми же настройками может также использоваться вместо блока 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 28.521s

/* 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[0], 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[0], 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' */
  }

Задайте пользовательский код детерминированные функции

Откройте диалоговое окно Configuration Parameters.

В Целевой панели Симуляции, набор Детерминированные функции к By Function. Нажмите Specify функцией и добавьте функции 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 12.802s

/* 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[0], 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[0], 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' */

Смотрите также

| | |