Как сгенерированный код обменивается данными со средой

Чтобы использовать код, который вы генерируете из модели, вы вызываете сгенерированные функции точки входа, такие как step и initialize. Среда, в которой вы вызываете эти функции, должна обеспечить данные о входном сигнале и, в зависимости от вашего приложения, планируя информацию. Сгенерированный алгоритм затем вычисляет выходные данные, которые может использовать среда вызова. Среда и алгоритм могут обмениваться этими данными через глобальные переменные или через формальные параметры (аргументы).

Набор входных и выходных данных и механизмов обмена составляет интерфейсы функций точки входа. Когда вы изучаете интерфейсы по умолчанию и как управлять ими, вы можете:

  • Запишите код, который вызывает сгенерированный код.

  • Сгенерируйте допускающий повторное использование (повторно используемый) код, который можно вызвать многократно в отдельном приложении.

  • Интегрируйте сгенерированный код с другим, внешним кодом в вашем приложении.

В модели корневой уровень Inport и блоки Outport представляют первичные входные параметры и выходные параметры алгоритма блока. По умолчанию генератор кода агрегировал эти блоки в стандартные структуры те входные и выходные данные хранилища.

Для получения информации о том, как сгенерированный код хранит внутренние данные, которые не участвуют в интерфейсе модели, видят Как Хранилища Сгенерированного кода Внутренний Сигнал, состояние и Данные о Параметре.

Интерфейсы данных в сгенерированном коде

В этом примере показано, как сгенерированный код обменивается данными со средой.

Исследуйте модель в качестве примера

Откройте модель rtwdemo_roll в качестве примера.

open_system('rtwdemo_roll')

На корневом уровне модель имеет много Inport блоков и один блок Outport.

В модели, Параметры конфигурации набора> Генерация кода> Системный конечный файл к grt.tlc.

set_param('rtwdemo_roll','SystemTargetFile','grt.tlc')

Смотрите установку для упаковки интерфейса Configuration Parameters> Code Generation> Interface> Code. Установка Nonreusable function средние значения, что сгенерированный код не является допускающим повторное использование (не повторно используемый).

В данном примере, чтобы сгенерировать более простой код, очистите Параметры конфигурации> Генерация кода> Интерфейс> Продвинутые параметры> логгирование MAT-файла.

set_param('rtwdemo_roll','MatFileLogging','off')

Сгенерируйте код одноразового использования

Сгенерируйте код из модели.

slbuild('rtwdemo_roll')
### Starting build procedure for: rtwdemo_roll
### Successful completion of build procedure for: rtwdemo_roll

Build Summary

Top model targets built:

Model         Action                       Rebuild Reason                                    
=============================================================================================
rtwdemo_roll  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 9.5674s

Смотрите файл rtwdemo_roll.h. Файл задает тип структуры, который представляет входные данные и тип, который представляет выходные данные.

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,...
    '/* External inputs (root inport signals with default storage) */',...
    '} ExtY_rtwdemo_roll_T;',1,1)
/* External inputs (root inport signals with default storage) */
typedef struct {
  real32_T Phi;                        /* '<Root>/Phi' */
  real32_T Psi;                        /* '<Root>/Psi' */
  real32_T Rate_FB;                    /* '<Root>/Rate_FB' */
  real32_T TAS;                        /* '<Root>/TAS' */
  boolean_T AP_Eng;                    /* '<Root>/AP_Eng' */
  boolean_T HDG_Mode;                  /* '<Root>/HDG_Mode' */
  real32_T HDG_Ref;                    /* '<Root>/HDG_Ref' */
  real32_T Turn_Knob;                  /* '<Root>/Turn_Knob' */
} ExtU_rtwdemo_roll_T;

/* External outputs (root outports fed by signals with default storage) */
typedef struct {
  real32_T Ail_Cmd;                    /* '<Root>/Ail_Cmd' */
} ExtY_rtwdemo_roll_T;

Каждое поле соответствует блоку Inport или Outport на корневом уровне модели. Имя каждого поля выводит из имени блока.

