Чтобы использовать код, который вы генерируете из модели, вы вызываете сгенерированные функции точки входа, такие как 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')
Сгенерируйте код одноразового использования
Сгенерируйте код из модели.
rtwbuild('rtwdemo_roll')
### Starting build procedure for model: rtwdemo_roll ### Successful completion of build procedure for model: rtwdemo_roll
Осмотрите файл 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 */ 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; }
Из-за интерфейса 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')
Сгенерируйте код из модели.
rtwbuild('rtwdemo_roll')
### Starting build procedure for model: rtwdemo_roll ### Successful completion of build procedure for model: rtwdemo_roll
Теперь, в 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 = ((DW_rtwdemo_roll_T *) 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)
Поскольку каждый вызов, который вы выполняете к функции точки входа, взаимодействует с отдельной структурой данных модели реального времени, вы избегаете неумышленного взаимодействия между вызовами.
Чтобы управлять характеристиками интерфейса данных в сгенерированном коде, смотрите Данные об Управлении и Функциональный Интерфейс в Сгенерированном коде.