2016-07-28 1222 views
2

我需要验证CRC8-SAE-J1850消息,因此编写了一个脚本,该脚本读取日志并需要从那里计算CRC8(非ZERO)以匹配他们与日志中的CRC8值一起检查,然后检查工具链中的哪一步导致麻烦。了解CRC8 SAE J1850(正常)与“零”的结果

无论如何,我花了一些时间来查看文档,SO帖子和其他人的源代码,但我想坚持使用python更简单的文本处理和接口到我的其他工具。

我发现了在SourceForge上evansneath's Python CRC Implementation一些代码,是很好的直线前进,想搏一搏,但我想如预期它不工作(也许我理解的东西完全错了,但我坚持在这里):

def crc(msg, div, code='11111111'): 
    """Cyclic Redundancy Check 
     Generates an error detecting code based on an inputted message and divisor in the form of a polynomial representation. 
     Arguments: 
     msg: The input message of which to generate the output code. 
     div: The divisor in polynomial form. For example, if the polynomial of x^3 + x + 1 is given, this should be represented as '1011' in the div argument. 
     code: This is an option argument where a previously generated code may be passed in. This can be used to check validity. If the inputted code produces an outputted code of all zeros, then the message has  no errors. 
    Returns: 
     An error-detecting code generated by the message and the given divisor. 
    """ 

    msg = msg + code 
    msg = list (msg) 
    div = list (div) 

    for i in range (len (msg) - len (code)): 
     if msg[i] == '1': 
      for j in range (len (div)): 
       msg[i+j] = str ((int (msg[i+j])+int (div[j]))%2) 

    return ''.join (msg[-len (code):]) 

#Testing: 
# Use a divisor that simulates: CRC8 SAE J1850 x^8+x^4+x^3+x^2+x^0 
div = '100011101'#0x1D with leading 1 as given by polynomial 
msg = '10101001' # 0xA9, just for a Test 

print('Input message:', hex(int(msg,2))) 
print('Polynomial:', hex(int(div,2))) 

o = '11111111' 
z = '00000000' 

code = crc(msg, div, o) 

print('CRC8 code:', hex(int(code,2))) 

# Test for output code of '00000000' respectively '11111111' proving that the function worked correctly 
print('Success:', crc(msg, div, code) == o) 

我检查了结果使用这个发电机: CRC Generator这似乎是唯一一个特色CRC8 SAE J1850零和非零。

现在有趣的部分:为零上述代码工作得很好。

不幸的是,我从我想要检查的软件中得到的CRC代码被初始化,并与两个工具提供完全不同的结果的0xFF('11111111')进行检查。 到目前为止,我甚至无法找到一些脱节的问题(我会评价最有可能的情况),或者通过上述脚本计算出的解决方案和网站上的解决方案之间的数学联系。 该网站符合软件的结果,但上面的python部分没有。

任何人都可以指向我可能错过的文档,或者是另一个问题吗? 在网站上输入消息时,我已经检查了MSB/LSB问题,并尝试使用0xFE进行初始化,如其他代码所示。但没有成功......然而,大多数例子都是基于零的,我没有问题。

编辑

我检查的计算和通过手的示例去以及打印每一个步骤和所取得的相同。所以在数学上它看起来是正确的,但是SAE除了追加'11111111'这一行然后按位异或,然后移位直到再次出现一个前导符,异或等等,并且将剩余的?这一定是我的理解问题。

