Для использования кода, создаваемого из модели, следует вызвать сгенерированные функции точки входа, такие как 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)
Поскольку каждый вызов, выполняемый для функции точки входа, взаимодействует с отдельной структурой данных модели в реальном времени, можно избежать непреднамеренного взаимодействия между вызовами.
Для управления характеристиками интерфейса данных в сгенерированном коде см. раздел Управляющие данные и интерфейс функций в сгенерированном коде.