Matlab 编程技巧:通过正则表达式解析DBC ⽂件
本⽂通过函数regexp的正则表达式功能,解析DBC⽂件中的报⽂帧信息。DBC⽂件中的信号等其他信息都可以通过类似的⽅式解析出来。⽂章⽬录
1 DBC ⽂件
DBC数据库⽂件是⽤来描述CAN⽹络节点间数据通讯的⼀种⽂件,做汽车CAN⽹络通信的话肯定是绕不开DBC⽂件的。关于DBC⽂件格式的内容可以参考另⼀位博主的⽂章,本⽂后⾯也会引⽤到其中的⼀些知识内容。
DBC⽂件的格式有很强的规律性,所以可以很轻松地通过函数regexp解析出其中地信息。实际上,Matlab提供了封装好的函数
canDatabase(),可以更加快速准确地解析DBC中的帧和信号。本⽂没有使⽤封装的函数,是希望以DBC为例,训练正则表达式的应⽤技巧,以便在遇到其他需求没有现成的函数时,⾃⼰也能造出轮⼦。
2 正则表达式函数
在Matlab中,正则表达式函数是regexp。关于正则表达式的语法不⽤死记硬背,⽤到的时候去查Matlab帮助⽂档就⾏。3 实例:解析报⽂帧信息
⾸先,⾃⼰新建⼀个DBC⽂件,⼀般是通过CANdb++这类DBC⼯具。不过这⾥为了⽅便就不去⼿动建⽴了,直接把如下内容拷贝进⽂本⽂件,并命名为DBC_Demo.dbc。
其中,BO_开头的那⼀⾏就是报⽂帧,其格式定义如下:
4 Matlab 脚本
1)⾸先要将DBC⽂件的⽂本内容导⼊到Matlab中。在Matlab命令⾏输⼊BS_:BU_: AVNT ACU HUD BO_996 HUD_1_B: 8 HUD  SG_ HUD_OffSt : 0|1@0- (1,0) [-1|0] "" ACU,AVNT  SG_ HUD_HeightLv : 7|7@0+ (1,0) [0|127] "lv" ACU,AVNT  SG_ HUD_BrightnessLv : 15|4@0+ (1,0) [0|15] "lv" ACU,AVN
T CM_ BO_ 996 "The message of control hud status";CM_ SG_ 996 HUD_BrightnessLv "Control hud brighness level";
1
2
3
4
5
6
7
8DBCText = fileread('DBC_Demo.dbc')
1
就会将DBC⽂件内容作为字符串返回到DBCText变量中。
2)⽤正则表达式提取出报⽂帧那⼀⾏,也就是BO_开头的那⼀⾏。这⾥开始就要研究BO_这⼀⾏的模式了。
1. BO关键字,在正则表达式模式中直接⽤BO_完全匹配即可;
2. 报⽂ID,是若⼲个数字可以⽤\d+表⽰1个或以上的阿拉伯数字;
3. 报⽂名称,⼀般是由字母、数字和下划线组成的字符串,所以可以⽤\w+表⽰;
4. 报⽂数据域字节数,⽆符号整数,直接⽤\d+表⽰;
5. ⽹络节点:⼀般是由字母、数字和下划线组成的字符串,所以可以⽤\w+表⽰;
所以报⽂帧这⼀⾏的模式可以写为:
中间的\s+或者\s*代表空格符。
然后就可以通过regexp解析出BO这⼀⾏了。注意加上’match’这个参数以返回字符串。
这⾥要注意,返回的的是⼀个字符串组成的元胞数组。由于demo中只有⼀个报⽂帧的定义,所以元胞数组中只有⼀个字符串。
3)解析元胞数组中的每⼀个报⽂帧⾏,提取出信息,这⾥只以⼀个报⽂帧为例。⾸先解析出报⽂ID,只要把之前的pattern改⼀下就⾏。>> pattern = 'BO_\s*\d+\s+\w+:\s+\d+\s+\w+';
1>> BO_Cell = regexp(DBCText,pattern,'match')
1
这⾥⽤了正则表达式的上下⽂匹配,语法是*(?=test)和(?<=test)*,其中test是上下⽂内容。这样就能根据上下⽂匹配出报⽂帧了。再⽐如说报⽂名称也⽤上下⽂匹配:
5 总结
⽤正则表达式解析DBC⽂件⽐较容易,只是需要⼀点耐⼼慢慢地调。除了报⽂帧,其他信号、波特率、节点等信息都能通过类似的⽅式解析。这样的技术也可以迁移到其他⽂件,只要我们了解了该⽂件的书写规则就⾏。pattern_MessageId = '(?<=BO_\s*)\d+(?=\s+\w+:\s+\d+\s+\w+)';
1>> MessageName_Cell = regexp(BO_Cell{1},'(?<=BO_\s*\d+\s+)\w+(?=:\s+\d+\s+\w+)','match')MessageName_Cell =  1×1 cell 数组    {'HUD_1_B'}
1
2
matlab定义函数表达式3
4
5
6
7