前面
dbc文件在汽车电子系统中的关键作用,不亚于语言对于我们人类社会。
什么是DBC文件?可以看我的这篇笔记:
DBC 文件
那么一个DBC文件是怎么诞生的呢?
本篇博文借助Vector的CANdb++工具给大家简单的介绍一下。
软件的下载安装
网址:Download Center
所需要的dll文件与软件:
链接:https://pan.baidu.com/s/1Or9pBRlMm27Gu8KUfvVpqw?pwd=l9ls 提取码:l9ls —来自百度网盘超级会员V5的分享
把dll文件放在C:\Windows\SysWOW64下,便可以打开软件
DBC的诞生
需求
设计的前提一定是需求,没有需求的设计都是耍流氓。
这里借鉴以一个大佬的例子(CSDN 蚂蚁小兵)
现在有一个总线,总共有3个节点:发动机 (Engine) 、前置大灯(Light) 、仪表盘(Display) 。
- 发动机就一个报文(EngineState) 报文有两个信号: 开关 (OnOff) 、速度(EngineSpeed)
- 前置大灯就一个报文 (LightState) 报文有两个信号: 前大灯(HeadLight) 、双闪灯 (FlashLight)
发动机和大灯都是发送节点,仪表盘是接收节点,显示发动机的状态和速度,显示大灯的状态。
新建dbc文件
File新建,根据自己的需要选择模板,这里我们选择CANoe类型的,它们的区别在于一些文件属性不一样。
新建成功
添加信号
选择single,右键新建:
Byte Order:表示数据格式,有“Motorola(大端模式)”,“Intel(小端模式)”可选,根据实际情况选择; Value Type: 表示数据是有/无符号类型(若偏移量为0,需要表示负数,则该项选择Signed; 若偏移量为负数,需要表示负数,则该项选择Unsigned。); Factor: 表示分辨率; Offset: 表示偏移量; Minimum:和Maximum表示该信号实际范围; 比如,最大值是30 即信号值3000*0.01(Factor) = 30,即信号的最大值是3000.
解析数据时:实际的信号物理值 = 分辨率 * CAN信号值 + 偏移量
同理添加四个信号:
EngineSpeed
定义
还以添加描述,这个在DBC文件里也会显示出来的,非常方便
EngineOnOff
FlashLight
HeadLight
添加报文
需要两个报文:LightState、EngineState
右键Messages新建:
ID:用十六进制表示,如果是标准帧,范围:0~0x7FF;
DLC: 表示新增message的实际的长度,最大为8
LightState
EngineState
同样把信号添加进去
添加进去之后的信号如何排布?
第一种方式,Layout直接拖动
第二种,设置起始位
报文发送类型
也就是说这个报文是怎么发送的,有没有时间间隔
比如EngineState 周期性发送 周期1S
添加节点
Display
display属于接收节点,所以添加接收信号,四个信号都加进去
Engine
Light
其实到这一步就已经差不多了,有了信号,有了报文,有了节点、它们之间也都联系了起来。
但其实还有一个点可以进行优化:那就是value table。
每一个信号其实都有自己的数值表,或者编码表,什么样的数值代表什么样的物理意义。
添加value table
进入界面:
新建,把名字对应好,省的搞混了
值描述
进入信号,添加对应
然后就可以在数值描述中看到对应的变化了:
同理添加其他信号的value table
都设置完成之后,点击检查,没什么问题。
查看生成的DBC文件
版本与NS
波特率
网络节点
报文与信号
注释
特征属性
源DBC文件
VERSION ""
NS_ :
NS_DESC_
CM_
BA_DEF_
BA_
VAL_
CAT_DEF_
CAT_
FILTER
BA_DEF_DEF_
EV_DATA_
ENVVAR_DATA_
SGTYPE_
SGTYPE_VAL_
BA_DEF_SGTYPE_
BA_SGTYPE_
SIG_TYPE_REF_
VAL_TABLE_
SIG_GROUP_
SIG_VALTYPE_
SIGTYPE_VALTYPE_
BO_TX_BU_
BA_DEF_REL_
BA_REL_
BA_DEF_DEF_REL_
BU_SG_REL_
BU_EV_REL_
BU_BO_REL_
SG_MUL_VAL_
BS_:
BU_: Light Engine Display
VAL_TABLE_ EngineState_Table 255 "无效值" 1 "发动机运行" 0 "发动机停止" ;
VAL_TABLE_ FlashState_Table 255 "无效值" 1 "双闪灯打开" 0 "双闪灯关闭" ;
VAL_TABLE_ HeadState_Table 255 "无效值" 1 "前大灯打开" 0 "前大灯关闭" ;
BO_ 801 EngineState: 2 Engine
SG_ EngineSpeed : 1|8@1- (1,0) [0|30] "r/min" Display
SG_ EngineOnOff : 0|1@1+ (1,0) [0|1] "" Display
BO_ 291 LightState: 1 Light
SG_ HeadLight : 1|1@1+ (1,0) [0|1] "" Display
SG_ FlashLight : 0|1@1+ (1,0) [0|1] "" Display
CM_ SG_ 801 EngineSpeed "发动机速度,单位r/min";
CM_ SG_ 801 EngineOnOff "发动机开关状态";
CM_ SG_ 291 HeadLight "前大灯状态";
CM_ SG_ 291 FlashLight "双闪灯状态";
BA_DEF_ SG_ "GenSigSendType" ENUM "Cyclic","OnWrite","OnWriteWithRepetition","OnChange","OnChangeWithRepetition","IfActive","IfActiveWithRepetition","NoSigSendType";
BA_DEF_ SG_ "GenSigInactiveValue" INT 0 0;
BA_DEF_ BO_ "GenMsgCycleTime" INT 0 0;
BA_DEF_ BO_ "GenMsgSendType" ENUM "Cyclic","not_used","not_used","not_used","not_used","Cyclic","not_used","IfActive","NoMsgSendType";
BA_DEF_ BU_ "NmStationAddress" HEX 0 0;
BA_DEF_ "DBName" STRING ;
BA_DEF_ "BusType" STRING ;
BA_DEF_ BU_ "NodeLayerModules" STRING ;
BA_DEF_ BU_ "ECU" STRING ;
BA_DEF_ BU_ "CANoeJitterMax" INT 0 0;
BA_DEF_ BU_ "CANoeJitterMin" INT 0 0;
BA_DEF_ BU_ "CANoeDrift" INT 0 0;
BA_DEF_ BU_ "CANoeStartDelay" INT 0 0;
BA_DEF_DEF_ "GenSigSendType" "Cyclic";
BA_DEF_DEF_ "GenSigInactiveValue" 0;
BA_DEF_DEF_ "GenMsgCycleTime" 0;
BA_DEF_DEF_ "GenMsgSendType" "NoMsgSendType";
BA_DEF_DEF_ "NmStationAddress" 0;
BA_DEF_DEF_ "DBName" "";
BA_DEF_DEF_ "BusType" "CAN";
BA_DEF_DEF_ "NodeLayerModules" "";
BA_DEF_DEF_ "ECU" "";
BA_DEF_DEF_ "CANoeJitterMax" 0;
BA_DEF_DEF_ "CANoeJitterMin" 0;
BA_DEF_DEF_ "CANoeDrift" 0;
BA_DEF_DEF_ "CANoeStartDelay" 0;
BA_ "DBName" "test";
BA_ "GenMsgSendType" BO_ 801 0;
BA_ "GenMsgCycleTime" BO_ 801 1000;
BA_ "GenMsgSendType" BO_ 291 0;
BA_ "GenMsgCycleTime" BO_ 291 1000;
VAL_ 801 EngineOnOff 255 "无效值" 1 "发动机运行" 0 "发动机停止" ;
VAL_ 291 HeadLight 255 "无效值" 1 "前大灯打开" 0 "前大灯关闭" ;
VAL_ 291 FlashLight 255 "无效值" 1 "双闪灯打开" 0 "双闪灯关闭" ;
总结
这是一个比较简单的实例,大概走了一遍DBC文件的配置路程,实际应用会更复杂。