Как сгенерированный код хранит внутренний сигнал, состояние и данные о параметре

Чтобы вычислить выходные параметры от входных параметров, сгенерированный код хранит некоторый internal data в глобальной памяти. Сигнал, который не соединяется с вводом или выводом корневого уровня (блок Inport или Outport) является внутренними данными.

Внутренние данные могут также включать:

  • Состояние блока, такое как состояние блока Unit Delay. Алгоритм должен сохранить значение состояния между циклами выполнения, таким образом, сгенерированный код обычно хранит состояния в глобальной памяти (например, как глобальная переменная или поле глобальной переменной структуры).

  • Параметры блоков, такие как параметр Gain блока Gain, значение которого генератор кода не может встроить в коде. Например, генератор кода не может встроить значение нескалярного параметра.

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

Для более эффективного кода можно сконфигурировать оптимизацию, такую как Configuration Parameters> Default parameter behavior и Configuration Parameters> Signal storage reuse, которые пытаются устранить устройство хранения данных для внутренних данных. Однако оптимизация не может устранить устройство хранения данных для некоторых данных, которые используют память в сгенерированном коде.

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

  • Сделайте сигналы доступными и параметры настраиваемый по умолчанию. Можно затем взаимодействовать с и контролировать код во время выполнения.

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

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

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

Внутренние данные в сгенерированном коде

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

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

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

open_system('rtwdemo_roll')

Модель содержит внутренние сигналы, которые не соединяют с корневым уровнем блоки Outport или Inport. Некоторые сигналы имеют имя, такое как phiCmd сигнал.

Модель также содержит некоторые блоки, которые обеспечивают данные состояния. Например, в BasicRollMode подсистема, блок Discrete-Time Integrator пометил Integrator обеспечивает состояние.

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

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

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

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

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

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

Установите эти параметры конфигурации:

  • Установите поведение параметра По умолчанию на Tunable.

  • Повторное использование устройства хранения данных Четкого сигнала.

set_param('rtwdemo_roll','DefaultParameterBehavior','Tunable',...
    'OptimizeBlockIOStorage','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 10.748s

Файл rtwdemo_roll.h задает несколько типов структуры, которые представляют внутренние данные. Например, структура ввода и вывода блока задает одно поле для каждого внутреннего сигнала в модели. Каждое имя поля выводит из имени блока, который генерирует сигнал или, если вы задаете имя для сигнала с имени сигнала.

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,...
    '/* Block signals (default storage) */','} B_rtwdemo_roll_T;',1,1)
/* Block signals (default storage) */
typedef struct {
  real32_T phiCmd;                     /* '<Root>/ModeSwitch' */
  real32_T hdgError;                   /* '<S2>/Sum' */
  real32_T DispGain;                   /* '<S2>/DispGain' */
  real32_T Product;                    /* '<S2>/Product' */
  real32_T Abs;                        /* '<S3>/Abs' */
  real32_T FixPtUnitDelay1;            /* '<S4>/FixPt Unit Delay1' */
  real32_T Xnew;                       /* '<S4>/Enable' */
  real32_T TKSwitch;                   /* '<S3>/TKSwitch' */
  real32_T RefSwitch;                  /* '<S3>/RefSwitch' */
  real32_T Integrator;                 /* '<S1>/Integrator' */
  real32_T DispLimit;                  /* '<S1>/DispLimit' */
  real32_T Sum;                        /* '<S1>/Sum' */
  real32_T DispGain_f;                 /* '<S1>/DispGain' */
  real32_T RateLimit;                  /* '<S1>/RateLimit' */
  real32_T Sum1;                       /* '<S1>/Sum1' */
  real32_T RateGain;                   /* '<S1>/RateGain' */
  real32_T Sum2;                       /* '<S1>/Sum2' */
  real32_T CmdLimit;                   /* '<S1>/CmdLimit' */
  real32_T IntGain;                    /* '<S1>/IntGain' */
  boolean_T NotEngaged;                /* '<S3>/NotEngaged' */
  boolean_T TKThreshold;               /* '<S3>/TKThreshold' */
  boolean_T RefThreshold2;             /* '<S3>/RefThreshold2' */
  boolean_T RefThreshold1;             /* '<S3>/RefThreshold1' */
  boolean_T Or;                        /* '<S3>/Or' */
  boolean_T NotEngaged_e;              /* '<S1>/NotEngaged' */
} B_rtwdemo_roll_T;

Файл задает тип структуры, структуру DWork, чтобы представлять состояния блока, такие как состояние блока Discrete-Time Integrator.

