Matlab的Simulink模型自动生成C语言代码

1 实验一

1.1 搭建框图

采用 Matlab 2018a 搭建仿真框图如下,命名为 ADD_Test.c

​ 图1 Simulink模型


1.2 初始设置

选择菜单栏 Simulink -> ModelConfiguration Parameters,按照下方所示设置参数,设置为固定步长,采用四阶龙格库塔方法解算微分方程,具体步长还可以在后期进行二次设置。

​ 图2 设置求解器参数

系统的目标文件选择为 ert.tlc,即采用嵌入形式的 C/C++代码生成,其结构更为简洁。生成的语言可选择 C 或者 C++

​ 图3 代码生成的参数设置

接口模块进行如下设置,需要选中 continuoustime 选项。至此,参数设置工作完毕,其余设置采用默认设置方式。

​ 图4 接口参数设置


1.3 代码生成

直接点击代码生成功能键,生成代码成功后会收到如图5所示的提示。此时,在示例文件 test.mdl 的目录下会出现名为 slprjtest_ert_rtw 的文件夹,如图6所示,包含了生成的 C 代码的相关文件。

​ 图5 代码生成成功提示

​ 图6 生成文件


1.4 代码应用

代码可在 Visual Studio2013 上运行,通过 文件 -> 打开 -> 项目/解决方案,找到 test_ert_rtw\msvc目录下的 test.sln 文件并添加,添加成功如下所示。

​ 图6 生成文件

如下所示,主文件经过初始化后,在 while 循环中调用 test_step()函数按单步执行,最后通过 test_terminate终止。在带有积分环节的模型中,还可以通过找到 test_M -> Timing.stepSize0 重新设置仿真步长。图7显示,每次给输入设置常值,经第五次调用后的输出结果。

​ 图7 代码测试


1.5 结论

采用Matlab和C混合编程,设计简单,结构清晰,修改方便,同时大大降低了编程失误带来的风险,为保证项目有效进行提供了保障。

如图所示,在matlab的工作界面输入 “mbuild -setup”,选择C++选项,再输入 “mex -setup”,选择C++选项,接着输入 deploytool命令。

​ 图8 MATLAB飞机本体方程动态链接库转换命令界面

接着会得到如下图的提示,选择Library Compiler选项,进入如图所示的Compiler界面,选择 .NETAssembly,添加相关脚本文件,把类的名字定义为airplane(自定义),确认后选择Package按钮进行打包,即可生成相应dll文件。

​ 图9 MATLAB飞机本体方程动态链接库转换Compiler界面

​ 图10 MATLAB飞机本体方程动态链接库转换操作界面

最后会跳出如下界面,生成的几个文件夹包含了调用到的dll文件。

​ 图11 MATLAB飞机本体方程动态链接库转换输出界面


2 实验二

2.1 创建Simulink模型

运行之后,通过Scope查看结果如下。

注意:我们要确保模型仿真运行没有问题。


2.2 将输入和需要的输出换成input和output模块


2.3 离散化模型

如果创建的Simulink模型种有连续模块,比如积分环节,那么一定要离散化,否则即使生成C代码也会报错。(为什么报错?先挖个坑)

点击设置

停止时间设置为inf,设置求解器,采样时间。

系统的目标文件选择为 ert.tlc,即采用嵌入形式的C/C++代码生成,其结构更为简洁。生成的语言可选择C或者C++。

代码生成 -> 接口

在模型资源管理器种查看定义的变量和配置的接口。

模型离散化器对simulink模型进行离散化,离散后的效果如下


2.4 生成C代码

首先,对建立的模型进行离散化

我们借助APP中的embedded coder工具生成C代码

进行编译

然后使用快速开始,按步骤进行生成C代码

其中,我们现在选择的C语言类型为PC格式,还可以选择ARM板格式

生成的C代码如下所示(/xxxx_ert_rtw文件夹下)


2.5 在VS2022上运行

点击文件->新建->从现有的代码中创建

打开ert_main.c这个文件

OK,我们在while循环中编写控制程序
(下面是写入while循环中的部分程序)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//定义文件地址和名字,指针
FILE* file_path = fopen("simulation.txt", "a+");
int i = 0;

while (i < 20000) {
/* Perform application tasks here */

if (i <= 20)
rtU.In1 = 0;
if (i > 20 && i <= 40)
rtU.In1 = 60;

/* Step the model */
PID_Test_step();
i++;

fprintf(file_path, "%f %f\n", rtU.In1, rtY.Out1); //写入
printf("%f %f\n", rtU.In1, rtY.Out1);
}
fclose(file_path);//关闭文件

保存的数据如下所示

我们看一下转成C代码运行的效果(将上面数据绘制图形)