张宁的个人博客

莫道君行早,更有早行人。

cantools库 ③使用cantools解析DBC文件

张宁的个人博客/发布时间:2023-07-21/分类:软件&硬件/ 浏览量:9366

《cantools库 ①快速了解入门》知道,使用cantools.database.load_file()读取的DBC文件包含以下信息:

  • DBC文件版本

  • 节点信息

  • message信息(包含具体signal信号)

我们可以使用cantools对其进行进一步解析,这里我们重点介绍对于message信息的解析。

解析DBC文件Message和Signal信号

1. 获取DBC文件Message信号清单

可以使用 dbc.messages 方法对DBC中的Message对象进行打包,并批量显示。Message对象将会被打包成列表数据

import can
import cantools
import cantools.database
import cantools.database.can.signal

if __name__ == "__main__":
    dbc1 = cantools.database.load_file("dbc/can_test.dbc")   #解析DBC文件
    #1.读取message/nodes/buses对象
    dbcx = dbc1.messages #打包文言message对象
    #dbcy = dbc1.nodes    #打包节点nodes对象
    #dbcz = dbc1.buses    #打包总线nodes对象
    print(dbcx)

输出如下:

这里列表内信号格式为:message('THU_516', 0x516, False, 32, None),其含义为:'THU_516'为其mesaage的name,0x516为message的id。

[message('THU_50A', 0x50a, False, 8, None), message('GW_3FC', 0x3fc, False, 64, None), message('GW_28B', 0x28b, False, 8, None), message('GW_17A', 0x17a, False, 64, None), message('THU_530', 0x530, False, 8, None), message('THU_516', 0x516, False, 32, None)]

2. 根据Message的name或者id直接解析对应的Message信号

在步骤1中,获取到message('THU_516', 0x516, False, 32, None)这个信号,所以可以使用'THU_516'或者0x516来解析单个meaasge。

import can
import cantools
import cantools.database
import cantools.database.can.signal
        
if __name__ == "__main__":
    dbc1 = cantools.database.load_file("dbc/can_test.dbc")  #解析DBC文件
    #1.读取message/nodes/buses对象
    dbcx = dbc1.messages #打包文言message对象
    #messagex = dbc1.get_message_by_name("THU_516")  #通过name获取报文对象
    messagey = dbc1.get_message_by_frame_id(0x516)   #通过id地址获取报文对象
    print(messagey)

这里分别使用了dbc.get_message_by_name()函数和dbc.get_message_by_frame_id()函数。其输出入下:

message('THU_516', 0x516, False, 32, None)

3. 解析meaasge中的signal信号

import can
import cantools
import cantools.database
import cantools.database.can.signal
        
if __name__ == "__main__":
    dbc1 = cantools.database.load_file("dbc/can_test.dbc")  #解析DBC文件
    signalx = dbc1.get_message_by_frame_id(0x516).signals  #通过message获取message对象,并通过signals获取信号对象
    print(signalx)

这里通过对message对象使用.signal方法来获取signal对象列表。输出如下:

[signal('HU_CurrentLocationValid', 7, 1, 'big_endian', False, 0, 1, 0, 0, 1, '/', False, None, None, None, None), ... ...]

这里每个signal我们可以通过遍历来单独输出,其具体含义为:

    # 打印信号详细信息
    for signal in signalx:
        if signal.name =="IP_TotalOdometer":   #筛选信号
            cantools.database.decode_signal(signal, raw_value)  
            print(f"Name: {signal.name}")
            print(f"Start bit: {signal.start}")
            print(f"Bit length: {signal.length}")
            print(f"byte_order: {signal.byte_order}")
            print(f"Is_signed: {signal.is_signed}")
            print(f"raw_initial: {signal.raw_initial}")
            print(f"Raw_invalid: {signal.raw_invalid}")
            print(f"conversion: {signal.conversion}")
            print(f"Minimum: {signal.minimum}")
            print(f"Maximum: {signal.maximum}")
            print(f"Unit: {signal.unit}")
            print(f"comment: {signal.comment}")
            print(f"receivers: {signal.receivers}")
            print(f"is_multiplexer: {signal.is_multiplexer}")
            print(f"multiplexer_ids: {signal.multiplexer_ids}")
            print(f"multiplexer_signal: {signal.multiplexer_signal}")
            print(f"offset: {signal.offset}")
            print(f"spn: {signal.spn}")

-完-

文章关键词
python
CAN
cantools
DBC
发表评论