rtwdemodbtype(file,...
    '/* Block states (default storage) for system','} DW_rtwdemo_roll_T;',1,1)
/* Block states (default storage) for system '<Root>' */
typedef struct {
  real32_T FixPtUnitDelay1_DSTATE;     /* '<S4>/FixPt Unit Delay1' */
  real32_T Integrator_DSTATE;          /* '<S1>/Integrator' */
  int8_T Integrator_PrevResetState;    /* '<S1>/Integrator' */
} DW_rtwdemo_roll_T;

Файл задает тип структуры, чтобы представлять данные о параметре. Каждые настраиваемые параметры блоков в модели, такой как параметр Усиления блока Gain, появляются как поле этой структуры. Если параметры блоков получают свое значение от переменной MATLAB или Simulink.Parameter объект, переменная или объект появляются как поле, не параметры блоков.

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

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

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

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,'/* Block signals (default storage) */',...
    '= &rtwdemo_roll_M_;',1,1)
/* Block signals (default storage) */
B_rtwdemo_roll_T rtwdemo_roll_B;

/* Block states (default storage) */
DW_rtwdemo_roll_T rtwdemo_roll_DW;

/* 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_;

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

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

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

rtwdemodbtype(file,'/* DiscreteIntegrator: ''<S1>/Integrator'' *',...
    '/* End of DiscreteIntegrator: ''<S1>/Integrator'' */',1,1)
  /* DiscreteIntegrator: '<S1>/Integrator' */
  if (rtwdemo_roll_B.NotEngaged_e || (rtwdemo_roll_DW.Integrator_PrevResetState
       != 0)) {
    rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_IC;
  }

  if (rtwdemo_roll_DW.Integrator_DSTATE >= rtwdemo_roll_P.intLim) {
    rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.intLim;
  } else if (rtwdemo_roll_DW.Integrator_DSTATE <=
             rtwdemo_roll_P.Integrator_LowerSat) {
    rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_LowerSat;
  }

  /* DiscreteIntegrator: '<S1>/Integrator' */
  rtwdemo_roll_B.Integrator = rtwdemo_roll_DW.Integrator_DSTATE;

  /* Saturate: '<S1>/DispLimit' */
  u0 = rtwdemo_roll_B.phiCmd;
  u1 = rtwdemo_roll_P.DispLimit_LowerSat;
  u2 = rtwdemo_roll_P.dispLim;
  if (u0 > u2) {
    /* Saturate: '<S1>/DispLimit' */
    rtwdemo_roll_B.DispLimit = u2;
  } else if (u0 < u1) {
    /* Saturate: '<S1>/DispLimit' */
    rtwdemo_roll_B.DispLimit = u1;
  } else {
    /* Saturate: '<S1>/DispLimit' */
    rtwdemo_roll_B.DispLimit = u0;
  }

  /* End of Saturate: '<S1>/DispLimit' */

  /* Sum: '<S1>/Sum' incorporates:
   *  Inport: '<Root>/Phi'
   */
  rtwdemo_roll_B.Sum = rtwdemo_roll_B.DispLimit - rtwdemo_roll_U.Phi;

  /* Gain: '<S1>/DispGain' */
  rtwdemo_roll_B.DispGain_f = rtwdemo_roll_P.dispGain * rtwdemo_roll_B.Sum;

  /* Saturate: '<S1>/RateLimit' */
  u0 = rtwdemo_roll_B.DispGain_f;
  u1 = rtwdemo_roll_P.RateLimit_LowerSat;
  u2 = rtwdemo_roll_P.rateLim;
  if (u0 > u2) {
    /* Saturate: '<S1>/RateLimit' */
    rtwdemo_roll_B.RateLimit = u2;
  } else if (u0 < u1) {
    /* Saturate: '<S1>/RateLimit' */
    rtwdemo_roll_B.RateLimit = u1;
  } else {
    /* Saturate: '<S1>/RateLimit' */
    rtwdemo_roll_B.RateLimit = u0;
  }

  /* End of Saturate: '<S1>/RateLimit' */

  /* Sum: '<S1>/Sum1' incorporates:
   *  Inport: '<Root>/Rate_FB'
   */
  rtwdemo_roll_B.Sum1 = rtwdemo_roll_B.RateLimit - rtwdemo_roll_U.Rate_FB;

  /* Gain: '<S1>/RateGain' */
  rtwdemo_roll_B.RateGain = rtwdemo_roll_P.rateGain * rtwdemo_roll_B.Sum1;

  /* Sum: '<S1>/Sum2' */
  rtwdemo_roll_B.Sum2 = rtwdemo_roll_B.Integrator + rtwdemo_roll_B.RateGain;

  /* Saturate: '<S1>/CmdLimit' */
  u0 = rtwdemo_roll_B.Sum2;
  u1 = rtwdemo_roll_P.CmdLimit_LowerSat;
  u2 = rtwdemo_roll_P.cmdLim;
  if (u0 > u2) {
    /* Saturate: '<S1>/CmdLimit' */
    rtwdemo_roll_B.CmdLimit = u2;
  } else if (u0 < u1) {
    /* Saturate: '<S1>/CmdLimit' */
    rtwdemo_roll_B.CmdLimit = u1;
  } else {
    /* Saturate: '<S1>/CmdLimit' */
    rtwdemo_roll_B.CmdLimit = u0;
  }

  /* End of Saturate: '<S1>/CmdLimit' */

  /* Gain: '<S1>/IntGain' */
  rtwdemo_roll_B.IntGain = rtwdemo_roll_P.intGain * rtwdemo_roll_B.Sum1;

  /* Update for DiscreteIntegrator: '<S1>/Integrator' */
  rtwdemo_roll_DW.Integrator_DSTATE += rtwdemo_roll_P.Integrator_gainval *
    rtwdemo_roll_B.IntGain;
  if (rtwdemo_roll_DW.Integrator_DSTATE >= rtwdemo_roll_P.intLim) {
    rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.intLim;
  } else if (rtwdemo_roll_DW.Integrator_DSTATE <=
             rtwdemo_roll_P.Integrator_LowerSat) {
    rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_LowerSat;
  }

  rtwdemo_roll_DW.Integrator_PrevResetState = (int8_T)
    rtwdemo_roll_B.NotEngaged_e;

  /* End of Update for DiscreteIntegrator: '<S1>/Integrator' */
  /* End of Outputs for SubSystem: '<Root>/BasicRollMode' */

  /* Switch: '<Root>/EngSwitch' incorporates:
   *  Inport: '<Root>/AP_Eng'
   */
  if (rtwdemo_roll_U.AP_Eng) {
    /* Outport: '<Root>/Ail_Cmd' */
    rtwdemo_roll_Y.Ail_Cmd = rtwdemo_roll_B.CmdLimit;
  } else {
    /* Outport: '<Root>/Ail_Cmd' incorporates:
     *  Constant: '<Root>/Zero'
     */
    rtwdemo_roll_Y.Ail_Cmd = rtwdemo_roll_P.Zero_Value_c;
  }

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

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

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

  /* block I/O */
  (void) memset(((void *) &rtwdemo_roll_B), 0,
                sizeof(B_rtwdemo_roll_T));

  /* 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 = rtwdemo_roll_P.LatchPhi_vinit;

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

  /* SystemInitialize for Atomic SubSystem: '<Root>/BasicRollMode' */
  /* InitializeConditions for DiscreteIntegrator: '<S1>/Integrator' */
  rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_IC;
  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 */',...
    'sizeof(DW_rtwdemo_roll_T));',1,1)
