例如我们有DBC文件,主要包含以下两个报文:
![](https://pic4.zhimg.com/80/v2-86d5c7a48f7685966f2e61ff9c67570b_720w.jpg)
图1.dbc文件Layout
现在需要在Simulink中创建MCU的CAN报文处理功能模块,即获取HCU发送的数据,解析获取HCU的指令信号;打包MCU内部信号,作为MCU发送报文。今天就跟大家介绍下CAN Unpack/Pack两种常用的应用场景
应用场景一:定义CAN_Msg_In、CAN_Msg_Out两变量,分别作为输入和输出报文变量
CAN_Msg_In和CAN_Msg_Out都为CAN_MESSAGE 类型。
在与底层驱动进行集成时,底层可使用CAN_Msg_In和CAN_Msg_Out这两个变量,或再定义其他CAN_MESSAGE 类型的接口变量。
![](https://pic4.zhimg.com/80/v2-9b75caa38f17a0fa3b249bc1ef09f4b7_720w.jpg)
![](https://pic1.zhimg.com/80/v2-de5f1f03cb1c1b5e3f865a8d462ae648_720w.jpg)
![](https://pic2.zhimg.com/80/v2-bd050ed2bdee871f7113c2fcb5cfd801_720w.jpg)
图2.CAN Unpack/Pack建模
上述CAN_MESSAGE数据类型在MATLAB自带的can_message.h中进行了定义
can_message.h可在MATLAB安装路径下找到一个文件,如下图。可以将此文件拷贝至当前路径下
![](https://pic2.zhimg.com/80/v2-1be7e429f58d96fa01c2c1c363d29321_720w.jpg)
图3.can_message.h所在路径
![](https://pic4.zhimg.com/80/v2-decc756c6510ef34a64d447b7622613f_720w.jpg)
图4.CAN_MESSAGE结构体
知道了CAN_MESSAGE 类型的定义后,这两个模块的使用就很简单了,我们可以在工作区定义名为CAN_MESSAGE的Simulink Bus数据对象,如下:
![](https://pic4.zhimg.com/80/v2-a251260c53fee9b3268f0d1a7e48b5e3_720w.jpg)
图5.定义CAN_MESSAGE Simulink.Bus数据对象
再定义CAN_Msg_In和CAN_Msg_Out两个Simulink.Signal数据对象,数据类型选择上面定义好的 Bus:CAN_MESSAGE
![](https://pic4.zhimg.com/80/v2-fe06d6f67ec83d31a2e67df45ae423b3_720w.jpg)
图6.CAN_Msg_In Simulink.Signal数据对象
其他信号的数据对象都是基础数据类型(double,unit8,int16等),这里不再赘述,所有数据对象最终定义成如下:
![](https://pic4.zhimg.com/80/v2-7588fcfcc3ceaca197dae08940158743_720w.jpg)
图7.所有数据对象
信号线关联数据对象,仿真无误,生成代码如下:
![](https://pic2.zhimg.com/80/v2-bd23e3e103e7c7eda53064102d900441_720w.jpg)
图8.变量定义
CAN Unpack部分代码,使用CAN_Msg_In变量直接进行解析
![](https://pic4.zhimg.com/80/v2-659c1131aaa4091d2908d7541d661ac7_720w.jpg)
图9.CAN Unpack模块部分代码
CAN Pack部分代码,信号打包输出CAN_Msg_Out
![](https://pic4.zhimg.com/80/v2-546c30bf598e2c6df3a9718511ee2107_720w.jpg)
图10.CAN Pack模块部分代码
应用场景二:对于底层驱动已经定义了CAN_MsgIn_Data[8] 和CAN_MsgOut_Data[8] 两个数组变量作为接口,用于存放CAN报文的Data部分,应用层只能使用这两个数组,此时可用这种方法。此方法其实和场景一种的很相似,都需要使用CAN_MESSAGE这个数据类型。首先也需要在工作区(或数据字典)中定义CAN_MESSAGE Simulink.Bus数据对象。
![](https://pic2.zhimg.com/80/v2-d6a5fb57ee4d9addec1fea83602ec641_720w.jpg)
与场景一的主要区别是CAN Pack中需要勾选 Output as bus
![](https://pic2.zhimg.com/80/v2-5a9bff6223e266dc47882989cadab5fd_720w.jpg)
图11.CAN Pack模块设置
此时,在CAN Pack输出端可接一个Bus Selector,仅输出Data
![](https://pic1.zhimg.com/80/v2-daab97479afe0594f2a250a86a834828_720w.jpg)
图12.Bus Selector选择Data部分输出
而CAN Unpack输入端,需要我们自己构造一个Bus信号,且需勾选输出为非虚拟总线,输出类型选择定义好的Bus:CAN_MESSAGE
![](https://pic2.zhimg.com/80/v2-3d67bc2bf29945346df45c3353df47a9_720w.jpg)
图13.Bus Creator构造非虚拟总线
其他设置与应用场景一类似,这里为了演示函数封装,将CAN UnPack/Pack都封装在单独的原子子系统中,并设置相应的函数和文件名。生成的部分代码如下:
![](https://pic2.zhimg.com/80/v2-00943f67174f47262175005ec2a219ed_720w.jpg)
图13.生成的step函数
Tips:需要注意的是,应用场景二中需要设置CAN pack模块输出bus信号,而稍低版本的MATLAB(例如16b)中是没有此项设置的
![](https://pic2.zhimg.com/80/v2-016b6b62ddd6386d09f14b9e30f7ad71_720w.jpg)
如果是这种情况,可在CAN Pack后面再增加一个CAN Unpack模块,并选择raw data输出
![](https://pic1.zhimg.com/80/v2-7a6cf290e516fe2fcd91a72bb6131b20_720w.jpg)
![](https://pic4.zhimg.com/80/v2-59d4f7c2f2083c348e706992ae3df69b_720w.jpg)
这种方法最后输出的直接是数组了,但因为多了一个CAN Unpack,无形中引入了该部分的代码,而该部分代码中涉及memcpy这个C库函数,这里也需要注意一下
![](https://pic3.zhimg.com/80/v2-7a2ee08abb05ffda7bb7dddcd228461e_720w.png)
除了这两个应用场景之外,在命令行输入canMessageBusType,工作区会自动创建一个名为CAN_MESSAGE_BUS的Simulink Bus数据对象,用法和上面我们自定义的CAN_MESSAGESimulink Bus数据对象类似,感兴趣的童鞋可以尝试一下。