Файл также задает тип структуры, структуру данных модели реального времени, одно поле которой хранит индикацию во время выполнения относительно того, столкнулся ли сгенерированный код с ошибкой во время выполнения.

rtwdemodbtype(file,'/* Real-time Model Data Structure */',...
    '/* Block states (default storage) */',1,0)
/* Real-time Model Data Structure */
struct tag_RTM_rtwdemo_roll_T {
  const char_T *errorStatus;
};

Когда вы изменяете параметры конфигурации модели, чтобы удовлетворить вашему приложению, эта структура может также содержать другие данные, которые принадлежат целой модели, такой как планирование информации.

Для типа структуры, который представляет структуру данных модели реального времени, файл rtwdemo_roll_types.h создает псевдоним (typedef) то, что сгенерированный код более позднее использование, чтобы выделить память для структуры.

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll_types.h');
rtwdemodbtype(file,'/* Forward declaration for rtModel */',...
    'RT_MODEL_rtwdemo_roll_T;',1,1)
/* Forward declaration for rtModel */
typedef struct tag_RTM_rtwdemo_roll_T RT_MODEL_rtwdemo_roll_T;

Используя эти типы структуры, файл rtwdemo_roll.c задает (выделяет память для), глобальные переменные структуры, которые хранят входные и выходные данные для сгенерированного алгоритма. Файл также задает переменные, которые представляют структуру данных модели реального времени и указатель на структуру.

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,...
    '/* External inputs (root inport signals with default storage) */',...
    '= &rtwdemo_roll_M_;',1,1)
/* External inputs (root inport signals with default storage) */
ExtU_rtwdemo_roll_T rtwdemo_roll_U;

/* External outputs (root outports fed by signals with default storage) */
ExtY_rtwdemo_roll_T rtwdemo_roll_Y;

/* Real-time model */
static RT_MODEL_rtwdemo_roll_T rtwdemo_roll_M_;
RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M = &rtwdemo_roll_M_;

Файл rtwdemo_roll.h объявляет эти переменные структуры. Ваш внешний код может включать (#include) этот файл, общим названием которого является model.h где model имя модели, к данным о доступе, которые участвуют в интерфейсе модели.

В rtwdemo_roll.c, модель step функция, которая представляет первичный алгоритм модели, использует void void интерфейс (без аргументов).

rtwdemodbtype(file,...
    '/* Model step function */','void rtwdemo_roll_step(void)',1,1)
/* Model step function */
void rtwdemo_roll_step(void)

В функциональном определении алгоритм читает входные данные и выходные данные записей путем прямого доступа к глобальным переменным структуры. Например, около конца алгоритма, кода для EngSwitch блок читает значение AP_Eng поле (который представляет вход) и, на основе того значения, условно пишет постоянное значение в Ail_Cmd поле (который представляет выход).

rtwdemodbtype(file,'if (rtwdemo_roll_U.AP_Eng) {','      }',1,1)
  if (rtwdemo_roll_U.AP_Eng) {
    /* Outputs for Atomic SubSystem: '<Root>/BasicRollMode' */
    /* Saturate: '<S1>/CmdLimit' */
    if (rtwdemo_roll_Y.Ail_Cmd > 15.0F) {
      /* Sum: '<S1>/Sum2' incorporates:
       *  Outport: '<Root>/Ail_Cmd'
       */
      rtwdemo_roll_Y.Ail_Cmd = 15.0F;
    } else if (rtwdemo_roll_Y.Ail_Cmd < -15.0F) {
      /* Sum: '<S1>/Sum2' incorporates:
       *  Outport: '<Root>/Ail_Cmd'
       */
      rtwdemo_roll_Y.Ail_Cmd = -15.0F;
    }

    /* End of Saturate: '<S1>/CmdLimit' */
    /* End of Outputs for SubSystem: '<Root>/BasicRollMode' */
  } else {
    /* Sum: '<S1>/Sum2' incorporates:
     *  Constant: '<Root>/Zero'
     *  Outport: '<Root>/Ail_Cmd'
     */
    rtwdemo_roll_Y.Ail_Cmd = 0.0F;
  }

  /* End of Switch: '<Root>/EngSwitch' */
}

