Simulink代码生成: Storage Class配置

之前一篇博客《Simulink代码生成: 信号线、参数配置》中,提及了一部分Storage Class(存储类型)的配置及其代码。本文更加详细地研究Storage Class中各个选项的含义以及生成的代码。

文章目录

  • 1 示例模型
  • 2 Storage Class配置及其代码
    • 2.1 Auto
    • 2.2 Model Default
    • 2.3 Exported Global
    • 2.4 Imported Extern
    • 2.5 Imported Extern Pointer
    • 2.5 Bitfield
    • 2.6 Volatile
    • 2.7 ExportToFile
    • 2.8 ImportFromFile
    • 2.9 FileScope
    • 2.10 Localization
    • 2.11 Struct
    • 2.12 GetSet
  • 3 总结

1 示例模型

首先打开Simulink,建立一个简单的具有输入、输出和Gain模块的模型。将输入信号线命名为Input1,并Resolve to Simulink Signal object,也就是左边的蓝色小叉子。
Simulink代码生成: Storage Class配置_第1张图片
然后在Matlab命令行输入:

>> Input1 = Simulink.Signal;

此时在Matlab工作区就会建立一个名为Input的信号对象。双击Input1,就可以编辑该对象,包括编辑Storage Class。
Simulink代码生成: Storage Class配置_第2张图片
将Data Type配置为single,然后本文开始研究Storage Class中的各个选项,以及对应生成的代码。

2 Storage Class配置及其代码

2.1 Auto

Storage Class的第一个选项就是Auto,也就是自动的意思。字面上看不出来自动的存储类型究竟是什么样,所以Ctrl + B生成代码看一下。
Simulink代码生成: Storage Class配置_第3张图片
观察生成的c文件可以看出,Input1是作为demo_U这个结构体变量的一个成员出现的。这个结构体的定义又是在demo.h中完成的,见下图。如果模型由多个输入,那么这个结构体中就会有多个一一对应的成员。
Simulink代码生成: Storage Class配置_第4张图片
这种Auto的方式一般是不会使用的。如果需要了解更多Auto配置的生成代码的机制,可以参考Matlab帮助文档《Standard Data Structures in the Generated Code》。

2.2 Model Default

将Storage Class选为Model Default后,会多出两个文本框可以填写。
Simulink代码生成: Storage Class配置_第5张图片
其中,Alias表示该存储对象的别名。也就是说,该信号无论在Simulink里面叫什么名字,生成代码的时候都会换成这个名字。Alignment表示数据对齐边界,但博主也并不是很了解,可以参考帮助文档。一般设为-1的默认值,生成代码的时候会采用最佳的对齐方式。

如果Alias和Alignment这两项默认不改,生成的代码就会和Auto一致。假设将Alias改为Input1_Alias,并生成代码,代码中所有原来的Input1,就会被替换成Input1_Alias,如下图。
Simulink代码生成: Storage Class配置_第6张图片

2.3 Exported Global

将Storage Class选为Exported Global。字面上意思是将其输出为全局变量。
Simulink代码生成: Storage Class配置_第7张图片
生成代码如下:
Simulink代码生成: Storage Class配置_第8张图片
这里可以看到,生成的代码直接把Input1这个变量定义出来了,而不象是之前的结构体。而且,定义Input1的时候是在模型对应的c文件内定义的。接着再打开demo.h头文件。
Simulink代码生成: Storage Class配置_第9张图片
可以看出,在demo.h中用extern关键字对Input1这个变量进行外部声明。也就是说,只要别的C文件包含了这个demo.h,就可以给Input1这个全局变量赋值。

这一点非常有价值,可以通过这个特性,在一个项目中用很多模块分别生成代码,分别编译代码,最后再链接到一起,从而实现了一个团队的分布式开发。而不需要将所有人的模型先集中成为一个大模型,再生成代码。

博主认为,Exported Global比较适合用于Outport的信号线,因为Inport的输入量一般是别的模型产生的,Outport是自己的模型产生的。

2.4 Imported Extern

将Storage Class选为Imported Extern。字面上意思是这个变量是外部引入的。
Simulink代码生成: Storage Class配置_第10张图片
生成代码如下:
Simulink代码生成: Storage Class配置_第11张图片
可以看出,step函数中用到了这个Input1,但是并没有在本文件中定义这个变量。

打开demo_private.h可以看到,在这个头文件中外部声明了Input1。也就是说,别的文件中定义了Input1。
Simulink代码生成: Storage Class配置_第12张图片
这个选项还是比较适用于输入端口的代码生成的。

2.5 Imported Extern Pointer

