当前位置:   article > 正文

汽车电子 -- DBC详解_dbc编写语法

dbc编写语法

关于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”用于描述信号的转换参数。

  1. “factor”是转换系数,用于确定从原始值到物理值的转换比例。
  2. “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
  • 1
  • 代码实现
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)
  • 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

2、python 解析DBC

安装cantools库

pip install cantools
  • 1

解析DBC文件

  • 导入cantools库并加载DBC文件
import cantools

# 加载DBC文件
db = cantools.database.load_file('example.dbc')
  • 1
  • 2
  • 3
  • 4
  • 解析节点
    可以使用db.nodes属性。这将返回一个包含所有节点的列表。我们可以遍历该列表来访问每个节点的属性:
# 遍历节点
for node in db.nodes:
    print("Node name: ", node.name)
    print("Node comment: ", node.comment)
    print()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 解析消息
    可以使用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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 解析信号
    可以使用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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3、更多参看

参看:Python之cantools

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/585889
推荐阅读
相关标签
  

闽ICP备14008679号