什么是 DBC 文件 DBC 是Database Can的缩写,其代表的是CAN的数据库文件。简单地说,通过 CAN 总线通信的数据类型可以用 DBC 文件来读取和理解。一般通过 Vector CANdb++ 进行编辑和查看。
DBC 文件内容 当我们打开一份 DBC 文件时,左侧树形目录对应
Networks:从网络的视角来观察总线上存在的节点、报文和信号
ECUs:每个 ECU 的 Network Node 和 Environment Variables
Environment Variables:在使用 CANoe 仿真节点时会用到
Network nodes:从单个节点的视角来观察与节点相关的总线报文及信号
Tx Messages:节点发送报文
Rx Messages:节点接收报文
Mapped Tx Signals:节点发送信号
Mapped Rx Signals:节点接收信号
Messages:CAN 总线上传输信息的最小单位
Signals:Message 里最小的元素单位
值得一提的是,Messages 与 Signals 下包含的报文信号比 Network nodes 下的收发报文信号要多,并且有可能会包含实际没用到的报文信号,因为所有创建的报文信号都会在 Messages 与 Signals 下显示,但只有映射到节点的报文信号才会在 Network nodes 下显示。
因此我们主要看 Network nodes 下里的网络节点,网络节点分为多个类,如下图,分为 SDE、sensor2、sensor3 三个类节点。
当点开节点时,会看到类节点下的 TX 与 RX 下的多个 messages。
ID:CAN message id,一般以16进制显示
Name: CAN message name
ID-Format:CAN 报文的类型(CAN Standard/CAN FD Standard)
DLC:数据长度代码,CAN 报文中数据的长度
每个 message 又包含了多个 signals。
Name:信号的名称
Multiplexing:多路复用
Startbit:信号的起始位
Byte Order:信号的位计数,分为 Motorols(大端字节序)和 Intel(小端字节序)
Value Type:数据类型
Factor:信号的转换系数
Offset:信号的转换偏移
Minimum & Maximum:最小和最大的信号值
Unit:信号中存在的物理数据的单位
Comment:信号说明
其中 factor 因数 与 offse 偏移量 定义了 physical 物理值(如vehicle speed,engine speed,water temperature)与 raw 原始值(总线上传输的值)的线性转换规则。
1 2 physical_value = raw_value * factor + offset raw_value = ( pysical_value - offset ) / factor
DBC 文件解析 这里使用 Python。首先安装 cantools 这个库文件,可以直接解析 dbc 文件。
使用时,直接 import cantools 即可。
1 2 3 import cantoolsdbc_file = "******" dbc_info = cantools.db.load_file(dbc_file)
直接使用时,下述附代码,可直接复制使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 import cantoolsclass DbcInfo : """ 用于读取dbc文件,返回dbc信息 """ def __init__ (self, input_file ): """ init """ self.dbc_file = input_file self.dbc_info = cantools.db.load_file(self.dbc_file) def get_message (self, frame_id ): """ return message,特别强调,frame_id输入10进制即可,同时必须是int型数据,不能是字符串 """ return self.dbc_info.get_message_by_frame_id(frame_id) def get_message_name (self, frame_id ): """ return message name """ return self.dbc_info.get_message_by_frame_id(frame_id).name def get_message_name_by_message_id (self, frame_name ): """ return message id by message name """ return self.dbc_info.get_message_by_name(frame_name).frame_id def get_signals_list (self, frame_id ): """ return signals list """ return self.dbc_info.get_message_by_frame_id(frame_id).signal_tree def get_signal (self, frame_id, signal_name ): """ return signal, 输入message id和signal name """ return self.dbc_info.get_message_by_frame_id(frame_id).get_signal_by_name(signal_name) def get_signal_config_maximum (self, frame_id, signal_name ): """ return signal maximum """ return self.dbc_info.get_message_by_frame_id(frame_id).get_signal_by_name(signal_name).maximum def get_signal_config_minimum (self, frame_id, signal_name ): """ return signal minimum """ return self.dbc_info.get_message_by_frame_id(frame_id).get_signal_by_name(signal_name).minimum def get_signal_config_scale (self, frame_id, signal_name ): """ return signal scale,这里指的是signal定义中其取值范围的间隔, 比如从1到10,每个2取一个值,scale就是2 """ return self.dbc_info.get_message_by_frame_id(frame_id).get_signal_by_name(signal_name).scale def get_signal_config_comment (self, frame_id, signal_name ): """ return signal comment,signal说明 """ return self.dbc_info.get_message_by_frame_id(frame_id).get_signal_by_name(signal_name).comment def signal_config_value_description_to_num (self, frame_id, signal_name, value_str ): """ return signal value description 这里需要特别说明下,有些signal取值不是正常的数值,而是文字描述, 这个在定义中是个表,比如1:open, 2:close, 4:ignore, 本函数的意思是当你取到这个字符串,比如close时,能够返回这个字符串在对应中的数字2, 这在解析和保存以及后续发送中是很有用的。 """ return self.dbc_info.get_message_by_frame_id(frame_id).get_signal_by_name(signal_name).\ choice_string_to_number(value_str) if __name__ == '__main__' : dbc_info = DbcInfo('D:test.dbc' ) print (dbc_info.get_message_name(520 ))
如果想进行 can 报文修改,需要注意的是,直接给的数据不一定符合要求,需要保证修改数值在 signal 的最大最小范围内,同时保证该值符合定义中的取值间隔,可采用下述函数进行 check,保证输入数值符合要求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def check_value_meet_norms (self, frame_id, signal_name, value ): """ check value meet norms and return closest value based on scale factor 检查输入是否符合规范,同时输出符合规范的最接近输入value值的value 如果你要用脚本修改can报文,但是修改的值如果不符合要求,给入会报错, 该函数保证修改值符合规范且接近用户期望值 """ max_value = self.get_signal_config_maximum(frame_id, signal_name) min_value = self.get_signal_config_minimum(frame_id, signal_name) scale_value = self.get_signal_config_scale(frame_id, signal_name) if value > max_value: if isinstance (scale_value, int ): return int (max_value) return max_value elif value < min_value: if isinstance (scale_value, int ): return int (max_value) return min_value else : num = round (value / scale_value) if isinstance (scale_value, int ): return int (num * scale_value) return num * scale_value
参考