Matlab/Simulink自动生成C代码实验

article/2025/11/9 16:31:01

目录

0. 概要

1. Matlab /Simulink/Embedded Coder关系与区别

2. 搭建Simulink模型及仿真

2.1 搭建模型

 2.2 仿真

3. 生成代码

 3.1 求解器设置为定步长

3.2 安装 MinGW-w64 编译器

 3.3 调出Simulink Coder

 4. 工具都生成了啥呢?


0. 概要

        Matlab网站提供了很多关于如何使用Coder自动生成代码的教程,也有很多相关的博客或者视频,但是“纸上得来终觉浅,绝知此事要躬行”,光看不练终究是如隔靴搔痒,不知所云。

        本文从搭建一个simulink模型开始,到生成代码并进行生成的C模型与原simulink模型的一致性验证,走完一个最小完整流程。希望对基于simulink模型自动生成C代码感兴趣的小伙伴们能有所帮助。

        以下实验用的Matlab-2021b版本。

1. Matlab /Simulink/Embedded Coder关系与区别

ref1: Difference between Simulink Coder and Embedded Coder - (mathworks.cn)

ref2: Difference between Simulink Coder, Embedded Coder and Matlab Coder - (mathworks.cn) 

ref3: Welcome to the Coders! » Guy on Simulink - MATLAB & Simulink (mathworks.com) 

MATLAB Coder is used to generate ANSI C/C++ code from MATLAB and is a pre-requisite for Simulink Coder and Embedded Coder. Simulink Coder does the same thing, but from Simulink. Embedded Coder allows to optimize/customize the code generated by MATLAB Coder and Simulink Coder for production use.

首先,MATLAB Coder是Simulink Coder和Embedded Coder的基础。

Simulink Coder以前称为Real-Time Workshop,所以生成的代码存放目录等名称中可以看到的_rtw后缀名就源于此。

Both Simulink Coder generate C code from Simulink models, and both of them can put that C code in a C++ wrapper to be effectively integrated with other C++ code.

The main difference between these products is:

  • Simulink Coder generates code with the purpose of the model being able to run standalone without a MATLAB license, or to verify the behavior of the generated code on a host computer.
  • Embedded Coder generates readable code that can be much more finely configured, customized, and optimized through various settings and constructs. Embedded Coder also provides support for automatically building the generated code on embedded systems (hence its name).

        Simulink Coder和Embedded Coder都是用于将simulink模型自动转换成C代码。Simulink Coder生成的代码可以独立于matlab进行运行,这样可以在主机上运行以验证所生成的代码。而Embedded Coder生成的代码,一言以蔽之,就是更加优化、简洁,并且支持面向目标嵌入式平台生成代码,并因此得名。从实际实验生成的代码量也可以看出,同样的Simulink模型,Embedded Coder生成的代码量要比Simulink Coder生成的代码量更小一些。而且,根据以上描述,Embedded Coder生成的代码的可读性更好一些(?这个有待亲测确认)

f489828c5ab118e5a474c1b634d0591d.png

2. 搭建Simulink模型及仿真

2.1 搭建模型

        本实验用的模型如下图所示,实现的功能是两个正弦波信号相加后灌入一个低通滤波器。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_20,color_FFFFFF,t_70,g_se,x_16

       两个正弦波信号的频率分别为1kHz,和5kHz,本实验中采样率统一为44.1kHz。其中第一个正弦波信号模块的参数设置如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_10,color_FFFFFF,t_70,g_se,x_16

        滤波器系数是通过BL1和AL1设置,这两个参数分别表示IIR滤波器传输函数的分子和分母,我们在matlab命令行输入命令进行设置,如下以下代码所示。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_10,color_FFFFFF,t_70,g_se,x_16

