关于BDC之前已经总结了很多:
参看:汽车电子 – 根据DBC解析CAN报文
参看:汽车电子 – CAN报文接收解析和发送组包
参看:汽车电子 – 使用CANdb++ Editor创建并制作一个DBC
DBC文件是用来描述CAN网络通信信号的一种格式文件。它可以用来监测与分析CAN网络上的报文数据,也可以用来模拟某个CAN节点
本文出现的符号:
’ | ’ ——可选择
’ ; '——结束定义
[…]——内容可选(0或1次)
{…}——内容重复(0或多次)
(…)——注释
unsigned_integer:无符号整型
signed_integer:有符号整型
double:双精度小数
char_string:字符串
C_identifier:C语言变量命名
一、DBC文件构成
1、版本与新符号
- VERSION
版本
VERSION “”
version’或为空,或由用户自行定义。 - NS_
为new symbol的缩写,后面紧跟着一堆ns,一般为创建dbc时自动生成,不用太关心。
2、波特率定义
- BS_
定义CAN网络的波特率。必须部分,但通常为空。
BS_: [baudrate:BTR1,BTR2]
用于定义CAN网络的波特率;[ ]内容表示为可选部分,可以省略(如下图例子中即把该部分省略了);但关键字”BS_:”必须存在,省略则会出错。《DBC File Format Document》规范中明确提醒,必须保留BS_: 标签。
3、网络节点的定义
- BU_
网络节点
BU_: Nodename1 Nodename2 Nodename3 ……
其中,Nodename1、Nodename2 网络节点名字,由用户自己定义;
注意事项:需要保证节点命名的唯一性。
上图,表示定义了 New_Node_1 、IECU、AMRR 三个网络节点。
4、报文帧的定义
- BO_
报文
BO_: message_id message_name : message_size transmitter {signal}
其中:
MessageId:报文ID,是以10进制数表示的;
MessageName:报文的名字,命名规则和C语言变量相同;
MessageSize:报文数据域字节数,为无符号整型数据,CAN 2.0为最大8字节,CAN FD 最大64字节;
Transmitter:该报文的网络节点;如果该报文没有指定发送节点,则该值需设置为” Vector__XXX”。
如上图:
报文ID:489(0x1E9)
报文名:YawRateFeedback
分隔符 : “:”
报文长度:8字节
报文发送者:该报文没有指定发送节点设置为” Vector__XXX”。
5、信号的定义
- SG_
信号
SG_: signal_name multiplexer_indicator : start_bit | signal_size @ byte_order value_type ( factor , offset ) [ minimum | maximum ] unit receiver {, receiver}
其中:
signal_name:信号名
multiplexer_indicator:定义了该信号是否为一个正常信号,或一个复用信号,此项可以被省略。
start_bit:起始位置。
signal_size:信号长度。
byte_order:字节顺序。0为intel格式,1为motorola。
value_type:数值类型。Unsigned无符号数, Signed有符号数。
factor:因子。
offset:偏移。facator与offset用来将原始值与物理值之间进行转化。物理值=原始值*因子+偏移量;
minimum:最小值。minumum与maximum为double类型,表示信号的最值范围。
maximum:最大值。minumum与maximum为double类型,表示信号的最值范围。
unit:单位。
receiver:接收者。如果一个信号没有指定接收者,则必须设置为‘Vector__XXX’。
这里需要注意的是Startbit总共有六种显示形式,其中Motorola有四种,Intel有两种。这六种形式可以通过CANdb工具进行切换,点击Options菜单下的Settings选项,在弹出的设置对话框中可以选择Motorola和Intel的具体显示形式:
6、注解部分
- CM_
对报文/信号的注解
CM_: Object MessageId/NodeName “Comment”
其中:
Object:表示进行注解的对象类型,可以是节点“BU_”、报文“BO_”、消息”SG_”;
MessageId/NodeName:表示进行注解的对象,若前面的对象类型是信号或者报文,则这里的值应为报文的ID(10进制数表示);若前面的对象类型为节点,则这里的值应为节点的名字;
Comment :表示进行注解的文本信息;
表示 ID为 1702(0x6A6)报文下的LVDA_WorkState的信号进行注解说明。
7、属性定义部分
- BA_DEF_DEF_
对报文/信号/节点等的属性初始值定义
BA_DEF_DEF_: AttributeName DefaultValue;
其中:
AttributeName:特征名称(C语言变量格式)。
DefaultValue:该特征的默认设置值。
- BA_
对报文/信号/节点等的属性设置值定义
BA_: AttributeName projectValue
其中:
AttributeName:特征名称(C语言变量格式)
projectValue:该特征的设置值
8、数值表部分
- VAL_
数值表定义
VAL_: MessageId SignalName N “DefineN” …… 0 “Define0”
其中:
MessageId 表示该信号所属的报文ID(10进制数表示);
SignalName 表示信号名;
N “DefineN” …… 0 “Define0” 表示定义的数值表内容,即该信号的有效值分别用什么符号表示 。
如上图表示ID为616(0x268)这条报文下的,AT_ActualGearValid的信号,进行其数值表的定义。
- VAL_TABLE_
全局信号值表,用来对信号值解码
VAL_TABLE_: name value “value_description” …0 “value_description”
其中:
name表示value table的名称, 命名必须满足“符号字符串”要求;
value表示value table的值,十进制表示;
value_description表示value table的值描述;
如上图表示MRR_CarSlipReminder_WorkState信号的 2 表示"Active" 、1 表示"Standby"、 0 表示"OFF" ;
二、factor和offset及其运算公式
在DBC文件中,“factor”和“offset”用于描述信号的转换参数。
- “factor”是转换系数,用于确定从原始值到物理值的转换比例。
- “offset”是转换偏移量,用于定义转换过程中的一个常数偏移。
转换公式:
根据这些定义,可以使用以下公式进行转换:
物理值 = 原始值 * factor + offset
或
原始值 = (物理值 - offset) / factor
三、Startbit显示形式
根据ByteOrder不同,Startbit总共有六种显示形式,其中Motorola有四种,Intel有两种。
1、Motorola Forward MSB:
2、Motorola Forward LSB:
3、 Intel Standard:
四、python脚本
1、用python获取DBC文件并保存到EXCEL
- 安装相关库
pip install cantools openpyxl
- 代码实现
import cantools
from openpyxl import Workbook
def read_dbc_and_save_to_excel(dbc_file_path, excel_file_path):
# Load DBC file
db = cantools.database.load_file(dbc_file_path)
# Create Excel workbook and worksheet
wb = Workbook()
ws = wb.active
ws.append(['ID', 'Name', 'Signal', 'Start', 'Length', 'Factor', 'Offset', 'Min', 'Max', 'Unit'])
# Write DBC data to Excel
for message in db.messages:
ws.append([message.name, message.frame_id, message.length, message.cycle_time])
for signal in message.signals:
ws.append(["", signal.name, signal.start, signal.length, signal.byte_order, signal.is_signed,
signal.scale, signal.offset, signal.minimum, signal.maximum])
# Save Excel file
wb.save(excel_file_path)
if __name__ == "__main__":
dbc_file_path = "path/to/your/file.dbc" # Replace with the actual DBC file path
excel_file_path = "path/to/your/output.xlsx" # Replace with the desired Excel output path
read_dbc_and_save_to_excel(dbc_file_path, excel_file_path)
2、python 解析DBC
安装cantools库
pip install cantools
解析DBC文件
- 导入cantools库并加载DBC文件
import cantools
# 加载DBC文件
db = cantools.database.load_file('example.dbc')
- 解析节点
可以使用db.nodes属性。这将返回一个包含所有节点的列表。我们可以遍历该列表来访问每个节点的属性:
# 遍历节点
for node in db.nodes:
print("Node name: ", node.name)
print("Node comment: ", node.comment)
print()
- 解析消息
可以使用db.messages属性。这将返回一个包含所有消息的列表。我们可以遍历该列表来访问每个消息的属性:
# 遍历消息
for message in db.messages:
print("Message name: ", message.name)
print("Message id: ", message.frame_id)
print("Message length: ", message.length)
print("Message senders: ", message.senders)
print("Message comment: ", message.comment)
print()
- 解析信号
可以使用message.signals属性。这将返回一个包含所有信号的列表。我们可以遍历该列表来访问每个信号的属性:
# 遍历信号
for signal in message.signals:
print("Signal name: ", signal.name)
print("Signal start bit: ", signal.start)
print("Signal length: ", signal.length)
print("Signal byte order: ",signal.byte_order)