/* Model initialize function */
void rtwdemo_roll_initialize(void)
{
  /* Registration code */

  /* initialize error status */
  rtmSetErrorStatus(rtwdemo_roll_M, (NULL));

  /* states (dwork) */
  (void) memset((void *)&rtwdemo_roll_DW, 0,
                sizeof(DW_rtwdemo_roll_T));

  /* external inputs */
  (void)memset(&rtwdemo_roll_U, 0, sizeof(ExtU_rtwdemo_roll_T));

  /* external outputs */
  rtwdemo_roll_Y.Ail_Cmd = 0.0F;

  /* SystemInitialize for Atomic SubSystem: '<Root>/RollAngleReference' */
  /* InitializeConditions for UnitDelay: '<S4>/FixPt Unit Delay1' */
  rtwdemo_roll_DW.FixPtUnitDelay1_DSTATE = 0.0F;

  /* End of SystemInitialize for SubSystem: '<Root>/RollAngleReference' */

  /* SystemInitialize for Atomic SubSystem: '<Root>/BasicRollMode' */
  /* InitializeConditions for DiscreteIntegrator: '<S1>/Integrator' */
  rtwdemo_roll_DW.Integrator_DSTATE = 0.0F;
  rtwdemo_roll_DW.Integrator_PrevResetState = 0;

  /* End of SystemInitialize for SubSystem: '<Root>/BasicRollMode' */
}

/* Model terminate function */
void rtwdemo_roll_terminate(void)
{
  /* (no terminate code required) */
}

Из-за void void взаимодействуйте через интерфейс и прямой доступ к данным, функция не повторно используема. Если вы вызываете функцию многократно в приложении, каждый вызов читает и входные и выходные данные записей в те же глобальные переменные структуры, приводящие к повреждению данных и неумышленному взаимодействию между вызовами.

Функция инициализации модели, rtwdemo_roll_initialize, инициализирует входные и выходные данные, чтобы обнулить. Функция также инициализирует ошибочное состояние. Функция непосредственно получает доступ к глобальным переменным, что означает, что функция не повторно используема.

rtwdemodbtype(file,'/* Model initialize function */',...
    'rtmSetErrorStatus(rtwdemo_roll_M, (NULL));',1,1)
/* Model initialize function */
void rtwdemo_roll_initialize(void)
{
  /* Registration code */

  /* initialize error status */
  rtmSetErrorStatus(rtwdemo_roll_M, (NULL));
rtwdemodbtype(file,'  /* external inputs */',...
    '/* SystemInitialize for Atomic SubSystem:',1,0)
  /* external inputs */
  (void)memset(&rtwdemo_roll_U, 0, sizeof(ExtU_rtwdemo_roll_T));

  /* external outputs */
  rtwdemo_roll_Y.Ail_Cmd = 0.0F;

Сгенерируйте повторно используемый код

Можно сконфигурировать сгенерированный код как повторно используемый, что означает, что можно вызвать функции точки входа многократно в приложении. С этой настройкой, вместо того, чтобы непосредственно получить доступ к глобальным переменным, точка входа функционирует обменный вход, выход и другие данные модели через формальные параметры (аргументы указателя). С этими аргументами указателя каждый вызов может считать входные параметры и записать выходные параметры в набор отдельных глобальных переменных, предотвратив неумышленное взаимодействие между вызовами.

В модели, упаковке интерфейса Configuration Parameters> Code Generation> Interface> Code набора к Reusable function.

set_param('rtwdemo_roll','CodeInterfacePackaging','Reusable function')

Сгенерируйте код из модели.

slbuild('rtwdemo_roll')
### Starting build procedure for: rtwdemo_roll
### Successful completion of build procedure for: rtwdemo_roll

Build Summary

Top model targets built:

Model         Action                       Rebuild Reason                   
============================================================================
rtwdemo_roll  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 7.2544s

Теперь в rtwdemo_roll.h, структура данных модели реального времени содержит указатели на ошибочную индикацию, входные данные, выходные данные и дополнительные данные в форме DWork подструктура (который хранит, например, состояния блока, такие как состояние блока Discrete-Time Integrator).

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,'/* Real-time Model Data Structure */',...
    '/* External data declarations for dependent source files */',1,0)
