使用dbcc工具根据dbc文件生成CAN报文解析c代码

本文介绍了DBC文件的用途和格式,并详细阐述了一个名为dbcc的工具,该工具用于解析DBC文件并解码CAN报文。通过在Ubuntu上编译dbcc源码,然后使用特定的命令行选项运行,可以解析不同的CAN帧。文章还展示了如何根据CANid调用相应的解包函数,以及结构体的设计来存储解码后的数据。
摘要由CSDN通过智能技术生成

dbcc工具在github上的地址:
https://github.com/howerj/dbcc
仓库地址:
git@github.com:howerj/dbcc.git

源码下载到Ubuntu后,使用gcc编译即可,编译完成后,就可以在源码当前目录生成dbcc可执行程序。
编译方法:
make CC=gcc

dbcc工具使用方法:
可以先使用./dbcc -h看下使用帮助说明。

基本的使用方法是,在dbcc参数中跟上dbc文件即可。例如:./dbcc DBC_FILE

示例dbc文件(片段):

BO_ 2F8 DATE_TIME_SZ: 8 Host
 SG_ DISP_MILLISEC : 0|44@1+ (1,0) [0|3298534883327] "ms" Vector__XXX

BO_ 330 LICENSE: 8 Host
 SG_ LICENSE_NUMBER : 24|16@1+ (1,0) [0|65535] "" Vector__XXX
 SG_ LICENSE_EXT : 40|16@1+ (1,0) [0|65535] "" Vector__XXX
 SG_ LICENSE_CITY : 16|8@1+ (1,0) [0|255] "" Vector__XXX
 SG_ LICENSE_PROV : 0|16@1+ (1,0) [0|65535] "" Vector__XXX

BO_ 19A VEH_INFO: 8 Host
 SG_ VEH_TYPE : 8|8@1+ (1,0) [0|255] "" Vector__XXX
 SG_ VEH_COMPANY : 0|8@1+ (1,0) [0|255] "" Vector__XX把

dbc文件的格式介绍请阅读博客:DBC文件解析
注意:上面的dbc文件中的can id,我转换成十六进制了,因为生成的代码中,CAN id是以十六进制的形式表示的,所以为了方便查看,我把本来是十进制表示的can id转换成十六进制了。

转换后的代码中,核心的函数是unpack_message,unpack_message函数源码:

int unpack_message(can_obj_ailsz_h_t *o, const unsigned long id, uint64_t data, uint8_t dlc, dbcc_time_stamp_t time_stamp) {
	assert(o);
	assert(id < (1ul << 29)); /* 29-bit CAN ID is largest possible */
	assert(dlc <= 8);         /* Maximum of 8 bytes in a CAN packet */
	switch (id) {
	case 0x199: return unpack_can_0x199_TERMINAL_ID(o, data, dlc, time_stamp);
	case 0x19a: return unpack_can_0x19a_VEH_INFO(o, data, dlc, time_stamp);
	case 0x1a1: return unpack_can_0x1a1_V_VEH_SZ(o, data, dlc, time_stamp);
	case 0x2f8: return unpack_can_0x2f8_DATE_TIME_SZ(o, data, dlc, time_stamp);
	case 0x330: return unpack_can_0x330_LICENSE(o, data, dlc, time_stamp);
	case 0x412: return unpack_can_0x412_GPS_PO_CAN_SZ(o, data, dlc, time_stamp);
	case 0x414: return unpack_can_0x414_GPS_PO_EXTS_CAN_SZ(o, data, dlc, time_stamp);
	case 0x500: return unpack_can_0x500_AD_MODE_SZ(o, data, dlc, time_stamp);
	default: break; 
	}
	return -1; 
}

这个函数先解析出CAN id,然后根据CAN id调用对应的can帧的解析函数,取出can报文里面的值后存放到o指针指向的结构体中。所以比较粗糙的调用过程是:
定义can_obj_ailsz_h_t 类型的全局变量o,然后收到can数据后,调用unpack_message函数,将o的指针传进去,将can报文传进去,例如:

can_obj_ailsz_h_t o;
can_frame can_frame;
if(read(can_fd, &can_frame, sizeof(v2x_can_frame_t)) > 0)
{
	unpack_message(&o, can_frame.can_id, *(uint64_t *)can_frame->data, can_frame.can_dlc, 0);
}
//读取o结构体中的各个字段的值

结构体can_obj_ailsz_h_t中定义了各个CAN报文中的信号字段,如下所示:

typedef PREPACK struct {
	//........此处省略一部分...........
	can_0x412_GPS_PO_CAN_SZ_t can_0x412_GPS_PO_CAN_SZ;
	can_0x414_GPS_PO_EXTS_CAN_SZ_t can_0x414_GPS_PO_EXTS_CAN_SZ;
	can_0x500_AD_MODE_SZ_t can_0x500_AD_MODE_SZ;
} POSTPACK can_obj_ailsz_h_t;

代码中,根据dbc文件中定义的每个can帧的信号,定义出一个一个的结构体,这个总的结构体中包含了dbc文件定义的所有的can帧信息。这部分十分不难,各位读者可自行分析。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值