主要内容

生成的代码如何与环境交换数据

要使用从模型生成的代码,可以调用生成的入口点函数,例如一步而且初始化.调用这些函数的环境必须提供输入信号数据,并根据应用程序提供调度信息。生成的算法然后计算调用环境可以使用的输出数据。环境和算法可以通过全局变量或形式参数(参数)交换这些数据。

输入和输出数据集以及交换机制构成了入口点函数的接口。当你理解了默认接口以及如何控制它们时,你可以:

  • 编写调用生成代码的代码。

  • 生成可在单个应用程序中多次调用的可重用(可重入)代码。

  • 将生成的代码与应用程序中的其他外部代码集成。

在模型中,根级轮廓尺寸而且外港块表示块算法的主要输入和输出。默认情况下,代码生成器将这些块聚合到存储输入和输出数据的标准结构中。

有关生成的代码如何存储不参与模型接口的内部数据的信息,请参见生成的代码如何存储内部信号,状态和参数数据

生成代码中的数据接口

这个例子展示了生成的代码如何与环境交换数据。

探索范例模型

打开示例模型rtwdemo_roll

open_system (“rtwdemo_roll”

在根级别,模型有许多import块和一个Outport块。

在模型中,设置>代码生成>系统目标文件grt.tlc

set_param (“rtwdemo_roll”“SystemTargetFile”“grt.tlc”

检查以下设置配置参数>代码生成>接口>代码接口封装.设置那种一次性的功能意味着生成的代码不可重用(不可重入)。

对于本例,要生成更简单的代码,请清除配置参数>代码生成>接口>高级参数> mat文件日志

set_param (“rtwdemo_roll”“MatFileLogging”“关闭”

生成不可重用的代码

从模型生成代码。

slbuild (“rtwdemo_roll”
# # #开始构建过程:rtwdemo_roll # # #成功完成构建过程:rtwdemo_roll模型建立目标:总结构建模型重建行动的理由  ============================================================================================== rtwdemo_roll代码生成和编译。代码生成信息文件不存在。构建1 / 1模型(0个模型已经更新)构建持续时间:0h 0m 10.478s

检查文件rtwdemo_roll.h.该文件定义了一个表示输入数据的结构类型和一个表示输出数据的类型。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.h”);rtwdemodbtype(文件,...'/*外部输入(默认存储的根输入信号)*/'...“}ExtY_rtwdemo_roll_T;”, 1, 1)
/*外部输入(根输入信号默认存储)*/ typedef struct {real32_T Phi;/* '<根>/Phi' */ real32_T Psi;/* '/Psi' */ real32_T Rate_FB;/* '/Rate_FB' */ real32_T TAS;/* '/TAS' */ boolean_T AP_Eng;/* '/AP_Eng' */ boolean_T HDG_Mode;/* '/HDG_Mode' */ real32_T HDG_Ref;/* '/HDG_Ref' */ real32_T Turn_Knob;/* '/Turn_Knob' */} ExtU_rtwdemo_roll_T;/*外部输出(根输出由默认存储的信号提供)*/ typedef struct {real32_T Ail_Cmd; /* '/Ail_Cmd' */ } ExtY_rtwdemo_roll_T;

每个字段对应于模型根级别的一个import或Outport块。每个字段的名称来源于块的名称。

文件还定义了结构类型实时模型数据结构,其单个字段存储一个运行时指示,指示生成的代码在执行期间是否遇到错误。

rtwdemodbtype(文件,/*实时模型数据结构*/...'/*块状态(默认存储)*/', 1,0)
/*实时模型数据结构*/ struct tag_RTM_rtwdemo_roll_T {const char_T *errorStatus;};

当您修改模型配置参数以适应您的应用程序时,该结构还可以包含与整个模型相关的其他数据,例如调度信息。

对于表示实时模型数据结构的结构类型,为文件rtwdemo_roll_types.h创建别名(类型定义),生成的代码稍后使用它来为结构分配内存。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll_types.h”);rtwdemodbtype(文件,'/* rtModel */'...“RT_MODEL_rtwdemo_roll_T;”, 1, 1)
/* rtModel的前向声明*/ typedef struct tag_RTM_rtwdemo_roll_T RT_MODEL_rtwdemo_roll_T;

使用这些结构类型,文件rtwdemo_roll.c定义(为其分配内存)全局结构变量,用于存储生成算法的输入和输出数据。该文件还定义了表示实时模型数据结构的变量和指向该结构的指针。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.c”);rtwdemodbtype(文件,...'/*外部输入(默认存储的根输入信号)*/'...“= &rtwdemo_roll_M_;”, 1, 1)
/*外部输入(默认存储的根输入信号)*/ ExtU_rtwdemo_roll_T rtwdemo_roll_U;/*外部输出(根输出由默认存储的信号提供)*/ ExtY_rtwdemo_roll_T rtwdemo_roll_Y;/*实时模型*/静态RT_MODEL_rtwdemo_roll_T rtwdemo_roll_M_;RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M = &rtwdemo_roll_M_;

