概述
浏览模型示例
打开模型示例 rtwdemo_roll。
open_system('rtwdemo_roll')
该模型包含不连接到根级别 Inport 或 Outport 模块的内部信号。某些信号具有名称,例如 phiCmd 信号。
该模型还包含一些维护状态数据的模块。例如,在 BasicRollMode 子系统中,标记为 Integrator 的 Discrete-Time Integrator 模块用于维护状态。
在模型中,将 Configuration Parameters > Code Generation > System target file 设置为 grt.tlc。
set_param('rtwdemo_roll','SystemTargetFile','grt.tlc')
检查 Configuration Parameters > Code Generation > Interface > Code interface packaging 的设置。设置 Nonreusable function 表示生成的代码不可重用(可重入)。
对于此示例,通过清除 Configuration Parameters > Code Generation > Interface > Advanced parameters > Mat-file logging 生成更简单的代码。
set_param('rtwdemo_roll','MatFileLogging','off')
生成不可重用的代码
设置以下配置参数:
将 Default parameter behavior 设置为 Tunable。
清除 Signal storage reuse。
set_param('rtwdemo_roll','DefaultParameterBehavior','Tunable',...
'OptimizeBlockIOStorage','off')
从模型中生成代码。
rtwbuild('rtwdemo_roll')
### Starting build procedure for: rtwdemo_roll
### Successful completion of build procedure for: rtwdemo_roll
文件 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; /* '/ModeSwitch' */
real32_T Abs; /* '/Abs' */
real32_T FixPtUnitDelay1; /* '/FixPt Unit Delay1' */
real32_T Xnew; /* '/Enable' */
real32_T TKSwitch; /* '/TKSwitch' */
real32_T RefSwitch; /* '/RefSwitch' */
real32_T Integrator; /* '/Integrator' */
real32_T DispLimit; /* '/DispLimit' */
real32_T Sum; /* '/Sum' */
real32_T DispGain; /* '/DispGain' */
real32_T RateLimit; /* '/RateLimit' */
real32_T Sum1; /* '/Sum1' */
real32_T RateGain; /* '/RateGain' */
real32_T Sum2; /* '/Sum2' */
real32_T CmdLimit; /* '/CmdLimit' */
real32_T IntGain; /* '/IntGain' */
real32_T hdgError; /* '/Sum' */
real32_T DispGain_a; /* '/DispGain' */
real32_T Product; /* '/Product' */
boolean_T NotEngaged; /* '/NotEngaged' */
boolean_T TKThreshold; /* '/TKThreshold' */
boolean_T RefThreshold2; /* '/RefThreshold2' */
boolean_T RefThreshold1; /* '/RefThreshold1' */
boolean_T Or; /* '/Or' */
boolean_T NotEngaged_e; /* '/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 '' */
typedef struct {
real32_T FixPtUnitDelay1_DSTATE; /* '/FixPt Unit Delay1' */
real32_T Integrator_DSTATE; /* '/Integrator' */
int8_T Integrator_PrevResetState; /* '/Integrator' */
} DW_rtwdemo_roll_T;
该文件定义一种表示参数数据的结构体类型。模型中的每个可调模块参数(例如 Gain 模块的 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 */
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: ''/Integrator'' *',...
'/* End of DiscreteIntegrator: ''/Integrator'' */',1,1)
/* DiscreteIntegrator: '/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;
}
}
rtwdemo_roll_B.Integrator = rtwdemo_roll_DW.Integrator_DSTATE;
由于存在 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: ''/RollAngleReference'' */',...
'/* Model terminate function */',1,0)
/* SystemInitialize for Atomic SubSystem: '/RollAngleReference' */
/* InitializeConditions for UnitDelay: '/FixPt Unit Delay1' */
rtwdemo_roll_DW.FixPtUnitDelay1_DSTATE = rtwdemo_roll_P.LatchPhi_vinit;
/* End of SystemInitialize for SubSystem: '/RollAngleReference' */
/* SystemInitialize for Atomic SubSystem: '/BasicRollMode' */
/* InitializeConditions for DiscreteIntegrator: '/Integrator' */
rtwdemo_roll_DW.Integrator_DSTATE = rtwdemo_roll_P.Integrator_IC;
rtwdemo_roll_DW.Integrator_PrevResetState = 0;
/* End of SystemInitialize for SubSystem: '/BasicRollMode' */
}
生成可重用的代码
您可以将生成的代码配置为可重入代码,这意味着您可以在一个应用程序中多次调用入口函数。使用此配置时,入口函数并不直接访问全局变量,而是通过形参(指针参数)接受内部数据。通过使用这些指针参数,每次调用都可以在一组单独的全局变量中维护内部数据,从而防止各次调用之间出现意外的交互。
在模型中,将 Configuration Parameters > Code Generation > Interface > Code interface packaging 设置为 Reusable function。
set_param('rtwdemo_roll','CodeInterfacePackaging','Reusable function')
从模型中生成代码。
rtwbuild('rtwdemo_roll')
### Starting build procedure for: rtwdemo_roll
### Successful completion of build procedure for: rtwdemo_roll
现在,在 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 = ((B_rtwdemo_roll_T *)
rtwdemo_roll_M->blockIO);
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,'/* DiscreteIntegrator: ''/Integrator'' */',...
'/* End of DiscreteIntegrator: ''/Integrator'' */',1,1)
/* DiscreteIntegrator: '/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;
}
}
rtwdemo_roll_B->Integrator = rtwdemo_roll_DW->Integrator_DSTATE;
同样,模型初始化函数接受实时模型数据结构体作为参数。
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)
由于您对入口函数的每次调用都与一个单独的实时模型数据结构体交互,因此可以避免各次调用之间发生意外交互。
使用代码生成优化消除内部数据
为了获得消耗更少内存的更高效代码,请选择优化,例如您在前面清除了的 Default parameter behavior。
set_param('rtwdemo_roll','DefaultParameterBehavior','Inlined',...
'OptimizeBlockIOStorage','on',...
'LocalBlockOutputs','on')
在此示例中,为了获得更简单的代码,请将 Code interface packaging 设置为 Nonreusable function。
set_param('rtwdemo_roll','CodeInterfacePackaging','Nonreusable function')
从模型中生成代码。
rtwbuild('rtwdemo_roll')
### Starting build procedure for: rtwdemo_roll
### Successful completion of build procedure for: rtwdemo_roll
现在,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 '' */
typedef struct {
real32_T FixPtUnitDelay1_DSTATE; /* '/FixPt Unit Delay1' */
real32_T Integrator_DSTATE; /* '/Integrator' */
int8_T Integrator_PrevResetState; /* '/Integrator' */
} DW_rtwdemo_roll_T;
现在,为 Discrete-Time Integrator 模块生成的代码仅在 DWork 结构体中存储状态和输出数据。
file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,'/* Update for DiscreteIntegrator: ''/Integrator''',...
'/* End of Update for DiscreteIntegrator: ''/Integrator'' */',1,1)
/* Update for DiscreteIntegrator: '/Integrator' incorporates:
* Gain: '/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 模块中,Upper saturation limit 和 Lower saturation limit 参数设置为 intLim 和 -intLim。intLim 是 Simulink.Parameter 对象,用于存储值 5。在为 Discrete-Time Integrator 生成的代码中,这些模块参数和 intLim 显示为内联字面数字 5.0F 和 -5.0F。
如果模型包含代码生成器不能直接内联的参数(例如数组参数),则代码会定义表示该数据的结构体类型。此常量参数结构体使用 const 存储类型限定符,因此某些编译工具链可以进一步优化程序集代码。
最后
以上就是现代苗条为你收集整理的matlab 生成信号文件,生成的代码如何存储内部信号、状态和参数数据的全部内容,希望文章能够帮你解决matlab 生成信号文件,生成的代码如何存储内部信号、状态和参数数据所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复