/* Model initialize function */
void rtwdemo_roll_initialize(void)
{
  /* Registration code */

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

  /* block I/O */
  (void) memset(((void *) &rtwdemo_roll_B), 0,
                sizeof(B_rtwdemo_roll_T));

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

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

rtwdemodbtype(file,...
    '/* SystemInitialize for Atomic SubSystem: ''<Root>/RollAngleReference'' */',...
    '/* Model terminate function */',1,0)
  /* SystemInitialize for Atomic SubSystem: '<Root>/RollAngleReference' */
  /* InitializeConditions for UnitDelay: '<S4>/FixPt Unit Delay1' */
  rtwdemo_roll_DW.FixPtUnitDelay1_DSTATE = rtwdemo_roll_P.LatchPhi_vinit;

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

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

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

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

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

В модели, упаковке интерфейса 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 9.203s

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

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;
  B_rtwdemo_roll_T *blockIO;
  ExtU_rtwdemo_roll_T *inputs;
  ExtY_rtwdemo_roll_T *outputs;
  DW_rtwdemo_roll_T *dwork;
};

/* Block parameters (default storage) */
extern P_rtwdemo_roll_T rtwdemo_roll_P;

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

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)

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

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_B =','rtwdemo_roll_M->outputs;',1,1)
  B_rtwdemo_roll_T *rtwdemo_roll_B = rtwdemo_roll_M->blockIO;
  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,'/* DiscreteIntegrator: ''<S1>/Integrator'' */',...
    '/* End of DiscreteIntegrator: ''<S1>/Integrator'' */',1,1)
  /* DiscreteIntegrator: '<S1>/Integrator' */
  if (rtwdemo_roll_B->NotEngaged_e ||
      (rtwdemo_roll_DW->Integrator_PrevResetState != 0)) {
    rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P.Integrator_IC;
  }

  if (rtwdemo_roll_DW->Integrator_DSTATE >= rtwdemo_roll_P.intLim) {
    rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P.intLim;
  } else if (rtwdemo_roll_DW->Integrator_DSTATE <=
             rtwdemo_roll_P.Integrator_LowerSat) {
    rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P.Integrator_LowerSat;
  }

  /* DiscreteIntegrator: '<S1>/Integrator' */
  rtwdemo_roll_B->Integrator = rtwdemo_roll_DW->Integrator_DSTATE;

  /* Saturate: '<S1>/DispLimit' */
  u0 = rtwdemo_roll_B->phiCmd;
  u1 = rtwdemo_roll_P.DispLimit_LowerSat;
  u2 = rtwdemo_roll_P.dispLim;
  if (u0 > u2) {
    /* Saturate: '<S1>/DispLimit' */
    rtwdemo_roll_B->DispLimit = u2;
  } else if (u0 < u1) {
    /* Saturate: '<S1>/DispLimit' */
    rtwdemo_roll_B->DispLimit = u1;
  } else {
    /* Saturate: '<S1>/DispLimit' */
    rtwdemo_roll_B->DispLimit = u0;
  }

  /* End of Saturate: '<S1>/DispLimit' */

  /* Sum: '<S1>/Sum' incorporates:
   *  Inport: '<Root>/Phi'
   */
  rtwdemo_roll_B->Sum = rtwdemo_roll_B->DispLimit - rtwdemo_roll_U->Phi;

  /* Gain: '<S1>/DispGain' */
  rtwdemo_roll_B->DispGain_f = rtwdemo_roll_P.dispGain * rtwdemo_roll_B->Sum;

  /* Saturate: '<S1>/RateLimit' */
  u0 = rtwdemo_roll_B->DispGain_f;
  u1 = rtwdemo_roll_P.RateLimit_LowerSat;
  u2 = rtwdemo_roll_P.rateLim;
  if (u0 > u2) {
    /* Saturate: '<S1>/RateLimit' */
    rtwdemo_roll_B->RateLimit = u2;
  } else if (u0 < u1) {
    /* Saturate: '<S1>/RateLimit' */
    rtwdemo_roll_B->RateLimit = u1;
  } else {
    /* Saturate: '<S1>/RateLimit' */
    rtwdemo_roll_B->RateLimit = u0;
  }

  /* End of Saturate: '<S1>/RateLimit' */

  /* Sum: '<S1>/Sum1' incorporates:
   *  Inport: '<Root>/Rate_FB'
   */
  rtwdemo_roll_B->Sum1 = rtwdemo_roll_B->RateLimit - rtwdemo_roll_U->Rate_FB;

  /* Gain: '<S1>/RateGain' */
  rtwdemo_roll_B->RateGain = rtwdemo_roll_P.rateGain * rtwdemo_roll_B->Sum1;

  /* Sum: '<S1>/Sum2' */
  rtwdemo_roll_B->Sum2 = rtwdemo_roll_B->Integrator + rtwdemo_roll_B->RateGain;

  /* Saturate: '<S1>/CmdLimit' */
  u0 = rtwdemo_roll_B->Sum2;
  u1 = rtwdemo_roll_P.CmdLimit_LowerSat;
  u2 = rtwdemo_roll_P.cmdLim;
  if (u0 > u2) {
    /* Saturate: '<S1>/CmdLimit' */
    rtwdemo_roll_B->CmdLimit = u2;
  } else if (u0 < u1) {
    /* Saturate: '<S1>/CmdLimit' */
    rtwdemo_roll_B->CmdLimit = u1;
  } else {
    /* Saturate: '<S1>/CmdLimit' */
    rtwdemo_roll_B->CmdLimit = u0;
  }

  /* End of Saturate: '<S1>/CmdLimit' */

  /* Gain: '<S1>/IntGain' */
  rtwdemo_roll_B->IntGain = rtwdemo_roll_P.intGain * rtwdemo_roll_B->Sum1;

  /* Update for DiscreteIntegrator: '<S1>/Integrator' */
  rtwdemo_roll_DW->Integrator_DSTATE += rtwdemo_roll_P.Integrator_gainval *
    rtwdemo_roll_B->IntGain;
  if (rtwdemo_roll_DW->Integrator_DSTATE >= rtwdemo_roll_P.intLim) {
    rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P.intLim;
  } else if (rtwdemo_roll_DW->Integrator_DSTATE <=
             rtwdemo_roll_P.Integrator_LowerSat) {
    rtwdemo_roll_DW->Integrator_DSTATE = rtwdemo_roll_P.Integrator_LowerSat;
  }

  rtwdemo_roll_DW->Integrator_PrevResetState = (int8_T)
    rtwdemo_roll_B->NotEngaged_e;

  /* End of Update for DiscreteIntegrator: '<S1>/Integrator' */
  /* End of Outputs for SubSystem: '<Root>/BasicRollMode' */

  /* Switch: '<Root>/EngSwitch' incorporates:
   *  Inport: '<Root>/AP_Eng'
   */
  if (rtwdemo_roll_U->AP_Eng) {
    /* Outport: '<Root>/Ail_Cmd' */
    rtwdemo_roll_Y->Ail_Cmd = rtwdemo_roll_B->CmdLimit;
  } else {
    /* Outport: '<Root>/Ail_Cmd' incorporates:
     *  Constant: '<Root>/Zero'
     */
    rtwdemo_roll_Y->Ail_Cmd = rtwdemo_roll_P.Zero_Value_c;
  }

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

