simulink可对生成的代码做深度定制化,主要从以下几个方面:
- 控制函数原型(function prototypes)
- 函数接口复用(reuse function interface)
- 数据存储管理(storage class & memory section)
- 函数模板(function templates)
下面一一说明:
控制函数原型(function prototypes)
默认设置下,3个入口函数和为以下形式

且输入输出和非内联变量会以全局结构体的形式被函数访问。

函数名管理
但我们可以对此进行管理:在模型的code mapping - c的界面中(序号1)点击function(序号2),我们可以在function name(序号3)处对3个入口函数的名字进行修改(图中已经做了修改),并且可以点击4修改model_step的函数原型(初始化函数和终止函数的原型不可修改,只能改函数名)。

我们点击上图4修改step函数的原型,在下图勾选3然后点击4会出现详细设置,如下图
1是step函数原型的预览
2是函数名
5是设置step函数的返回值,可以返回指针也可以返回变量
6是step函数的返回值和形参设置
7是初步校验

函数返回值管理
3处如果选择void,函数声明里的形参有一个指针,指向输出值。此时该step函数为无返回值(return),而生成了一个指针,指向本该输出的数据:静态变量FQF_arg_ETC_output_scaled



3处如果不选择void而是选择响应的信号标签(ETC_output_scaled),意思是:以数值方式返回计算结果(此时2出会改变)

代码如下,可着重对比一下”C return arguement“选项的影响,step函数的原型有变化:形参及返回值均变化。
extern void FQF_Step(real_T FQF_arg_pedal_scaled, real_T FQF_arg_angle_scaled, real_T *FQF_arg_ETC_output_scaled); // 选择void的代码
extern real_T FQF_Step(real_T FQF_arg_pedal_scaled, real_T FQF_arg_angle_scaled); // 选择信号标签(ETC_output_scaled)的代码

用return返回计算结果的值


函数形参管理
函数的形参也可以用指针传递,比如当输入信号为一个结构体时(vector),此时需要在形参的设置处选择为pointer即可。

总结一下:
- simulink仅允许用户在step函数上进行函数原型控制,但是可以对初始化函数和终止函数崇明ing
- 可以控制函数的形参和返回值(值和指针)
函数接口复用
一般来讲,函数的形参和返回值(输入和输出)都是以全局变量结构体的形式存在:


当需要对model_step函数进行多测调用时,全局变量结构体就会导致冲突:model_step.c中直接操作全局变量。

具体如下,下拉菜单选择“reusable function”和“individual arguments”。代码体现为:把全局变量改成独立的函数形参传进函数内部。(选择individual arguments时(code interface packaging会和控制函数原型里的configure arguments for steps function prototype冲突,需要取消configure arguments for steps function prototype的选择对勾))

代码如下,model_step形参里多了1个状态"RT_MODEL_piCtrl_prototype_sta_T *const piCtrl_prototype_start_M",2个输入“real_T piCtrl_prototype_start_U_pedal_scaled”、“real_T piCtrl_prototype_start_U_angle_scaled”,1个输出“real_T *piCtrl_prototype_start_Y_ETC_output_scaled”,此时该step函数就不是直接操作全局变量,而是操作函数内部变量(形参),不会出现数据冲突,此时函数便可复用。

model_step函数形参里的状态量的定义如下:

选择structure reference时

代码如下,1个状态“RT_MODEL_piCtrl_prototype_sta_T *const piCtrl_prototype_start_M”(同上),一个输入“ExtU_piCtrl_prototype_start_T *piCtrl_prototype_start_U”,1个输出“ExtY_piCtrl_prototype_start_T *piCtrl_prototype_start_Y”。

为何2个输入变成了1个输入?原因是把输入输入变成了结构体,2个输入信号被封装在一个结构体里。但本质是一样的,都是step函数对形参操作而不对全局变量操作。

选择为part of model data structure时,

代码如下,

model_step函数的形参超级简单,只有一个“RT_MODEL_piCtrl_prototype_sta_T *const piCtrl_prototype_start_M”。但是我们看下这个“piCtrl_prototype_start_M”里有什么。和model.c的赋值对比一下,其实本质也一样,把step函数对形参操作而不对全局变量操作,只不过函数接口的封装形式不同。

数据存储管理
下面这东西叫embedded coder dictionary,听起来有点像数据字典,用处也比较相似,用来管理data access formats,function templates,memory sections等。在1中点击2会弹出3,embedded coder dictionary中有3个主要界面:storage classes(很重要,数据字典必用)、function customization templates和memory section。其中storage classes和memory section配合使用,memory section用于精确管理变量的声明和定义,storage classes相当于对memory section进行了一次扩充和更多特性管理的封装。

storage classes可通过变量声明&定义对内存进行精确管理,此处也可定义关键字#pragma:

函数模板
上面说的embedded coder dictionary定义函数模板function templates,和C++里的函数模板不是一个意思,此处的函数模板有点类似于函数命名规则,见下图3,$R和N是命名规则缩写,鼠标放在上面就会弹出所代表的意思,比如代表模型名字等。

本文详细介绍Simulink如何通过定制函数原型、管理接口和数据存储来提升代码灵活性。涉及控制函数原型修改、返回值与形参设定,以及函数接口的复用策略,帮助用户避免全局变量冲突,实现代码高效复用和内存精准管理。
1万+

被折叠的 条评论
为什么被折叠?



