生成代码是基于模型设计的重要环节。在工作中经常需要手动生成一下代码来验证一些简单的问题,譬如想知道某种配置或者某种模型会生成什么形式的代码。
本文会结合一个简单的模型,描述生成嵌入式代码的最简配置流程。同时简要分析在Simulink默认配置下所生成的代码。
不同版本的Matlab生成的代码可能有少许区别,本文基于Matlab2018a环境。
首先打开Simulink,随意创建一个简单的模型,如下图。
一般控制策略的模型都会包括输入输出端口和内部的控制逻辑。这里建立的控制逻辑比较简单,只是把输入信号放大两倍再输出,在C代码中对应的就是简单的乘以2。
除此以外先不用对模块进行配置,观察在默认配置下,生成的代码是什么形式。
1.Ctrl+E打开模型的配置窗口
2.点击左侧的Solver,右侧Type选为Fixed-step,Solver选为discrete。这是因为必须是离散的求解器才能用Embedded Coder生成代码。
3.点击左侧的Code Generation,把System target file选为Embedded Coder。这么配置是告诉Simulink要生成生成嵌入式C代码。
4.点击Report,勾选Create code generation report和Open report automatically。这样,在生成完毕代码后会自动打开报告。最后点击OK即可完成配置。
5.Ctrl+B生成代码,会在Matlab当前工作路径下生成。代码生成完毕后自动弹出如下报告,可以通过点击左侧的目录或者c文件/头文件名,查看代码。
首先,会生成一个ert_main.c的C文件。该文件含有一个主函数,调用模型的初始化函数和step函数。
这个主函数其实完全没有必要,因为项目团队中一般会为底层配置好操作系统和任务调度,而不需要用Simulink生成。可以通过配置Simulink不生成这个主函数,以减少生成代码所用的时间。
头文件中首先是宏定义。然后通过结构体定义了输入输出变量类型,以及声明模型的初始化函数,step函数等。
Embedded Coder生成的C文件十分重要,它和Simulink模型中的算法紧密相关。下面详细描述C文件的内容。
代码中默认生成了大量的注释,可以很好的帮助我们读懂代码各个部分的作用,或者关联到模型中对应的模块。
注释的生成也可以在Simulink自定义配置。
接下来会定义变量,对应着模型最外层的输入输出模块。由于输入输出没有经过任何特殊配置,生成代码的时候就会按照默认的结构体的方式定义。
后续会研究如何配置输入输出以适应软件集成的需求。
step函数反映了模型的策略,完全和模型相对应。通常如果想验证某种模型生成代码的样子,只要通过查看step函数的内容即可。
后续研究代码生成的博客将主要分析step函数的内容。
初始化函数中包含了变量初始化和错误状态监测函数。
关于零初始化,可以通过勾选Data Initialization中的Remove root level I/O zero initialization取消生成。
关于这个rtmSetErrorStatus函数,其实没什么用处。可以通过勾选Remove error status field in real-time model data structure不生成它。
Code Generation过程不仅仅生成了C文件和头文件,还“顺便”执行了一下makefile,把代码编译成了可执行文件。
其实并不需要做这一步,因为所有模块生成代码后会和底层软件、手写代码等一起集成,多了这么一步反而会花费更多时间生成代码。通过勾选Generate code only可以不编译。
本文只是通过简单的配置来生成代码样例,这样的代码完全没法拿去和其他代码集成编译软件,还需要更多的配置才行。后面会在此基础上,讨论更多的代码生成配置,包括如何和底层代码交互,如何生成适合某个硬件的代码,如何优化代码等。
>>返回个人博客总目录