/* Model initialize function */
void rtwdemo_roll_initialize(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)
{
  DW_rtwdemo_roll_T *rtwdemo_roll_DW = rtwdemo_roll_M->dwork;

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

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

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

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

/* Model terminate function */
void rtwdemo_roll_terminate(RT_MODEL_rtwdemo_roll_T * rtwdemo_roll_M)
{
  /* model code */
  rt_FREE(rtwdemo_roll_M->blockIO);
  rt_FREE(rtwdemo_roll_M->inputs);
  rt_FREE(rtwdemo_roll_M->outputs);
  rt_FREE(rtwdemo_roll_M->dwork);
  rt_FREE(rtwdemo_roll_M);
}

/* Model data allocation function */
RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)
{
  RT_MODEL_rtwdemo_roll_T *rtwdemo_roll_M;
  rtwdemo_roll_M = (RT_MODEL_rtwdemo_roll_T *) malloc(sizeof
    (RT_MODEL_rtwdemo_roll_T));
  if (rtwdemo_roll_M == NULL) {
    return NULL;
  }

  (void) memset((char *)rtwdemo_roll_M, 0,
                sizeof(RT_MODEL_rtwdemo_roll_T));

  /* block I/O */
  {
    B_rtwdemo_roll_T *b = (B_rtwdemo_roll_T *) malloc(sizeof(B_rtwdemo_roll_T));
    rt_VALIDATE_MEMORY(rtwdemo_roll_M,b);
    rtwdemo_roll_M->blockIO = (b);
  }

  /* states (dwork) */
  {
    DW_rtwdemo_roll_T *dwork = (DW_rtwdemo_roll_T *) malloc(sizeof
      (DW_rtwdemo_roll_T));
    rt_VALIDATE_MEMORY(rtwdemo_roll_M,dwork);
    rtwdemo_roll_M->dwork = (dwork);
  }

  /* external inputs */
  {
    ExtU_rtwdemo_roll_T *rtwdemo_roll_U = (ExtU_rtwdemo_roll_T *) malloc(sizeof
      (ExtU_rtwdemo_roll_T));
    rt_VALIDATE_MEMORY(rtwdemo_roll_M,rtwdemo_roll_U);
    rtwdemo_roll_M->inputs = (((ExtU_rtwdemo_roll_T *) rtwdemo_roll_U));
  }

  /* external outputs */
  {
    ExtY_rtwdemo_roll_T *rtwdemo_roll_Y = (ExtY_rtwdemo_roll_T *) malloc(sizeof
      (ExtY_rtwdemo_roll_T));
    rt_VALIDATE_MEMORY(rtwdemo_roll_M,rtwdemo_roll_Y);
    rtwdemo_roll_M->outputs = (rtwdemo_roll_Y);
  }

  {
    B_rtwdemo_roll_T *rtwdemo_roll_B = rtwdemo_roll_M->blockIO;
    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;

    /* block I/O */
    (void) memset(((void *) rtwdemo_roll_B), 0,
                  sizeof(B_rtwdemo_roll_T));

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

  return rtwdemo_roll_M;
}

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

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)

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