Test 1 --------------------------- 
Input message: 0xa9 
Polynome: 0x11d 
['1', '0', '1', '0', '1', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', 1'] 
/
['1', '0', '0', '0', '1', '1', '1', '0', '1'] 
= 
current message: ['1', '0', '1', '0', '1', '0', '0', '1', '1', '1', '1', '1', '1 ', '1', '1', '1'] 
shift 0 Bits 
1 XOR 1 = 0 
0 XOR 0 = 0 
1 XOR 0 = 1 
0 XOR 0 = 0 
1 XOR 1 = 0 
0 XOR 1 = 1 
0 XOR 1 = 1 
1 XOR 0 = 1 
1 XOR 1 = 0 
current message: ['0', '0', '1', '0', '0', '1', '1', '1', '0', '1', '1', '1', '1 ', '1', '1', '1'] 
shift 2 Bits 
1 XOR 1 = 0 
0 XOR 0 = 0 
0 XOR 0 = 0 
1 XOR 0 = 1 
1 XOR 1 = 0 
1 XOR 1 = 0 
0 XOR 1 = 1 
1 XOR 0 = 1 
1 XOR 1 = 0 
current message: ['0', '0', '0', '0', '0', '1', '0', '0', '1', '1', '0', '1', '1 ', '1', '1', '1'] 
shift 5 Bits 
1 XOR 1 = 0 
0 XOR 0 = 0 
0 XOR 0 = 0 
1 XOR 0 = 1 
1 XOR 1 = 0 
0 XOR 1 = 1 
1 XOR 1 = 0 
1 XOR 0 = 1 
1 XOR 1 = 0 
CRC8 code: 0xab 

