Simulink代码生成:通过Legacy Code Tool集成C函数
本文通过一个例程来简述如何使用Legacy Code Tool将外部C函数集成到Simulink模型中。文章目录1 问题引入2 编译器安装3 Legacy Code Tool简单示例3.1 创建C文件和头文件3.2 通过LCT生成S-function模块3.3 模型仿真3.4 代码生成4 总结1 问题引入假设一个公司在旧的项目中,没有通过Simulink建模并生成代码,而是纯手写的C代码。在新的项
本文通过一个例程来简述如何使用Legacy Code Tool将外部C函数集成到Simulink模型中。
1 问题引入
假设一个公司在旧的项目中,没有通过Simulink建模并生成代码,而是纯手写的C代码。在新的项目中应用了Matlab的这一套工具链进行MBD开发,想要在模型中直接调用以前写的C函数可以吗?
答案是肯定的。很多工程师会首先想到通过S-function去完成。博主想介绍一种更加简便的方法——Legacy Code Tool,把已经写好的C函数集成到Simulink模型中。现有的C代码中的函数将会作为一个Simulink模块进行仿真以及生成代码。
其实Legacy Code Tool背后的机制也是通过S-Function实现,但是LCT可以直接生成.mexw64文件和S-Function代码,而不需要工程师手动创建。
2 编译器安装
由于集成C函数的过程中涉及到了C代码的编译,所以必须在Matlab中安装一个MingW64编译器,方法如下。
2)点击右侧的Download下载安装文件mingw.mlpkginstall。
3)在Matlab中打开这个安装文件,就会自动安装。
4)安装完成后,在Matlab命令行窗口输入mex -setup,就会显示MinGW64编译器信息如下:
这样就算是安装完成了。如果安装不成功就会报错。
3 Legacy Code Tool简单示例
本章节通过一个简单的例程来演示通过LCT集成C函数的方法。
3.1 创建C文件和头文件
既然是集成C函数,那么必须得要有个C文件和头文件才行。
1)首先在Matlab当前文件夹中新建一个gougu_lct.c和gougu_lct.h文件。
2)打开C文件gougu_lct.c,在其中写入如下代码,包含一个计算勾股定理的函数。
#include <math.h>
#include "gougu_lct.h"
float gougu_lct(float* a, float* b)
{
float c;
c = sqrt((pow(*a,2) + pow(*b,2)));
return c;
}
3)打开头文件gougu_lct.h,写入函数的声明。
float gougu_lct(float* a, float* b);
3.2 通过LCT生成S-function模块
1)在Matlab命令行运行legacy_code函数来初始化一个LCT结构体def,该结构体中包含LCT的一些属性信息。
>> def = legacy_code('initialize')
def =
包含以下字段的 struct:
SFunctionName: ''
InitializeConditionsFcnSpec: ''
OutputFcnSpec: ''
StartFcnSpec: ''
TerminateFcnSpec: ''
HeaderFiles: {}
SourceFiles: {}
HostLibFiles: {}
TargetLibFiles: {}
IncPaths: {}
SrcPaths: {}
LibPaths: {}
SampleTime: 'inherited'
Options: [1×1 struct]
2)接下来为这个结构体指定一些具体的属性值
>> def.SFunctionName = 'gougu_lct_sfcn';
>> def.HeaderFiles = {'gougu_lct.h'};
>> def.SourceFiles = {'gougu_lct.c'};
>> def.IncPaths = {'E:\学习\博客\Simulink代码生成\LCF'};
>> def.SrcPaths = def.IncPaths;
其中,各个属性的意思如下:
属性名称 | 含义 |
---|---|
def.SFunctionName | S-function的名字,也就是对应的模块名 |
def.HeaderFiles | 头文件名称,要用单元数组 |
def.SourceFiles | 源文件名称,要用单元数组 |
def.IncPaths | 头文件路径,这个根据自己放的路径来写,不要照搬博主的 |
def.SrcPaths | 源文件路径,这里和头文件路径相同 |
3)指定OutputFcnSpec,该属性是一个字符串,通过一定的书写规律表现出C函数和对应的S-Function(也就是最后的Simulink模块)之间的输入、输出映射关系。
>> def.OutputFcnSpec = 'single y1 = gougu_lct(single u1[1],single u2[1])';
这里做一些简单解释:
字符 | 含义 |
---|---|
single y1 | 表示模块的输出y1是single类型,对应C函数返回的变量c |
gougu_lct | C代码中的函数名 |
single u1[1] | u1表示第1个输入参数,对应C函数的第1个参数,类型为single |
single u2[1] | u2表示第2个输入参数,对应C函数的第2个参数,类型为single |
需要注意一点,参数个数不同、返回个数不同、类型不同都会影响OutputFcnSpec字符串的写法,具体写法可以参照帮助文档Integrate C Functions Using Legacy Code Tool。
4)通过legacy_code函数生成S-function源文件,在Matlab命令行运行如下指令。
>> legacy_code('sfcn_cmex_generate',def);
运行完成后会在Matlba当前路径下生成gougu_lct_sfcn.c这个S-function源文件。
5)通过legacy_code函数编译这个S-function源文件,在Matlab命令行运行如下指令。
>> legacy_code('compile',def);
然后,Matlab命令窗口会显示一些编译信息。
同时,会在当前路径生成gougu_lct_sfcn.mexw64文件。
6)通过legacy_code函数在一个新的Simulink窗口中生成S-function模块,该模块拥有C函数的功能。在Matlab命令行运行如下指令。
>> legacy_code('slblock_generate',def);
弹出的Simulink模型如图所示。
3.3 模型仿真
1)给模型加上输入常量,和输出display模块,并将常量设置为3和4.
2)由于C函数中输入输出是浮点型,并且OutputFcnSpec属性中也指定了single类型,所以要把输入的Constant常量的类型都改为single。
3)Ctrl + D更新模型,就会看到输出显示的数值是5,符合勾股定理的结果。
同时注意到,输入输出的类型都是single。
3.4 代码生成
1)通过legacy_code函数生成tlc文件,为后面的代码生成做准备。在Matlab命令行运行如下指令。
>> legacy_code('sfcn_tlc_generate',def);
运行后,Matlab当前路径会生成gougu_lct_sfcn.tlc文件。
2)回到模型,将输入输出替换成Inport和Outport,并配置好Embedded Coder代码生成。
3)Ctrl + B生成代码。生成代码成功后,可以在step函数中看到对勾股定理函数的调用。
在demo.h头文件中也包含了gougu_lct.h头文件。
在后面编译软件的时候,不要忘记把gougu_lct.c和gougu_lct.h加进去一起编译。
4 总结
本文只是演示了一个使用LCT的基本方法,展示了一个完整的流程。实际项目中可能会遇上更多的问题需要想办法解决。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)