Устраните внутренние данные с оптимизацией генерации кода

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

set_param('rtwdemo_roll','DefaultParameterBehavior','Inlined',...
    'OptimizeBlockIOStorage','on',...
    'LocalBlockOutputs','on')

В этом примере, для более простого кода, упаковки интерфейса Code набора к Nonreusable function.

set_param('rtwdemo_roll','CodeInterfacePackaging','Nonreusable 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 8.078s

Теперь rtwdemo_roll.h не задает структуру для вводов и выводов блока. Для всех внутренних сигналов в модели, оптимизация или устраненное устройство хранения данных или созданные переменные локальной функции вместо глобальных полей структуры.

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

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,...
    '/* Block states (default storage) for system','} DW_rtwdemo_roll_T;',1,1)
/* Block states (default storage) for system '<Root>' */
typedef struct {
  real32_T FixPtUnitDelay1_DSTATE;     /* '<S4>/FixPt Unit Delay1' */
  real32_T Integrator_DSTATE;          /* '<S1>/Integrator' */
  int8_T Integrator_PrevResetState;    /* '<S1>/Integrator' */
} DW_rtwdemo_roll_T;

Код, сгенерированный для блока Discrete-Time Integrator теперь, хранит и выходные данные состояния только в структуре DWork.

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,'/* Update for DiscreteIntegrator: ''<S1>/Integrator''',...
    '/* End of Update for DiscreteIntegrator: ''<S1>/Integrator'' */',1,1)
  /* Update for DiscreteIntegrator: '<S1>/Integrator' incorporates:
   *  Gain: '<S1>/IntGain'
   */
  rtwdemo_roll_DW.Integrator_DSTATE += 0.5F * rtb_TKSwitch * 0.025F;
  if (rtwdemo_roll_DW.Integrator_DSTATE >= 5.0F) {
    rtwdemo_roll_DW.Integrator_DSTATE = 5.0F;
  } else if (rtwdemo_roll_DW.Integrator_DSTATE <= -5.0F) {
    rtwdemo_roll_DW.Integrator_DSTATE = -5.0F;
  }

  rtwdemo_roll_DW.Integrator_PrevResetState = (int8_T)rtb_NotEngaged_f;