该文件rtwdemo_roll.h声明这些结构变量。您的外部代码可以包括(# include)此文件,其通用名称为模型.h在哪里模型是模型的名称,用于访问参与模型接口的数据。

rtwdemo_roll.c,模型一步函数,表示主要模型算法,它使用无效无效接口(不带参数)。

rtwdemodbtype(文件,...'/*模型阶跃函数*/'“空白rtwdemo_roll_step(空白), 1, 1)
/* rtwdemo_roll_step(void)

在函数定义中,算法通过直接访问全局结构变量来读取输入数据和写入输出数据。例如,在算法的末尾,为的代码EngSwitch块的值AP_Eng字段(表示输入),并根据该值有条件地将常量值写入Ail_Cmd字段(表示输出)。

rtwdemodbtype(文件,'if (rtwdemo_roll_U.AP_Eng) {'“}”, 1, 1)
if (rtwdemo_roll_U.AP_Eng) {/* output for Atomic SubSystem: '/BasicRollMode' */ /*饱和:'/CmdLimit' */ if (rtwdemo_roll_Y. ap_eng) {/* output for Atomic SubSystem: '/BasicRollMode' */ /*饱和:'/CmdLimit' */ if (rtwdemo_roll_Y. ap_eng)Ail_Cmd > 15.0F) {/* Sum: '/Sum2'合并:* Outport: '/Ail_Cmd' */ rtwdemo_roll_Y。Ail_Cmd = 15.0F;} else if (rtwdemo_roll_Y.)Ail_Cmd< -15.0F) { /* Sum: '/Sum2' incorporates: * Outport: '/Ail_Cmd' */ rtwdemo_roll_Y.Ail_Cmd = -15.0F; } /* End of Saturate: '/CmdLimit' */ /* End of Outputs for SubSystem: '/BasicRollMode' */ } else { /* Sum: '/Sum2' incorporates: * Constant: '/Zero' * Outport: '/Ail_Cmd' */ rtwdemo_roll_Y.Ail_Cmd = 0.0F; } /* End of Switch: '/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: '/RollAngleReference' */ /* InitializeConditions for UnitDelay: '/FixPt Unit Delay1' */ rtwdemo_roll_DW.FixPtUnitDelay1_DSTATE = 0.0F; /* End of SystemInitialize for SubSystem: '/RollAngleReference' */ /* SystemInitialize for Atomic SubSystem: '/BasicRollMode' */ /* InitializeConditions for DiscreteIntegrator: '/Integrator' */ rtwdemo_roll_DW.Integrator_DSTATE = 0.0F; rtwdemo_roll_DW.Integrator_PrevResetState = 0; /* End of SystemInitialize for SubSystem: '/BasicRollMode' */ } /* Model terminate function */ void rtwdemo_roll_terminate(void) { /* (no terminate code required) */ }

由于无效无效接口和数据直接访问,功能不可重入。如果在应用程序中多次调用该函数,则每次调用都会将输入和输出数据读写到相同的全局结构变量,从而导致数据损坏和调用之间的无意交互。

模型初始化函数,rtwdemo_roll_initialize,将输入和输出数据初始化为零。该函数还初始化错误状态。该函数直接访问全局变量,这意味着该函数不可重入。