fL=3e3; fs=44.1e3; [BL1 AL1] = butter(4, fL/fs);

        这条语句设计了一个采样率为44.1kHz、通带频率为3kHz的4阶巴特沃斯低通滤波器。这样的话可以将5kHz的正弦波率除掉,保留1kHz的正弦波信号。这个变化可以通过观测各节点频谱很容易确认。

        除了输入正弦波信号、低通滤波器模块,其它还有存储各滤波器输入输出数据的数据缓存模块,TimeScope用于观测时域波形,以及几个频谱分析仪(Spectrum Analyzer)模块。

 2.2 仿真

        设置仿真时长1秒钟(由于是44.1kHz采样率,1kHz和5kHz的正弦波,1秒钟的仿真时间足够了),仿真结果如下所示。

        四个节点的信号频谱,从左到右分别是1kHz的输入信号,5kHz的输入信号,滤波器输入信号(即两者相加的结果),滤波器输出结果。结果符合预期,从滤波器输出端频谱可以看出5kHz的信号分量收到了抑制。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_20,color_FFFFFF,t_70,g_se,x_16

        TimeScope输出的时域波形如下(中间两个顺序颠倒了,各波形的title请忽视),同样可以看出最后滤波器输出信号只剩下了1kHz的低频成分。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_20,color_FFFFFF,t_70,g_se,x_16

        由于有两个out(To WorkSpace)模块,所以仿真还生成了一个存储这些数据的结构体out,其中所包含的信息如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_15,color_FFFFFF,t_70,g_se,x_16

        执行命令“save('ex_lpf_ref.mat','out')”将这个数据存储下来用于后与生成的代码运行结果做对比。用plot语句同样可以画出以上TimeScope相同的波形,如下所示。

figure;
plot(out.tout, out.flt_dout(:,:));
hold on
plot(out.tout, out.flt_din(:,:));

        其中out.tout代表的是采样时间序列。 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_17,color_FFFFFF,t_70,g_se,x_16

3. 生成代码

 3.1 求解器设置为定步长

        在Simulink模型窗口的最上面的菜单Tab中选择“建模”-->"模型设置"后弹出“配置参数”对话窗,将“求解器选择”下面的“类型”改为“定步长”,其它不用管。只有定步长设置才能正确地生成C代码。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_20,color_FFFFFF,t_70,g_se,x_16

3.2 安装 MinGW-w64 编译器

        执行mex -setup检查是否为matlab配置了C编译器。如果没有的话,可以使用“附加功能”菜单安装,比如说我安装的是MinGW-w64:

  • 在 MATLAB 主页选项卡的环境部分,点击附加功能 > 获取附加功能

  • 0b3aed9a5a0c4a18aa19da8f56d19002.png

  • 在附加资源管理器中右上搜索框中输入“MinGW”回车会出现MinGW-64安装包下载链接,点进去再点击安装即可。

        然后遵照指令一步一步往前走即可。

        注意,MinGW 安装文件夹名称不能包含空格。例如,以下这样的的缺省安装路径是不行。

        C:\Program Files\mingw-64

        工具不能正确识别这种路径。

 3.3 调出Simulink Coder

        在Simulink模型窗口的“APP”,缺省地有“Embedded Coder”,但是没有“Simulink Coder”。本实验要生成可以独立运行的C程序,所以要用Simulink Coder。

点击最右端的下拉标志:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_20,color_FFFFFF,t_70,g_se,x_16

        在弹出的窗口中下拉到“代码生成”部分,选中“Simulink Coder”即可。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_16,color_FFFFFF,t_70,g_se,x_16

        这样会在原来APP旁边出现一个“C CODE”的TAB。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_20,color_FFFFFF,t_70,g_se,x_16

         可以从“Quick Start”出发去生成代码,Matlab内置例子通常是走这个流程,不过我走了一遍后没有感受到什么好处,所以以下实验不走这个流程。此处的Settings以下的内容,其实和上一层的“建模”-->"模型设置"相同,点进去再确认一下代码生成的设置:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_20,color_FFFFFF,t_70,g_se,x_16

        如果只想生成代码,可以勾选“仅生成代码”,但是本实验想让matlab走完编译的全过程。其它选项暂时就缺省就好了。万事俱备,点击“Build”按钮即可。顺利的话,可以看到在matlab的当前工作目录下生成了:ex_lpf.exe,ex_lpf.slxc以及存放所生成的代码的目录ex_lpf_grt_rtw。

        接下来我们先不管它生成了啥,先看看所生成的exe文件是否正确。在matlab命令行执行命令"! ex_lpf.exe"(用“!”后接exe文件名可以运行exe可执行文件),可以看到执行结果生成了一个ex_lpf.mat。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_10,color_FFFFFF,t_70,g_se,x_16

        将ex_lpf.mat加载进来(load ex_lpf.mat),里面包含rt_flt_din,rt_flt_dout,rt_tout,分别上面提到的out中的三个变量对应,只不过多了个rt_的前缀名(表示real-time?)。 对比这些数据与上面simulink模型运行所得到的数据结果可以确认它们的确是一致的。这就表明所生成的C代码模型与原simulink模型的确是等价的。

 4. 工具都生成了啥呢?

        是时候看看Coder都给我们生成了啥了。在以上代码生成完后会弹出一个“Code Generation Report”对话窗口,如下所示:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA56yo54mb5oWi6ICV,size_20,color_FFFFFF,t_70,g_se,x_16

        点击左边各文件可以查看各代码文件的内容。 第一印象一定是,哇,这么简单的一个模型,居然生成了这么多东西。需要花一些时间来看看:

  • 到底生成了啥
  • 为什么要生成这么多的东西,
  • 如何在C的开发平台中集成使用这些所生成的代码呢
  • 这些生成的代码的运行效率如何呢?