Reverse Calculation: Check 
['1', '0', '1', '0', '1', '0', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1'] 
/
['1', '0', '0', '0', '1', '1', '1', '0', '1'] 
= 
current message: ['1', '0', '1', '0', '1', '0', '0', '1', '1', '0', '1', '0', '1', '0', '1', '1'] 
shift 0 Bits 
1 XOR 1 = 0 
0 XOR 0 = 0 
1 XOR 0 = 1 
0 XOR 0 = 0 
1 XOR 1 = 0 
0 XOR 1 = 1 
0 XOR 1 = 1 
1 XOR 0 = 1 
1 XOR 1 = 0 
current message: ['0', '0', '1', '0', '0', '1', '1', '1', '0', '0', '1', '0', '1', '0', '1', '1'] 
shift 2 Bits 
1 XOR 1 = 0 
0 XOR 0 = 0 
0 XOR 0 = 0 
1 XOR 0 = 1 
1 XOR 1 = 0 
1 XOR 1 = 0 
0 XOR 1 = 1 
0 XOR 0 = 0 
1 XOR 1 = 0 
current message: ['0', '0', '0', '0', '0', '1', '0', '0', '1', '0', '0', '0', '1', '0', '1', '1'] 
shift 5 Bits 
1 XOR 1 = 0 
0 XOR 0 = 0 
0 XOR 0 = 0 
1 XOR 0 = 1 
0 XOR 1 = 1 
0 XOR 1 = 1 
0 XOR 1 = 1 
1 XOR 0 = 1 
0 XOR 1 = 1 
CRC correct: True 

回答

0

我解决它。

从来没有提到过,对于SAE J1850,输入与0xFF异或。即使C代码马克阿德勒提供的国家精确地说,在crc ^= 0xff;然而它并没有帮助我明白我的问题是什么。

这不是一个错误,我的代码工作正常,但它是我假设的前提。

这就是为什么C代码没有帮助我解决问题,因为我从来没有理解这是第一个问题。

SAE J1850计算(具有XORin 0xFF,XORout 0xFF,非反射,非反转,多项式0x1D)的经校正的代码按位如下。

积分为代码保留evensneath on github,我只是改变了输入。

def crc(msg, div, code='11111111'): 
"""Cyclic Redundancy Check 
Generates an error detecting code based on an inputted message 
and divisor in the form of a polynomial representation. 
Arguments: 
    msg: The input message of which to generate the output code. 
    div: The divisor in polynomial form. For example, if the polynomial 
     of x^3 + x + 1 is given, this should be represented as '1011' in 
     the div argument. 
    code: This is an option argument where a previously generated code may 
     be passed in. This can be used to check validity. If the inputted 
     code produces an outputted code of all zeros, then the message has 
     no errors. 
Returns: 
    An error-detecting code generated by the message and the given divisor. 
""" 
# Append the code to the message. If no code is given, default to '1111111' 
# Uncomment every occurence of msg_XORIN if not CRC-8 SAE J1850 
msg_XORIN = [] # XOR the input before appending the code 
msg_XORIN = [str((int(msg[i])+1) %2) for i in range(len(list(msg)))] 
msg = msg_XORIN 

div = list(div) 
msg = list(msg) + list(code) # Convert msg and div into list form for easier handling 

# Loop over every message bit (minus the appended code) 
for i in range(len(msg)-len(code)): 
    # If that messsage bit is not one, shift until it is. 
    if msg[i] == '1': 
     for j in range(len(div)): 
      # Perform modulo 2 (== XOR) on each index of the divisor 
      msg[i+j] = str((int(msg[i+j])+int(div[j]))%2) 

# Output the last error-checking code portion of the message generated 

return ''.join(msg[-len(code):]) 

该问题的测试用例可以结转。调用一次生成CRC,再次调用msg +生成的crc来验证。

好来源:http://reveng.sourceforge.net/crc-catalogue/1-15.htm#crc.cat-bits.8

+0

从你的描述“这是永远不会提到的SAE J1850的输入与0xFF异或“,我认为你还没有完成。只有在链接CRC计算时才有“输入”,即一次计算CRC块,其中输入是前面块的CRC。如果您所做的只是计算消息的CRC,那么除了消息和长度之外,没有其他输入。然后规范提供了什么来初始化寄存器('init')以及什么是异或 - 输出('xorout')。 –

+0

一旦你明白了这一点,那么当链接时为什么需要_initial_ exclusive或带有'xorout'是为了重建上次运行的寄存器内容。 –

1

即CRC通常与这些参数定义:

width=8 poly=0x1d init=0xff refin=false refout=false xorout=0xff check=0x4b name="CRC-8/SAE-J1850" 

crcgen将采取,并产生C语言代码来计算CRC。如果你喜欢,你可以很容易地把它翻译成Python。下面是从crcgen在C逐位程序:

#include <stdint.h> 

unsigned crc8sae_j1850_bit(unsigned crc, unsigned char const *data, size_t len) { 
    if (data == NULL) 
     return 0; 
    crc ^= 0xff; 
    while (len--) { 
     crc ^= *data++; 
     for (unsigned k = 0; k < 8; k++) 
      crc = crc & 0x80 ? (crc << 1)^0x1d : crc << 1; 
    } 
    crc &= 0xff; 
    crc ^= 0xff; 
    return crc; 
} 

所列链接CRC计算器页面上“零”的版本有这些参数,只要改变初始和xorout值为零:

width=8 poly=0x1d init=0x00 refin=false refout=false xorout=0x00 check=0x37 name="CRC-8/SAE-J1850-ZERO" 

这里是crcgen在C逐位例程一个:

#include <stdint.h> 

unsigned crc8sae_j1850_zero_bit(unsigned crc, unsigned char const *data, size_t len) { 
    if (data == NULL) 
     return 0; 
    while (len--) { 
     crc ^= *data++; 
     for (unsigned k = 0; k < 8; k++) 
      crc = crc & 0x80 ? (crc << 1)^0x1d : crc << 1; 
    } 
    crc &= 0xff; 
    return crc; 
} 
+0

在我只要你可以在网站资源选择CRC8 SAE J1850 ZERO或正常。根据我工作的制造商,两者都可能适用。 – AnyOneElse

+0

我明白你的观点,我尝试过这个工具,但是你并没有真正涉及到我的问题。我不想Zero,但我想出了任何原因,上面的代码与Zero零件的webresource相同,但是如果我使用FF初始化并最终化(分别为webtool),则不会返回相同的结果“11111111”),但我不明白为什么。 – AnyOneElse

+0

我不打算尝试调试发布在您的问题中的Python代码。我提供了正确计算CRC的方法。这个问题中的代码对一个很长(可能非常长的实际消息)的ASCII 0和1的字符串进行了长时间的划分,这不是现实世界中计算CRC的方式。 –