Оптимизация также устранила устройство хранения данных для параметров блоков в модели. Например, в блоке Discrete-Time Integrator, Верхний предел насыщения и Более низкие предельные параметры насыщения установлены в intLim и -intLim. intLim Simulink.Parameter возразите, что хранит значение 5. В коде, сгенерированном для Интегратора Дискретного времени, этих параметров блоков и intLim появитесь как встроенные литеральные числа 5.0F и -5.0F.

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

Локальные переменные в сгенерированном коде

Когда вы выбираете оптимизацию Configuration Parameters> Enable local block outputs, генератор кода пытается дать к более эффективному коду путем представления внутренних сигналов как локальных переменных вместо полей глобальной структуры. Если память, использованная локальными переменными, рискует превышать стековое пространство, доступное на вашем целевом компьютере, рассмотрите указание на максимальный размер стека установкой Configuration Parameters> Maximum stack size (bytes). Для получения дополнительной информации смотрите размер стека Maximum (байты).

Внешний вид тестовых точек в сгенерированном коде

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

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

Если у вас есть Embedded Coder®:

  • Можно управлять представлением по умолчанию тестовых точек путем определения настроек генерации кода для категории Internal data данных в Коде, Сопоставляющем Редактор (см., Конфигурируют Генерацию кода По умолчанию для Данных (Embedded Coder)).

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

Виртуальные шины не появляются в сгенерированном коде, даже когда сопоставлено с тестовой точкой. Чтобы отобразить шину в сгенерированном коде, используйте невиртуальную шину или виртуальную шину, преобразованную в невиртуальную шину блоком Signal Conversion.

Внешний вид переменных рабочей области в сгенерированном коде

Workspace variables является переменными, которые вы используете, чтобы задать значения параметров блоков в модели. Переменные рабочей области включают числовые переменные MATLAB® и Simulink.Parameter объекты, которые вы храните в рабочей области, такой как базовое рабочее пространство, или в словаре данных.

