CAN BLF包解析和播包发送(一):CAN dbc解析

CAN DBC解析

CAN dbc文件是什么

CAN DBC 指的是CAN 报文的格式定义。简单地说,通过CAN 总线通信的数据类型可以用DBC文件来读取和理解。一般采用can editor进行编辑和查看。can editor是vector提供的编辑工具。
DBC 是处理8字节十六进制CAN 报文和原始CAN 数据的识别和转换的最常用方法。一个CAN 帧中的数据可以分成8个单byte的值、64个单bit值、一个64-bit 值或这些值的任何组合。数据字段最多可以包含8个字节的数据。一个CAN 帧可以包含0到64个单独的信号(对于64个通道,它们都将是二进制的)。
DBC报文一帧可以称作message,而message中的每一个信号称作signal。其中message包含:

  • id,CAN message id,一般以16进制显示;
  • name, CAN message name;
  • CAN 报文的类型(CAN 标准帧/扩展帧或CAN FD 标准帧/扩展帧)
  • 数据长度代码(DLC)–CAN 报文中数据的长度

singal中包含:

  • 信号名称:signal name, 消息中存在的信号的名称
  • 单位:信号中存在的物理数据的单位
  • 起始位:信号的起始位
  • 位计数:信号的位计数
  • 类型:数据类型
  • Factor(系数):信号的转换系数
  • Offset(偏移):信号的转换偏移
  • 最小和最大的信号值
  • comment, 信号说明

好,废话不多说,直接进入正题,dbc解析~

DBC解析

dbc文件解析采用python,原因是Python有dbc文件解析的库,可以直接使用,比较方便。dbc解析采用的是cantools这个库文件,只需要安装这个库即可。
安装方法:

pip3 install cantools

使用时,直接import cantools即可。
下面为常用接口的介绍说明:

dbc_file = "******"
dbc_info = cantools.db.load_file(dbc_file)    #创建一个dbc数据库对象

直接使用时,下述附代码,可直接复制使用。

# -*- coding: utf-8 -*-
#####
"""
# author:vehicle_ma, 2023/2/10
"""
######

import cantools

class 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)   #直接返回message的所有信息

    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    #这里返回的是message中signal的list,包含一个message中所有的signal

    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')
    #test,根据自己需求使用上述函数即可
    #frame_id输入10进制即可,同时必须是int型数据,不能是字符串
    print(dbc_info.get_message_name(520))

如果想进行can报文修改,需要注意的是,直接给的数据不一定符合要求,需要保证修改数值在signla的最大最小范围内,同时保证该值符合定义中的取值间隔,可采用下述函数进行check,保证输入数值符合要求。

    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

cantools官方包链接: https://www.cnpython.com/pypi/cantools.

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值