2. MATLAB/Simulink基础:Simulink环境介绍、基本模块库、模型创建与仿真
好,咱们开始聊Simulink。说实话,很多做嵌入式的人一开始都把它当成一个画图工具,觉得不就是拖几个方块连几根线嘛。嗯,我当年刚入行时也这么想,直到第一次在项目里因为一个采样时间设置错误,导致生成的代码在ECU上跑飞了……从那以后,我再也不敢小看这个环境了。
2.1 Simulink环境介绍
打开Simulink,你首先看到的是启动界面。我个人习惯直接点工具栏上的Simulink图标,或者命令行敲simulink回车。你会看到几个关键区域:
- 库浏览器(Library Browser):所有模块的仓库,左边是分类树,右边是具体模块
- 模型编辑器(Model Editor):你拖模块、画连线的主战场
- 仿真工具栏:运行、停止、设置仿真时间,都在这里
这里有个小细节——很多人一上来就找模块,其实不如先熟悉一下模型资源管理器(Model Explorer)。我在做AUTOSAR项目时,经常用它来批量管理信号和参数,比在画布上一个一个点快多了。
2.2 基本模块库
Simulink的模块库看着眼花缭乱,但做ECU软件,你真正高频使用的其实就那几类。我按使用频率给你排个序:
| 模块库 | 常用模块 | 我的使用场景 |
|---|---|---|
| Sources(信号源) | Inport, Constant, Step, Pulse Generator | 给模型注入外部输入,比如传感器信号 |
| Sinks(信号接收) | Outport, Scope, To Workspace | 把结果输出到ECU端口或查看波形 |
| Continuous(连续) | Integrator, Transfer Fcn | 做PID控制器时常用,但生成代码时要注意离散化 |
| Discrete(离散) | Unit Delay, Discrete PID Controller | 这才是嵌入式的主力,所有采样时间都要显式设置 |
| Math Operations | Add, Product, Gain, Saturation | 加减乘除限幅,天天用 |
| Logic and Bit Operations | Logical Operator, Relational Operator | 做状态机条件判断时离不开 |
你可能会问,为什么没有Stateflow?别急,那是专门做状态机的,后面章节我会单独讲。这里先打好基础。
2.3 模型创建与仿真
好,咱们动手建一个最简单的模型。假设你要实现一个功能:输入一个车速信号,经过一个低通滤波器,再输出给CAN总线。
步骤其实很简单:
- 从Sources库拖一个Inport模块,命名
VehSpd_Input - 从Discrete库拖一个Discrete Filter模块,双击设置分子分母系数
- 从Sinks库拖一个Outport模块,命名
VehSpd_Filtered - 用鼠标连线,从Inport连到Filter,再从Filter连到Outport
代码层面,你不需要写一行。但Simulink背后其实在生成一个差分方程。比如一阶低通滤波器的离散形式:
y(n) = a * x(n) + (1-a) * y(n-1)
其中a是滤波系数,由采样时间和截止频率决定。你在Discrete Filter模块里填的分子分母,就是对应这个方程的系数。
设置好仿真时间(比如10秒),点一下运行按钮。双击Scope模块,你就能看到输入信号和滤波后的输出波形。嗯,这里要注意——Scope的显示刷新频率可能跟不上仿真步长,如果波形卡顿,可以试试把仿真步长改大一点,或者用To Workspace把数据导到MATLAB里画图。
2.4 仿真参数配置
仿真不是随便点一下运行就完事的。你需要配置几个关键参数:
- 求解器(Solver):嵌入式模型选
discrete (no continuous states),别选ode45那些连续求解器 - 步长(Step size):固定步长,比如0.01秒(对应100Hz任务周期)
- 仿真时间(Stop time):根据你的测试场景来,一般设10-100秒足够
为什么强调固定步长?因为ECU的任务调度是周期性的,你想想看,如果仿真步长不固定,生成的代码里就会出现变步长逻辑,这在嵌入式里几乎不可接受。我见过一个同事,仿真时用变步长跑得好好的,生成代码后一部署就报看门狗超时,查了半天才发现是步长不一致导致的。
好了,这一章的内容就这些。记住:Simulink不是画图工具,它是代码生成的前端。你拖的每一个模块,连的每一条线,最终都会变成ECU里跑的C代码。所以从一开始,就要用嵌入式工程师的思维去建模。