/* Real-time Model Data Structure */
struct tag_RTM_rtwdemo_roll_T {
  const char_T *errorStatus;
  ExtU_rtwdemo_roll_T *inputs;
  ExtY_rtwdemo_roll_T *outputs;
  DW_rtwdemo_roll_T *dwork;
};

Чтобы вызвать сгенерированный код многократно в приложении, ваш код должен выделить память для структуры данных модели реального времени на вызов. Файл rtwdemo_roll.c задает специализированную функцию, которая выделяет память для новой структуры данных модели реального времени и возвращает указатель на структуру. Функция также выделяет память для подструктур, которые поля в структуре данных модели указывают на, такие как структуры ввода и вывода.

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,'/* Model data allocation function */',...
    'RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)',1,1)
/* Model data allocation function */
RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)

В rtwdemo_roll.c, модель step функция принимает аргумент, который представляет структуру данных модели реального времени.

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,...
    '/* Model step function */','void rtwdemo_roll_step',1,1)
/* Model step function */
void rtwdemo_roll_step(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

В функциональном определении алгоритм сначала извлекает каждый указатель из структуры данных модели реального времени в локальную переменную.

rtwdemodbtype(file,...
    '*rtwdemo_roll_DW =','rtwdemo_roll_M->outputs;',1,1)
  DW_rtwdemo_roll_T *rtwdemo_roll_DW = rtwdemo_roll_M->dwork;
  ExtU_rtwdemo_roll_T *rtwdemo_roll_U = (ExtU_rtwdemo_roll_T *)
    rtwdemo_roll_M->inputs;
  ExtY_rtwdemo_roll_T *rtwdemo_roll_Y = (ExtY_rtwdemo_roll_T *)
    rtwdemo_roll_M->outputs;

Затем чтобы получить доступ к входным и выходным данным, сохраненным в глобальной памяти, алгоритм взаимодействует с этими локальными переменными.

rtwdemodbtype(file,'  if (rtwdemo_roll_U->AP_Eng) {',...
    '  /* End of Switch: ''<Root>/EngSwitch'' */',1,1)
  if (rtwdemo_roll_U->AP_Eng) {
    /* Outputs for Atomic SubSystem: '<Root>/BasicRollMode' */
    /* Saturate: '<S1>/CmdLimit' */
    if (rtwdemo_roll_Y->Ail_Cmd > 15.0F) {
      /* Sum: '<S1>/Sum2' incorporates:
       *  Outport: '<Root>/Ail_Cmd'
       */
      rtwdemo_roll_Y->Ail_Cmd = 15.0F;
    } else if (rtwdemo_roll_Y->Ail_Cmd < -15.0F) {
      /* Sum: '<S1>/Sum2' incorporates:
       *  Outport: '<Root>/Ail_Cmd'
       */
      rtwdemo_roll_Y->Ail_Cmd = -15.0F;
    }

    /* End of Saturate: '<S1>/CmdLimit' */
    /* End of Outputs for SubSystem: '<Root>/BasicRollMode' */
  } else {
    /* Sum: '<S1>/Sum2' incorporates:
     *  Constant: '<Root>/Zero'
     *  Outport: '<Root>/Ail_Cmd'
     */
    rtwdemo_roll_Y->Ail_Cmd = 0.0F;
  }

Точно так же функция инициализации модели принимает структуру данных модели реального времени как аргумент.

rtwdemodbtype(file,...
    '/* Model initialize function */','void rtwdemo_roll_initialize',1,1)
/* Model initialize function */
void rtwdemo_roll_initialize(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

Поскольку каждый вызов, который вы выполняете к функции точки входа, взаимодействует с отдельной структурой данных модели реального времени, вы избегаете неумышленного взаимодействия между вызовами.

Сконфигурируйте интерфейс данных

Чтобы управлять характеристиками интерфейса данных в сгенерированном коде, смотрите Данные об Управлении и Функциональный Интерфейс в Сгенерированном коде.

Похожие темы