例如我们有DBC文件,主要包含以下两个报文:
图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 类型的接口变量。
图2.CAN Unpack/Pack建模
上述CAN_MESSAGE数据类型在MATLAB自带的can_message.h中进行了定义
can_message.h可在MATLAB安装路径下找到一个文件,如下图。可以将此文件拷贝至当前路径下
图3.can_message.h所在路径
图4.CAN_MESSAGE结构体
知道了CAN_MESSAGE 类型的定义后,这两个模块的使用就很简单了,我们可以在工作区定义名为CAN_MESSAGE的Simulink Bus数据对象,如下:
图5.定义CAN_MESSAGE Simulink.Bus数据对象
再定义CAN_Msg_In和CAN_Msg_Out两个Simulink.Signal数据对象,数据类型选择上面定义好的 Bus:CAN_MESSAGE
图6.CAN_Msg_In Simulink.Signal数据对象
其他信号的数据对象都是基础数据类型(double,unit8,int16等),这里不再赘述,所有数据对象最终定义成如下:
图7.所有数据对象
信号线关联数据对象,仿真无误,生成代码如下:
图8.变量定义
CAN Unpack部分代码,使用CAN_Msg_In变量直接进行解析
图9.CAN Unpack模块部分代码
CAN Pack部分代码,信号打包输出CAN_Msg_Out
图10.CAN Pack模块部分代码
应用场景二:对于底层驱动已经定义了CAN_MsgIn_Data[8] 和CAN_MsgOut_Data[8] 两个数组变量作为接口,用于存放CAN报文的Data部分,应用层只能使用这两个数组,此时可用这种方法。此方法其实和场景一种的很相似,都需要使用CAN_MESSAGE这个数据类型。首先也需要在工作区(或数据字典)中定义CAN_MESSAGE Simulink.Bus数据对象。
与场景一的主要区别是CAN Pack中需要勾选 Output as bus
图11.CAN Pack模块设置
此时,在CAN Pack输出端可接一个Bus Selector,仅输出Data
图12.Bus Selector选择Data部分输出
而CAN Unpack输入端,需要我们自己构造一个Bus信号,且需勾选输出为非虚拟总线,输出类型选择定义好的Bus:CAN_MESSAGE
图13.Bus Creator构造非虚拟总线
其他设置与应用场景一类似,这里为了演示函数封装,将CAN UnPack/Pack都封装在单独的原子子系统中,并设置相应的函数和文件名。生成的部分代码如下:
图13.生成的step函数
Tips:需要注意的是,应用场景二中需要设置CAN pack模块输出bus信号,而稍低版本的MATLAB(例如16b)中是没有此项设置的
如果是这种情况,可在CAN Pack后面再增加一个CAN Unpack模块,并选择raw data输出
这种方法最后输出的直接是数组了,但因为多了一个CAN Unpack,无形中引入了该部分的代码,而该部分代码中涉及memcpy这个C库函数,这里也需要注意一下
除了这两个应用场景之外,在命令行输入canMessageBusType,工作区会自动创建一个名为CAN_MESSAGE_BUS的Simulink Bus数据对象,用法和上面我们自定义的CAN_MESSAGESimulink Bus数据对象类似,感兴趣的童鞋可以尝试一下。