Когда вы устанавливаете Default parameter behavior на Tunable, по умолчанию переменные рабочей области появляются в сгенерированном коде как настраиваемые поля глобальной структуры параметров. Если вы используете такую переменную, чтобы задать несколько значений параметров блоков, переменная появляется как одно поле глобальной структуры параметров. Код не создает несколько полей, чтобы представлять параметры блоков. Поэтому настройка значения поля во время выполнения кода изменяет математическое поведение модели таким же образом как настройка значения переменной MATLAB или объекта параметра в процессе моделирования.

Если у вас есть Embedded Coder, можно управлять представлением по умолчанию переменных рабочей области путем определения настроек генерации кода для категорий данных о параметре в Коде, Сопоставляющем Редактор (см., Конфигурируют Генерацию кода По умолчанию для Данных (Embedded Coder)).

  • Категория Model parameters применяется к переменным, которые вы храните в рабочем пространстве модели.

  • Категория External parameters применяется к переменным, которые вы храните в базовом рабочем пространстве или словаре данных.

Продвиньте внутренние данные интерфейс

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

Данные, которые можно продвинуть

В зависимости от повторной входимости сгенерированного кода, то есть, установка, которую вы выбираете для Code interface packaging, можно сконфигурировать каждый элемент данных в модели, чтобы участвовать в интерфейсе путем появления в коде как одна из этих сущностей:

  • Глобальный символ, такой как глобальная переменная или вызов специализированной функции

  • Формальный параметр (аргумент) сгенерированных функций точки входа

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

Категория данныхПоявитесь как глобальный символПоявитесь в качестве аргумента функции точки входа
Блок Inport или Outport корневого уровняТолько для неповторно используемой модели.Да.
Сигнал, соединяющий два блокаТолько для неповторно используемой модели.

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

В качестве альтернативы соедините сигнал с блоком Outport корневого уровня.

Состояние блокаТолько для неповторно используемой модели.Только для повторно используемой модели и только как поле структуры.
Хранилище данных, такое как блок Data Store MemoryДа.Только для повторно используемой модели и только как поле структуры.
Параметры блоков или объект параметра, такой как Simulink.ParameterДа.Только как поле структуры.

Алгоритм одно экземпляра

Для алгоритма одно экземпляра (вы устанавливаете Code interface packaging на Nonreusable function), примените классы памяти непосредственно к отдельным элементам данных при помощи Model Data Editor или Property Inspector. С непосредственно прикладным классом памяти элемент данных появляется в коде как глобальный символ, такой как глобальная переменная. Класс памяти также препятствует тому, чтобы оптимизация устранила устройство хранения данных для элемента данных.

Можно применить классы памяти к сигналам, состояниям блока и параметрам блоков. (Для параметров блоков вы применяете классы памяти косвенно через объекты параметра, такие как Simulink.Parameter). Однако для сигнала, рассмотрите соединение сигнала с блоком Outport на корневом уровне модели. Затем опционально, можно применить класс памяти к блоку. В блок-схеме блок Outport показывает, что сигнал представляет систему выход.

Для получения дополнительной информации о классах памяти, смотрите Настройку генерации кода C для Элементов Интерфейса модели.

Повторно используемый алгоритм

Для повторно используемого алгоритма (вы устанавливаете Code interface packaging на Reusable function), используйте различные методы, чтобы сконфигурировать элементы данных, чтобы появиться в коде как формальные параметры (аргументы) сгенерированных функций точки входа.

  • Для внутреннего сигнала непосредственно примените класс памяти Model default (см. Настройку генерации кода C для Элементов Интерфейса модели). Если вы имеете Embedded Coder, в Коде, Сопоставляющем Редактор, для категории Internal data, устанавливаете класс памяти по умолчанию на Default или к классу структурированного хранилища, который вы задаете в Словаре Embedded Coder (см., Создают Определения Кода для Использования в Редакторе Отображений Кода (Embedded Coder)). В качестве альтернативы сконфигурируйте сигнал как тестовую точку (см. Внешний вид Тестовых точек в Сгенерированном коде). По умолчанию сигнал появляется как поле одной из стандартных структур данных (см. Как Хранилища Сгенерированного кода Внутренний Сигнал, состояние и Данные о Параметре). Если вы не хотите сигнал появиться в производственном коде, используйте тестовую точку так, чтобы можно было позже выбрать параметр конфигурации модели Ignore test point signals.

    В качестве альтернативы соедините сигнал с блоком Outport на корневом уровне модели. Соединение сигнала с блоком Outport корневого уровня препятствует тому, чтобы оптимизация устранила сигнал из кода. Чтобы помочь с маршрутизацией сигнала в большой модели, используйте блоки From и Goto.

  • Для параметров блоков создайте объект параметра, такой как Simulink.Parameter и непосредственно примените класс памяти кроме Auto к объекту. Класс памяти препятствует тому, чтобы оптимизация встроила значение параметров в коде.

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

    Для получения информации о применении классов памяти смотрите Настройку генерации кода C для Элементов Интерфейса модели.

