Main Content

조건부 실행에서 C Caller 블록 사용하기

이 예제에서는 조건부 실행에서 C Caller 블록을 사용하는 방법을 보여줍니다. 예제 모델에는 출력값이 Switch 블록의 입력 분기인 두 개의 C Caller 블록이 포함되어 있습니다. 각 C Caller 블록은 사용자 지정 C 코드 함수 sort_ascend()sort_descend() 중 하나를 호출합니다. 입력 분기의 값 중 하나만 Switch 블록의 출력 측으로 전달됩니다. 동일한 설정을 가진 C Function 블록을 C Caller 블록 대신 사용하여 이러한 사용자 지정 코드 함수를 호출할 수도 있습니다

이 예제에서는 다음과 같은 개념을 보여줍니다.

  • 조건부 실행 컨텍스트에 놓인 Simulink® 블록에서 사용자 지정 C 코드를 호출합니다.

  • 사용자 지정 코드에서 함수별로 결정적 함수를 구성합니다.

모델 검토하기

이 모델은 Switch 블록의 입력 분기에 연결된 C Caller 블록을 통해 사용자 지정 코드를 호출합니다.

open_system('slexCCallerConditional');

코드 생성하기

이 모델의 사용자 지정 코드 함수는 결정적 함수로 식별되지 않았습니다. 모델에서 코드가 생성되면 Switch 블록이 함수 중 하나의 출력값만 필요로 하는데도 시뮬레이션 중에, 그리고 생성된 코드에서 두 C 함수가 모두 실행됩니다.

slbuild(bdroot);
cfile = fullfile('slexCCallerConditional_grt_rtw','slexCCallerConditional.c');
coder.example.extractLines(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 22.192s

/* 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' */
  }

결정적 사용자 지정 코드 함수 지정하기

구성 파라미터 대화 상자 열기

시뮬레이션 타깃 창에서 결정적 함수By Function으로 설정합니다. 함수별 지정을 클릭하고 함수 sort_ascendsort_descend를 목록에 추가합니다. 이 작업은 지정된 사용자 지정 코드 함수에 결정적 동작이 있음을, 다시 말해 함수에 대한 동일한 입력값이 항상 동일한 출력을 낳는다는 사실을 모델에 알려줍니다. 결정적인 것으로 설정된 함수가 Switch 블록의 false 값에 해당하는 입력 분기에 있으면 이를 호출할 필요가 없습니다.

configset.highlightParameter(bdroot,'DefaultCustomCodeDeterministicFunctions');
set_param(bdroot,'DefaultCustomCodeDeterministicFunctions','ByFunction');
set_param(bdroot,'CustomCodeDeterministicFunctions','sort_ascend,sort_descend');

코드 다시 생성하기

이제 결정적 함수를 지정했으며, 이렇게 생성된 코드의 경우 Switch 블록의 true 분기에 있는 C Caller 블록만 실행되므로 더 효율적입니다. Simulink에서 모델을 시뮬레이션할 때도 동일한 효율성이 적용됩니다.

slbuild(bdroot);
cfile = fullfile('slexCCallerConditional_grt_rtw','slexCCallerConditional.c');
coder.example.extractLines(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 16.289s

/* 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' */

참고 항목

| | |