exponenta event banner

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

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

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

  • Код записи, вызывающий сгенерированный код.

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

  • Интеграция созданного кода с другим внешним кодом в приложении.

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

Сведения о том, как сгенерированный код хранит внутренние данные, которые не участвуют в интерфейсе модели, см. в разделе Как сгенерированный код хранит внутренний сигнал, состояние и данные параметров.

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

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

Изучение примера модели

Открыть пример модели rtwdemo_roll.

open_system('rtwdemo_roll')

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

В модели установите Параметры конфигурации > Создание кода > Целевой файл системы в значение grt.tlc.

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

Проверьте настройки параметров конфигурации > Создание кода > Интерфейс > Упаковка интерфейса кода. Настройка Nonreusable function означает, что созданный код не используется повторно (не вводится повторно).

В этом примере для создания более простого кода снимите флажок «Параметры конфигурации» > «Создание кода» > «Интерфейс» > «Дополнительные параметры» > «Ведение журнала файлов».

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 7.4399s

Проверка файла 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 block считывает значение 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;

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

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

В модели установите Параметры конфигурации > Создание кода > Интерфейс > Упаковка интерфейса кода в значение 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 6.1374s

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

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)

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

Конфигурирование интерфейса данных

Для управления характеристиками интерфейса данных в сгенерированном коде см. раздел Управляющие данные и интерфейс функций в сгенерированном коде.

Связанные темы