Управляйте представлением по умолчанию внутренних данных (Embedded Coder)

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

Управляйте размещением данных в памяти вставкой прагм

Используйте Код, Сопоставляющий Редактор, чтобы задать раздел memory по умолчанию для каждой категории данных, таких как состояния и сигналы (Internal data). В сгенерированном коде ваши пользовательские прагмы или другие художественные оформления окружают определения данных и объявления.

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

Для получения дополнительной информации смотрите Данные об Управлении и Функциональное Размещение в Памяти Вставкой Прагм (Embedded Coder).

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

Можно управлять некоторыми характеристиками стандартных структур данных. Для получения дополнительной информации смотрите Имена типов данных Управления в Сгенерированном коде (Embedded Coder).

Для дополнительного управления характеристиками структуры, такими как размещение в файлах сгенерированного кода, создают ваш собственный класс структурированного хранилища при помощи Словаря Embedded Coder. Затем примените класс памяти к категориям данных при помощи Кода, Сопоставляющего Редактор. Класс памяти удаляет данные из стандартных структур, создавая другие структуры, которыми можно более точно управлять. Для получения дополнительной информации о применении классов памяти по умолчанию к категориям данных, смотрите, Конфигурируют Генерацию кода По умолчанию для Данных (Embedded Coder). Для получения дополнительной информации о создании класса памяти, смотрите, Задают Классы памяти, Разделы Памяти и Шаблоны функций для Программной архитектуры (Embedded Coder).

Организуйте данные в структуры согласно субкомпонентам

  • В стандартных структурах данных, чтобы создать подструктуры, которые содержат данные для одно экземпляра (неповторно используемая) стандартная подпрограмма или субкомпонент, используют атомарную подсистему, чтобы инкапсулировать соответствующие блоки. В параметрах подсистемы, набор Function packaging к Reusable function. Для получения дополнительной информации смотрите, Генерируют Модульный Функциональный Код для Невиртуальных Подсистем (Embedded Coder).

    В качестве альтернативы инкапсулируйте блоки в модели и используйте блок Model. В модели, на которую ссылаются, набор Configuration Parameters> Model Referencing> Total number of instances allowed per top model к Multiple. Для получения дополнительной информации смотрите, Генерируют Код для Иерархии Модели - ссылки.

  • Создать отдельные, автономные структуры, которые содержат данные для мультиэкземпляра (повторно используемая) стандартная подпрограмма или субкомпонент, в модели, используют атомарную подсистему, чтобы инкапсулировать соответствующие блоки. В параметрах подсистемы, набор Function packaging к Nonreusable function и выберите Function with separate data. Для получения дополнительной информации смотрите, Генерируют Модульный Функциональный Код для Невиртуальных Подсистем (Embedded Coder).

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

Организуйте данные о сигнале и параметре в значимые, пользовательские структуры и подструктуры

Чтобы организовать произвольные сигналы и параметры в пользовательские структуры и подструктуры, создайте невиртуальные сигналы шины и структуры параметра. Опционально, чтобы препятствовать тому, чтобы оптимизация устранила данные из кода, установите класс памяти сигнала шины или структуры параметра к значению кроме Auto (настройка по умолчанию).

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

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

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

Чтобы заставить категорию внутренних данных появиться в сгенерированном коде как отдельные, неструктурированные глобальные переменные вместо полей стандартной структуры данных, примените неструктурированный класс памяти к категории данных при помощи Кода, Сопоставляющего Редактор. Например, примените класс памяти ExportedGlobal. Однако, если вы генерируете мультиэкземпляр, повторно используемый код путем установки параметра конфигурации Code interface packaging на значение кроме Nonreusable function, вы не можете использовать этот метод для некоторых категорий данных (см. Классы памяти и Повторно используемый, Модели Мультиэкземпляра и Компоненты).

Чтобы применить классы памяти по умолчанию к категориям данных при помощи Кода, Сопоставляющего Редактор, смотрите, Конфигурируют Генерацию кода По умолчанию для Данных (Embedded Coder). Чтобы выбрать класс памяти, смотрите, Выбирают Storage Class for Controlling Data Representation in Generated Code.

Похожие темы