生成的代码如何与环境交换数据
要使用从模型生成的代码,可以调用生成的入口点函数,例如一步
而且初始化
.调用这些函数的环境必须提供输入信号数据,并根据应用程序提供调度信息。生成的算法然后计算调用环境可以使用的输出数据。环境和算法可以通过全局变量或形式参数(参数)交换此数据。
输入和输出数据集和交换机制构成入口点函数的接口。当你理解默认接口和如何控制它们时,你可以:
编写调用生成代码的代码。
生成可以在单个应用程序中多次调用的可重用(可重入)代码。
将生成的代码与应用程序中的其他外部代码集成。
在模型中,根级轮廓尺寸而且外港块表示块算法的主要输入和输出。默认情况下,代码生成器将这些块聚合到存储输入和输出数据的标准结构中。
有关生成的代码如何存储不参与模型接口的内部数据的信息,请参见生成的代码如何存储内部信号,状态和参数数据.
生成代码中的数据接口
这个例子展示了生成的代码如何与环境交换数据。
探索范例模型
打开示例模型rtwdemo_roll
.
open_system (“rtwdemo_roll”)
在根级别,模型有许多导入块和一个输出端口块。
在模型中,集合>代码生成>系统目标文件来grt.tlc
.
set_param (“rtwdemo_roll”,“SystemTargetFile”,“grt.tlc”)
检查设置配置参数>代码生成>接口>代码接口封装.设置那种一次性的功能
表示生成的代码不可重用(不可重入)。
对于本例,要生成更简单的代码,请清除配置参数>代码生成>接口>高级参数> Mat-file logging.
set_param (“rtwdemo_roll”,“MatFileLogging”,“关闭”)
生成不可重用的代码
从模型生成代码。
rtwbuild (“rtwdemo_roll”)
成功完成:rtwdemo_roll的构建过程构建总结已构建的顶级模型目标:模型操作重建原因============================================================================================= rtwdemo_roll生成和编译的代码生成信息文件不存在。构建1个模型(0个模型已经更新)构建持续时间:0h 0m 12.947s
检查文件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_;rtwdemo_roll_t *const rtwdemo_roll_M = &rtwdemo_roll_M;
该文件rtwdemo_roll.h
声明这些结构变量。您的外部代码可以包括(# include
)这个文件,其总名为模型.h
在哪里模型
是模型的名称,以访问参与模型接口的数据。
在rtwdemo_roll.c
,模型一步
函数,它表示主要模型算法,使用无效
无效
接口(不带参数)。
rtwdemodbtype(文件,...'/*模型阶跃函数*/',“空白rtwdemo_roll_step(空白), 1, 1)
/*建模步长函数*/ void 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'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; }
由于无效
无效
接口和数据直接访问,功能不可重入。如果在应用程序中多次调用该函数,则每次调用都将输入和输出数据写入相同的全局结构变量,从而导致数据损坏和调用之间的无意交互。
模型初始化函数,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”,“可重用函数”)
从模型生成代码。
rtwbuild (“rtwdemo_roll”)
成功完成:rtwdemo_roll的构建过程构建总结已构建的顶级模型目标:模型操作重建原因============================================================================ rtwdemo_roll生成和编译的代码生成的代码已过期。构建1个模型(0个模型已经更新)构建时间:0h 0m 10.849秒
现在,在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)
/*建模步长函数*/ void 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->input;ExtY_rtwdemo_roll_T *rtwdemo_roll_Y = (ExtY_rtwdemo_roll_T *) rtwdemo_roll_M->outputs;
然后,为了访问存储在全局内存中的输入和输出数据,算法与这些局部变量进行交互。
rtwdemodbtype(文件,' if (rtwdemo_roll_U->AP_Eng) {',...' /* Switch结束:"/EngSwitch " */' , 1, 1)
if (rtwdemo_roll_U->AP_Eng) {/* Outputs for Atomic SubSystem: '/BasicRollMode' */ /*饱和:' /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;}} /*饱和结束:' /CmdLimit' */ /*输出子系统结束:' /BasicRollMode' */} else {/* Sum: ' /Sum2'合并:* Constant: ' /Zero' * 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)
因为您对入口点函数的每个调用都与单独的实时模型数据结构交互,所以您可以避免调用之间的无意交互。
配置数据接口
若要在生成的代码中控制数据接口的特征,请参见生成代码中的控制数据和函数接口.