等等等等。不过,现在我写累了,等我歇一歇再回来。。。

        

相关博文:

Matlab/Simulink Embedded Coder一个非常迷幻的问题

Simulink模型参数初始化方法种种

Matlab/Simulink Coder: 将子系统生成为独立的函数和文件


http://chatgpt.dhexx.cn/article/4AG99sXs.shtml

相关文章

关于RuoYi自动代码生成功能的使用

为什么要使用代码生成? 答:因为在后端构建的过程中会有许多重复的类似的代码编写,而我们如果一个个去编写,会耗费大量时间与精力,所以我们可以设计一个功能去自动生成这些重复的,简单的代码。而若依系统就…

Mybatis Plus自动生成代码

mybatis-plus自动生成代码 一、简易生成代码二、指定生成的样式,并且不在一个模块1.父pom文件配置2.子模块pom文件配置3.准备vm文件4.设置MyBatisPlusGenerator.java5.运行MyBatisPlusGenerator.java文件6.运行sign-auth模块,解决异常 一、简易生成代码 /*** 代码生…

Simulink自动代码生成:数据类型别名自定义

在手写代码时,我们经常能看到自定义数据类型别名,例如有些代码中将计算机默认的数据类型改为我们自己习惯的名称,如图所示。 目录 一. 系统默认生成的别名二. 建立Simulink AliasType三. 修改Data Type Replacement四. 数据类型别名修改后的…

Simulink 自动代码生成原理

如下图,Simulink模型会先变成一个文本式的 .rtw 模型描述文件,然后再变成 .c,.h,最后编译为最终目标文件。 典型的 Simulink 用户通常都是,用Simulink设计好算法后,做到生成源代码这一步。然后把生成的算法的.c .h 源代…

如何自动生成SpringBoot项目代码

目录 1.RuoYi源码下载及启动若依服务1.1. RuoYi源码下载1.2. 启动若依服务 2.自动生成代码3.代码及sql文件链接 已经工作一段时间啦!首先是从后端开发开始入手的,前端也是在自学阶段(边学边问我身边的同事大佬),努力是…

Simulink自动代码生成:数据字典的建立及代码优化

在上一节《Simulink自动代码生成:生成代码的基本设置》的基础上,我们来对模型进行优化,使得生成的代码更能满足实际的需求,没看过我上一篇文章的可以点开如下链接:   Simulink自动代码生成:生成代码的基本…

推荐几个代码自动生成器

文章目录 老的代码生成器的地址:[https://www.cnblogs.com/skyme/archive/2011/12/22/2297592.html](https://link.zhihu.com/?targethttps%3A//www.cnblogs.com/skyme/archive/2011/12/22/2297592.html)1.懒猴子CG2.IT猿网3.listcode4.magicalcoder5.CodeSmith6. …

Mybatis代码自动生成

新启动的项目,数据库设计可能随时会变动,一些基础的接口,特别是xml文件和映射对象也需要变动,改动工作量大,用mybatis-plus代码自动生成工具自动生成代码,大大提高了效率 自动生成代码工具使用过程记录如下 首先手动创建一个springboot项目,可以去springboot官网上生成,也可以…

Simulink 自动代码生成电机控制:基于Keil软件集成

目录 系统软件架构 1.应用层全模型生成,底层手写代码 2.应用层模型生成,底层也是基于模型生成 3.Autosar 软件集成操作 接口配置 总结 系统软件架构 嵌入式软件开发包含应用层和底层,目前基于模型的开发软件架构总结为以下几种: 1.应…

mybatis自动生成代码

mybatis自动生成代码有三种方式&#xff1a;命令行、eclipse插件、maven插件。在这里主要介绍比较方便使用的一种方式–maven插件&#xff0c;它可以在eclipse、idea中通用。 在pom.xml文件中配置mybatis-generator插件&#xff1a; <plugin><groupId>org.mybatis…

idea自动生成代码

idea是完全可以自动生成一些基础代码&#xff0c;后续只需要根据生成的基础代码进行业务代码的编写&#xff0c;看看是如何生成的&#xff0c;教程比较全面&#xff0c;请耐心阅读&#xff0c;谢谢啦&#xff01; 1.首先检查自己的idea是否安装了自动生成代码的插件&#xff0…

Matlab/Simulink 自动代码生成详细步骤

最近一直在忙于FCU控制器的模型搭建&#xff0c;空闲之余也想分享一下自己对Simulink建模过程中的一些想法&#xff0c;从接触simulink到应用simulink大约已经两年多了&#xff0c;随着接触时间&#xff0c;慢慢发现simulink在模型搭建方面真的是非常的方面。今天我就和大家分享…

MybatisGenerator自动代码生成器的使用

之前有写过一篇文章通过RuoYi自动生成SpringBoot项目代码&#xff0c;这篇文章有介绍如何通过RuoYi框架来自动生成相关的SpringBoot代码。但并不是所有的小伙伴都会去下载RuoYi这一套框架代码去获取domain、mapper以及mapping&#xff0c;特此本人再推荐一款很实用并且也容易上…

Simulink自动代码生成(一)

一个simulink模型能够生成代码首先要满足的条件&#xff1a; 1&#xff1a;确保模型仿真的正确性2&#xff1a;将需要的输入和输出改成input和output模块3&#xff1a;离散化模型&#xff0c;设置求解器为离散&#xff0c;固定步长满足上面条件后&#xff0c;接下来怎么生成嵌入…

代码一键自动生成,拿走不谢

程序猿学社的GitHub&#xff0c;欢迎Star github技术专题 本文已记录到github 文章目录 前言起源环境实战sql脚本pom.xmlapplication.yml启动类代码自动生成controller类 测试 前言 隔壁老王&#xff1a; 社长&#xff0c;我工作有一段时间咯&#xff0c;我看其他的同事&#x…

4个免费代码自动生成神器

4个免费代码自动生成神器 日常写代码&#xff0c;是一件非常需要耐心的事情&#xff0c;尤其是那些没有技术含量重复使用到的一些代码排列组合&#xff0c;比如前端的一些html和css布局&#xff0c;简单繁杂&#xff0c;这个时候就会使用到一些免费代码自动生成神器&#xff0c…

java自动代码生成

1.概述 可在线自动生成代码&#xff0c;省去复制、修改通用模板代码的繁琐过程&#xff0c;减少团队70%以上的开发工作量 基于java的template模板引擎velocity&#xff0c;在定义好模板文件后&#xff0c;动态产生适应业务的java、xml、html、sql等代码文件 2.自动生成过程 …

Linux防火墙关闭方法

Linux防火墙关闭方法 关闭防火墙&#xff1a; 1、查看状态&#xff1a;systemctl status firewalld 2、关闭&#xff1a; systemctl stop firewalld&#xff08;只执行这个&#xff0c;重启后不行&#xff0c;还必须执行systemctl status firewalld&#xff09; 1.1、查看seli…

Linux中的Java项目服务器无故关闭

部署在Linux中的项目&#xff0c;最近一直无故关闭。找了很多都找不到原因。最近发现一个现象终于让我知道是什么原因导致我的开发服务器无故关闭了。 起因 部署在linux中的java开发服务器最近一直无故关闭。且是因为我在启动脚本中加了如下命令导致的。 tail -f log/game.lo…

Linux 系统下关闭防火墙

一、重启后永久性生效&#xff1a; 开启&#xff1a; chkconfig iptables on 关闭&#xff1a; chkconfig iptables off 二、即时生效&#xff0c;重启后失效&#xff1a; 开启&#xff1a; service iptables start 关闭&#xff1a; service iptables stop 需要说明的…