将Storage Class选为Imported Extern Pointer,字面上意思是引入外部指针。
Simulink代码生成: Storage Class配置_第13张图片
观察生成的step函数和private头文件可以发现,除了Input1是个指针,其余的和Imported Extern选项一样,这里不做赘述。
Simulink代码生成: Storage Class配置_第14张图片

2.5 Bitfield

这个确实不太懂,工作中也没遇到过。为了不误导大家,就不写了,只占个坑。如果有了解的朋友,还望不吝赐教哈。

2.6 Volatile

将Storage Class选为Volatile,字面上意思是可变的。选完以后,会多出3个用户参数可以填。HeaderFile指的是头文件,这里写headerfile.h,变量的外部声明就在这;DefinitionFile指的是C文件,这里写definitionfile.c,变量的定义在这个c文件中;Owner写chhttty(也就是博主的网名),也可以不写。
Simulink代码生成: Storage Class配置_第15张图片
生成代码如下:
Simulink代码生成: Storage Class配置_第16张图片
Simulink代码生成: Storage Class配置_第17张图片
可以看出改变了的定义和声明是在headerfile.h和definitionfile.c中的。这里要注意到,Input1这个变量是被volatile修饰的,也就是告诉编译器,这个变量的值要从内存中读取。

搞汽车软件开发的肯定会马上想到标定量的概念。但是标定量定义的时候,一般还需要加上一个const关键字,以免程序其他地方修改这个变量值。如果要生成const这个关键字,可以通过脚本替换,也可以通过自定义用户自己的storageclass类型来实现。

2.7 ExportToFile

将Storage Class选为ExportToFile,同时设定HeaderFile和DefinitionFile。
Simulink代码生成: Storage Class配置_第18张图片
这个选项和Exported Global相似,会定义这个变量。区别在于,定义的文件不是在demo.c本身,而是用户自己指定的文件HeaderFile和DefinitionFile中。DefinitionFile代码如下:
Simulink代码生成: Storage Class配置_第19张图片

2.8 ImportFromFile

将Storage Class选为ImportFromFile,同时设定HeaderFile。
Simulink代码生成: Storage Class配置_第20张图片
这个选项和ImportExtern类似,只是这里需要指定headerfile。生成代码如下:
Simulink代码生成: Storage Class配置_第21张图片
注意观察private头文件,这里和ImportExtern选项不同,不再是extern修饰Input1变量,而是直接用#include包含了我们指定的头文件。

2.9 FileScope

将Storage Class选为FileScope。这个选项会生成静态全局变量,只在本文件内调用。如果还是把之前的Input1变量设为FileScope,生成代码会报错,应该是和模块输入的性质有冲突。所以这里就用Gain模块的增益参数来演示。

将Gain模块的参数设为gain1,如下图。
Simulink代码生成: Storage Class配置_第22张图片
然后再Matlab命令行执行以下命令:

>> gain1=Simulink.Parameter;
>> gain1.Value = 3;

此时在Matlab工作区会生成gain1参数对象。将其Value值改为3,StorageClass改为FileScope,保存。
Simulink代码生成: Storage Class配置_第23张图片
然后生成代码如下:
Simulink代码生成: Storage Class配置_第24张图片
可以观察到,在本代码中,用static关键字修饰gain1这个参数,并将其赋值为3。也就是说,gain1是个静态的全局变量。

这就表明,gain1这个参数只有在demo.c这个c文件中才能用,其他文件用到了就会报错。

2.10 Localization

这个选项和ExportedGlobal的结果一样,有可能是模型太简单没有反映出区别。待进一步研究。

2.11 Struct

将Storage Class选为Sturct。这个选项生成的代码和默认的Auto类似,都会有一个结构体来包含成员Input1,只是这个结构体是用户自定义的,比如下图中定义为struct1。
Simulink代码生成: Storage Class配置_第25张图片
生成代码中可以看到自定义的结构体:
Simulink代码生成: Storage Class配置_第26张图片
不过博主确实想不到需要这么搞的需求,毕竟结构体这个不够简洁直观。

2.12 GetSet

将Storage Class选为GetSet。这里和之前都不同,代码会生成一个函数来获取输入值或者设置输出值。定义一个头文件headerfile.h,同时会默认GetFunction和SetFuction函数。
Simulink代码生成: Storage Class配置_第27张图片
生成代码如下:
Simulink代码生成: Storage Class配置_第28张图片
可以理解成从headerfile.h中调用get_Input1()这个函数。另外,也可以自定义get函数。

3 总结

Simulink的StorageClass配置选项很多,可以按照项目需求自己定义。

>>返回个人博客总目录

你可能感兴趣的:(Simulink代码生成)