rtwdemodbtype(文件,/*模型初始化函数*/...“rtmSetErrorStatus (rtwdemo_roll_M (NULL));“, 1, 1)
/*模型初始化函数*/ void rtwdemo_roll_initialize(void){/*注册码*/ /*初始化错误状态*/ rtmSetErrorStatus(rtwdemo_roll_M, (NULL));
rtwdemodbtype(文件,' /*外部输入'...'/* SystemInitialize for Atomic SubSystem:', 1,0)
* (void)memset(&rtwdemo_roll_U, 0, sizeof(ExtU_rtwdemo_roll_T));/*外部输出*/ rtwdemo_roll_Y。Ail_Cmd = 0.0F;

生成可重用代码

您可以将生成的代码配置为可重入的,这意味着您可以在应用程序中多次调用入口点函数。使用这种配置,入口点函数不是直接访问全局变量,而是通过正式参数(指针参数)交换输入、输出和其他模型数据。使用这些指针参数,每个调用都可以读取输入并将输出写入一组单独的全局变量,从而防止调用之间的无意交互。

在模型中,设置配置参数>代码生成>接口>代码接口封装可重用的功能

set_param (“rtwdemo_roll”“CodeInterfacePackaging”“可重用函数”

从模型生成代码。

slbuild (“rtwdemo_roll”
# # #开始构建过程:rtwdemo_roll # # #成功完成构建过程:rtwdemo_roll模型建立目标:总结构建模型重建行动的理由  ============================================================================= rtwdemo_roll代码生成和编译。生成的代码已经过时。构建1 / 1模型(0个模型已经更新)构建时间:0h 0m 7.2004s

现在,在rtwdemo_roll.h时,实时模型数据结构包含指向错误指示的指针、输入数据、输出数据以及以DWork子结构(例如,存储块状态,例如离散时间积分器块的状态)。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.h”);rtwdemodbtype(文件,/*实时模型数据结构*/...'/*依赖源文件的外部数据声明*/', 1,0)
/*实时模型数据结构*/ struct tag_RTM_rtwdemo_roll_T {const char_T *errorStatus;ExtU_rtwdemo_roll_T *输入;ExtY_rtwdemo_roll_T *输出;DW_rtwdemo_roll_T * dwork;};

要在应用程序中多次调用生成的代码,您的代码必须为每次调用分配实时模型数据结构的内存。该文件rtwdemo_roll.c定义一个专门的函数,该函数为新的实时模型数据结构分配内存并返回指向该结构的指针。该函数还为模型数据结构中的字段所指向的子结构分配内存,例如输入和输出结构。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.c”);rtwdemodbtype(文件,/*模型数据分配函数*/'...“RT_MODEL_rtwdemo_roll_T * rtwdemo_roll(空白), 1, 1)
/*模型数据分配函数*/ RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)

rtwdemo_roll.c,模型一步函数接受表示实时模型数据结构的参数。

文件= fullfile(“rtwdemo_roll_grt_rtw”“rtwdemo_roll.c”);rtwdemodbtype(文件,...'/*模型阶跃函数*/'“空白rtwdemo_roll_step”, 1, 1)
/* rtwdemo_roll_step(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

在函数定义中,算法首先从实时模型数据结构中提取每个指针到一个局部变量中。

rtwdemodbtype(文件,...‘* rtwdemo_roll_DW = '“rtwdemo_roll_M - >输出;”, 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->输入;ExtY_rtwdemo_roll_T *rtwdemo_roll_Y = (ExtY_rtwdemo_roll_T *) rtwdemo_roll_M->输出;

然后,为了访问存储在全局内存中的输入和输出数据,算法与这些局部变量进行交互。

rtwdemodbtype(文件,' if (rtwdemo_roll_U->AP_Eng) {'...' /* End of Switch: " /EngSwitch " */', 1, 1)
if (rtwdemo_roll_U->AP_Eng) {/* Outputs for Atomic SubSystem: '/BasicRollMode' */ /* Saturate: '/CmdLimit' */ if (rtwdemo_roll_Y->Ail_Cmd > 15.0F) {/* Sum: '/Sum2': * Outport: '/Ail_Cmd' */ rtwdemo_roll_Y->Ail_Cmd = 15.0F;} else if (rtwdemo_roll_Y->Ail_Cmd < -15.0 f) {/* Sum: '/Sum2'合并:* Outport: '/Ail_Cmd' */ rtwdemo_roll_Y->Ail_Cmd = -15.0 f;} /* End of Saturate: '/CmdLimit' */ /* End of Outputs for SubSystem: '<根>/BasicRollMode' */} else {/* Sum: '/Sum2'合并:* Constant: '<根>/ 0 ' * Outport: '<根>/Ail_Cmd' */ rtwdemo_roll_Y->Ail_Cmd = 0.0F;}

类似地,模型初始化函数接受实时模型数据结构作为参数。

rtwdemodbtype(文件,.../*模型初始化函数*/“空白rtwdemo_roll_initialize”, 1, 1)
/*模型初始化函数*/ void rtwdemo_roll_initialize(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

由于对入口点函数的每个调用都与单独的实时模型数据结构交互,因此可以避免调用之间的无意交互。

配置数据接口

若要在生成的代码中控制数据接口的特征,请参见生成代码中的控制数据和函数接口

相关的话题