A. Can message introduction
CAN is a controller local network (Controller area Network, CAN) abbreviation, is by the development and production of automotive electronic products known as the German Bosch development, and eventually become the International Standard (ISO 11898), is one of the most widely used in the international field bus. In North America and Western Europe, the CAN bus protocol has become a standard bus for automotive computer control systems and embedded industrial control LANs, and has a J1939 protocol designed for large trucks and heavy machinery vehicles based on can.
The CAN bus transmits data in a message unit. Can message can be divided into standard frame and extended frame according to frame format, the standard frame is can frame with 11-bit identifier, and the extension frame is can frame with 29-bit identifier. According to the frame type can be divided into: 1. Send data from the sending node to other nodes; 2. Remote frames: Request to other nodes to send a data frame with the same identifier; 3. Error frame: Indicates that a bus error has been detected; 4. Overload frame: Overload frame is used to provide an additional delay between data frames (or remote frames). There are two coding formats: Intel format and Motorola format, the Motorola format is no better than the Intel format in terms of coding advantages and disadvantages, except that the user chooses it according to the designer's custom. Of course, for the user, before parsing, we must know what kind of coding format, otherwise, can not guarantee the correct interpretation of the meaning of the signal. The following is a 8-byte encoding of Can bus signal as an example, a detailed analysis of the difference between the two.
Intel encoded Format
When the data length of a signal is not more than 1 bytes (8 bits) and the signal is implemented in one byte (that is, the signal is not implemented across bytes): The high position of the signal (S_MSB) will be placed at the high level of the byte, and the signal's low (S_LSB) will be placed at that byte's low. When a signal has a data length of more than 1 bytes (8 bits) or the data length is no more than one byte but is implemented in a double-byte manner: the high position of the signal (S_MSB) will be placed at a higher-byte (MSB) level, and the low (S_LSB) signal will be placed at a low byte (LSB) lower position.
Motorola coded Format
When the data length of a signal is not more than 1 bytes (8 bits) and the signal is implemented in one byte (that is, the signal is not implemented across bytes): The high position of the signal (S_MSB) will be placed at the high level of the byte, and the signal's low (S_LSB) will be placed at that byte's low. When a signal has a data length of more than 1 bytes (8 bits) or the data length is no more than one byte but is implemented in a double-byte manner: the high position of the signal (S_MSB) will be placed at a low byte (MSB) high, and the signal Low (S_LSB) will be placed at a high byte (LSB) low. As can be seen, when the data length of a signal is not more than 1Byte, Intel and Motorola two format coding results are no different, exactly the same. When the data length of the signal exceeds 1Byte, the coding results of the two are obviously different.
two. Can message conversion tool requirements Analysis
1, support the standard frame of the can message conversion, extended frame is not supported
2, can message support Intel, Motorola two kinds of coding, first support Motorola format, post-append Intel format
3, the tool has a certain fault-tolerant processing capacity, report generation ability
4, the development of a unified format to facilitate the user to modify the test script 5, increase interactive mode, keyboard input, console output, for example:
Hint Language: StartBit:length:minValue:maxValue:setValue
Input: 35:1:0:1:1
Or: 35:1:::1
Console output: 00 00 00 00 08 00 00 00
examples of Intel and Motorola encodings:
three. Interactive mode
The code is as follows:
Import SYS print (----------------Welcome to the can message conversion Tool interactive mode----------------) print ("Please enter the can signal in the format: startbit:length: MinValue:maxValue:setValue ") Print (" For example: 32:1:0:1:1 ") print (" or omit MinValue and maxvalue:35:1:::1 ") print (" Please press RETURN again "at the end of signal input) #十进制转换成二进制list def octtobin (octnum, bit): while (octnum!= 0): Bit.append (octnum%2) octnum = Int (Oct NUM/2) for I in range (64-len (bit)): Bit.append (0) sig = [] Startbit = [] length = [] SetValue = [] #输入CAN信号 W Hile true:input_str = input () if not Len (INPUT_STR): Break if (Input_str.count (":") <4): pri NT ("Input format error, parameter missing SetValue, please re-enter.") ") Continue if (Input_str.split (": ") [4]==" "): Print (" SetValue parameter cannot be null, please re-enter. ") ") Continue Sig.append (INPUT_STR) #解析CAN信号 for I in range (Len (SIG)): Startbit.append (int (Sig[i].split (": ") [0])) length.append (int (Sig[i].split (":") [1])) setvalue.append (int (Sig[i].split (":") [4]) #CAN数组存放CAN报文值 CAN = [] for I in range ($): Can.append ( -1) for IIn range (len (startbit)): #长度超过1Byte的情况, temporarily does not support if (LENGTH[I]>16): print ("can signal length more than 2Byte, temporarily not supported ...")
") Sys.stdin.readline () sys.exit () #长度未超过1Byte的情况且未跨字节的信号 if ((Startbit[i]%8 + length[i]) <=8): For j in Range (Length[i]): bit = [] #setValue的二进制值按字节位从低到高填 octtobin (setvalue[i
],bit) #填满字节长度值 if (can[startbit[i]+j]==-1): can[startbit[i]+j] = bit[j] #字节存在冲突 Else:print (Sig[i] + "byte bit conflict, generate can message failure ... ") Sys.stdin.readline () sys.exit () #跨字节的信号 else: #高位位数和低位位数 Highle n = 8-startbit[i]%8 Lowlen = length[i]-Highlen bit = [] #setValue的二进制值按字节位从低到高填 Octtob
In (setvalue[i],bit) #先填进信号的高位 to J1 in range (Highlen): if (can[startbit[i]+j1]==-1):
CAN[STARTBIT[I]+J1] = bit[j1] #字节存在冲突 else: Print (Sig[i] + "byte bit conflict, generate can message failure ...
") Sys.stdin.readline () Sys.exit () #再填进信号的低位 to J2 in range (Lowlen):
if (can[(int (STARTBIT[I]/8)-1) *8+j2]==-1): can[(int (STARTBIT[I]/8)-1) *8+j2] = Bit[highlen+j2] #字节存在冲突 Else:print (Sig[i] + "byte bit conflict, generate can message failure ...
") Sys.stdin.readline () Sys.exit () #剩余位默认值设为0 for I in range: if (can[i]==-1): Can[i] = 0 #----------------Converts the binary list to hexadecimal output every 8 bits----------------#其中, map () converts the number in the list to a string, followed by a reverse order of every 8 bits in the Motorola format . Join () converts the binary list into a binary string. Int () converts the binary string to decimal #hex () and then converts the decimal to 16, upper () to uppercase, two lstrip () deletes "0X", #zfill () fills two bits,
The output does not wrap, separated by a space print (hex int ('. Join (Map (str,can[7::-1)), 2)). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (". Join (Map (str,can[15:7:-1])), 2). Upper (). Lstrip (" 0 "). Lstrip (" X "). Zfill (2) +" ", end=" ") Print (Hex ( Int ('. Join (Map (str,can[23:15:-1))), 2). UppeR (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (int ('. Join (Map (str,can[31:23:-1))), 2). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (int ('. Join (Map (str,can[39:31:-1)), 2)). Upper (). Lstrip ("0 "). Lstrip (" X "). Zfill (2) +" ", end=" ") Print (Hex (int ('. Join (Map (str,can[47:39:-1))), 2). Upper (). Lstrip (" 0 "). Lstrip ("X"). Zfill (2) + "", end= "") Print (hex int ('. Join (Map (str,can[55:47:-1))), 2). Upper (). Lstrip ("0"). Lstrip ("X").
Zfill (2) + "", end= "") Print (hex int ('. Join (Map (str,can[63:55:-1))), 2). Upper (). Lstrip ("0"). ("X"). Lstrip (2))
Run Screenshots:
Error Tip:
four. Configuration Item Mode
The configuration file is as follows:
# #注释:: Start #编码格式: 0=intel;1=motorola encodetype=1 #帧格式: 0= standard frame; 1 = extended frame; Canmode=0 #帧类型: 0 = data frame; cantype=0 #默认初始值 (0~1) Defaultvalue=0 #MSG定义 msgname=bcm_frp01 msgid=0x2cd #长度 (BYTE) msglength=8 #signal定义 #sigName =name:startbit:length: MinValue:maxValue:setValue #sigName =reversesw:25:6:0:1:13 #sigName =trunk_backdoor_sts:33:2:0:1:2 #sigName = Drvunlockstate:37:2:0:1:3 #sigName =headlamplowbeam:40:8:0:1:60 #sigName =hoodstatus:51:1:0:1:0 #sigName = headlamphighbeam:52:1:0:1:0 #sigName =rldoorstatus:59:1:0:1:0 #sigName =rrdoorstatus:58:1:0:1:0 #sigName = psgdoorstatus:57:2:0:1:0 signame=one:0:8:0:255:165 signame=two:24:12:0:4095:1701 sigName=Three:54:5:0:31:25:: End:
: Start #编码格式: 0=intel;1=motorola encodetype=1 #帧格式: 0= standard frame; 1 = extended frame; Canmode=0 #帧类型: 0 = data frame; cantype=0 #默认初始值 (0~1) Defaultvalue=0 #MSG定义 MSGNAME=BCM_FRP msgid=0x2cd #长度 (BYTE) msglength=8 #signal定义 #sigName =name:startbit:length: MinValue:maxValue:setValue #sigName =reversesw:25:6:0:1:13 #sigName =trunk_backdoor_sts:33:2:0:1:2 #sigName = Drvunlockstate:37:2:0:1:3 #sigName =headlamplowbeam:40:8:0:1:60 #sigName =hoodstatus:51:1:0:1:0 #sigName =headlamphighbeam
: 52:1:0:1:0 #sigName =rldoorstatus:59:1:0:1:0 #sigName =rrdoorstatus:58:1:0:1:0 #sigName =psgdoorstatus:57:2:0:1:0 Signame=one:35:1:0:1:1:: End
The code is as follows:
#!/usr/bin/python DefaultValue = 0 Signame = [] Startbit = [] length = [] MinValue = [] MaxValue = [] SetValue = [] #CAN数组
Store can message value can = [] logFile = open ("Log.txt", "W") def parseconfig (): config = open ("Config.txt", "r") Count = 0
IsError = False for line in config:line = Line.strip () #注释 if (Line.find ("#") >=0): Continue #开始标记 elif (Line.find (":: Start") >=0): Count = count + 1 isError = False if (count>1): Signame.clear () startbit.clear () Leng Th.clear () setvalue.clear () Continue else:continue El if (IsError = = True): Continue #编码格式 elif (Line.find ("Encodetype") >=0): Encodetyp E = line.split ("=") [1] if (encodetype!= "1"): IsError = True print (str (count) + ". Can message generation failed ... Currently only supports MOTorola encoding format, the Intel encoding format is not supported temporarily. ") Logfile.write ("%d. Can message generation failed ... Only Motorola-encoded formats are currently supported and the Intel encoding format is not supported. \ n "% count" continue #帧格式 elif (Line.find ("Canmode") >=0): Canmode = Line.sp Lit ("=") [1] if (Canmode!= "0"): IsError = True print (str (count) +. Can message generation failed ... Only standard frames are currently supported, and extended frames are temporarily not supported. ") Logfile.write ("%d. Can message generation failed ... Only standard frames are currently supported, and extended frames are temporarily not supported. \ n "% count" continue #帧类型 elif (Line.find ("Cantype") >=0): Cantype = Line.sp Lit ("=") [1] if (Cantype!= "0"): IsError = True print (str (count) +. Can message generation failed ... Currently, only data frames are supported, and no other frames are supported temporarily. ") Logfile.write ("%d. Can message generation failed ... Currently, only data frames are supported, and no other frames are supported temporarily. \ n "% count" continue #默认初始值 elif (Line.find ("defaultvalue") >=0): Global def Aultvalue defaultvalue = Int (line.split ("=") [1]) #MSG名称 elif (Line.find ("Msgname")>=0): Msgname = line.split ("=") [1] #MSGID elif (Line.find ("MSGID") >=0): MSGID = Line.split ("=") [1] #MSG长度 elif (Line.find ("Msglength") >=0): Msglength = line.split ("=") [1
] #signal定义 elif (Line.find ("Signame") >=0): Signame.append (Line.split (":") [0].split ("=") [1]) Startbit.append (int (Line.split (":") [1])) length.append (int (Line.split (":") [2]) #minV Alue.append (int (Line.split (":") [3])) #maxValue. Append (int (line.split (":") [4]) setvalue.append (int
(Line.split (":") [5]))
Elif (Line.find (":: End") >=0): Rv,errmsg = Getcanmessage () if (RV = "-1"): IsError = True print (str (count) +. Can message generation failed ... "+ errmsg" logfile.write ("%d. Can message generation failed ...") %s\n "% (count,errmsg)) Continue print (str (count) +". Can message generation success.。 ") Logfile.write ("%d. Can message Generation success ... \ n '% count] #----------------------------output header information----------------------------print ("msgname\t\tmsg Id\t\tmsglen\t\tmsgdata ") logfile.write (" msgname\t\tmsgid\t\tmsglen\t\tmsgdata\n ") if (Len (msgName)
<8): Print (Msgname + "\t\t", end= "") Logfile.write ("%s\t\t"% msgname) Else: Print (Msgname + "\ T", end= "") Logfile.write ("%s\t"% msgname) print (MsgID + "\ t\t ", end=" ") Logfile.write ("%s\t\t "% MsgID) print (Msglength +" \t\t ", end=" ") logFile. Write ("%s\t\t"% msglength) #----------------Converts the binary list to hexadecimal output every 8 bits----------------#其中, map () The numbers are converted to strings, followed by a reverse # '. Join () in the Motorola format, which converts a binary list into a binary string, int () converts a binary string to a decimal #hex () and then converts the decimal to 16. Upper () is converted to uppercase, two Lstrip () is deleted "0X", #zfill () fills two bits, the output does not wrap, and the print is separated by a space (hex int ('. JOin (Map (str,can[7::-1])), (2)). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (int (". Join" ( Str,can[15:7:-1]), (2)). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (int ('). Join (Map (STR,CA N[23:15:-1]), (2)). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (". Join" (Map str,can[31: 23:-1]), (2)). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (int ('). Join (Map (str,can[39:31:-1 ]), 2). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (int ('. Join (Map (str,can[47:39:-1))), 2 ). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (int ('. Join (Map (str,can[55:47:-1))), 2). Up Per (). Lstrip ("0"). Lstrip ("X"). Zfill (2) + "", end= "") Print (Hex (int ('. Join (Map (str,can[63:55:-1))), 2). Upper () . Lstrip ("0"). Lstrip ("X"). Zfill (2)) Logfile.write ("%s"% hex (int ('. Join (Map (str,can[7::-1))), 2). Upper (). Lstr IP ("0"). Lstrip ("X"). ZfilL (2)) Logfile.write ("%s"% hex int ('. Join (Map (str,can[15:7:-1)), 2)). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2
) Logfile.write ("%s"% hex int ('. Join (Map (str,can[23:15:-1))), 2). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2))
Logfile.write ('%s '% hex (int ('. Join (Map (str,can[31:23:-1))), 2). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2))
Logfile.write ('%s '% hex (int ('. Join (Map (str,can[39:31:-1))), 2). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2))
Logfile.write ('%s '% hex (int ('. Join (Map (str,can[47:39:-1))), 2). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2))
Logfile.write ('%s '% hex (int ('. Join (Map (str,can[55:47:-1))), 2). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2))
Logfile.write ("%s\n"% hex (int ('. Join (Map (str,can[63:55:-1))), 2). Upper (). Lstrip ("0"). Lstrip ("X"). Zfill (2)) Config.close () #十进制转换成二进制list def octtobin (octnum, bit): while (octnum!= 0): Bit.append ( octnum%2) Octnum = Int (OCTNUM/2) for I in range (64-len (bit)): Bit.append (0) #获取CAN报文值 def getcanmessage (): Can.clear () For I in range ($): Can.append ( -1) for I in Range (len (startbit)): #长度超过1Byte的情况, temporarily does not support if (Leng TH[I]>16): ErrMsg = "can signal length of more than 2Byte, temporarily not supported ..." "#print (Signame[i] + errmsg) return"-1 ", ErrMsg #长度未超过1Byte的情况且未跨字节的信号 if (STARTB It[i]%8 + length[i]) <=8): for J in Range (Length[i]): bit = [] #setValue的二进制
Value is Octtobin (setvalue[i],bit) #填满字节长度值 if (can[startbit[i]+j]==-1) by byte bit from low to High: CAN[STARTBIT[I]+J] = bit[j] #字节存在冲突 else:errmsg = "Byte bit conflict, generate can message failure ..."
"#print (Signame[i] + errmsg) return"-1 ", ErrMsg #跨字节的信号 else:
#高位位数和低位位数 Highlen = 8-startbit[i]%8 Lowlen = length[i]-Highlen bit = [] #setValue的二进制值按字节位从低到高填 octtobin (Setvalu
E[i],bit) #先填进信号的高位 for J1 in range (Highlen): if (can[startbit[i]+j1]==-1): CAN[STARTBIT[I]+J1] = bit[j1] #字节存在冲突 else:errmsg = "bytes Bit conflict, generate can message failure ...
"#print (Signame[i] + errmsg) return"-1 ", ErrMsg #再填进信号的低位 For J2 in range (Lowlen): if (can[(int (STARTBIT[I]/8)-1) *8+j2]==-1): can[(int (startbit[ I]/8)-1) *8+j2] = bit[highlen+j2] #字节存在冲突 else:errmsg = "byte bit conflict, build CA N Message failure ... "#print (Signame[i] + errmsg) return"-1 ", ErrMsg #剩余位设为默认值 to I in range (
: if (can[i]==-1): can[i] = defaultvalue #若无错误则返回正确值 return "0", "success!" If __name__ = = "__main__": #调用parseConfig () function starts executing program parseconfig ()
Run Result:
1. Can message Generation success ...
msgname msgID msglen msgdata
bcm_frp01 0x2cd 8 A5/
2. Can message Generation success ...
msgname msgID msglen msgdata
bcm_frp 0x2cd 8 00 00 00 00 08 00 00 00