计算CAN BUS的CRC 15

时间:2015-06-18 18:06:23

标签: c# biginteger crc

我需要计算CAN总线的CRC校验和。

情境:

我的输入看起来总是如下(其中x10*标记多次x|标记了一个部分,-是输入法的更改,lbLabeltbTextBoxcb是{{1} }):

  • ComboBox:0
  • lb:11x
  • tb:x
  • cb:x
  • cb:1
  • lb:4x => tb
  • Convert.ToString(8-64 / 8, 2).PadLeft(4, '0');:8-64x,=> tb
  • 8-64 % 8 == 0:15x => tb
  • CRC of above:1
  • lb:11
  • lb:1111111
  • lb:111

返回此布局:

lb

示例:

0|11*x-x|x-1-4*x|64*x|15*x-1|11|1111111|111

此字符串将由以下字符串扩展名处理,因此最多5位数字相互跟随:

00101010101000100100101010100101010(missing 15*x CRC sum)1111111111111

之后,以下方法返回除数:

public static string Correct4CRC(this string s)
{
    return s.Replace("00000", "000001").Replace("11111", "111110");
}

我遇到的唯一问题是public static BigInteger CreateDivisor(string s) { var i = BigInteger.Parse(s); var d = BigInteger.Pow(i, 15) + BigInteger.Pow(i, 14) + BigInteger.Pow(i, 10) + BigInteger.Pow(i, 8) + BigInteger.Pow(i, 7) + BigInteger.Pow(i, 4) + BigInteger.Pow(i, 3) + 1; return d; } 的部分:

^

我知道这可能会因为要求代码而被关闭,但请耐心等待,因为我真的不明白。另一个问题是,没有真正的文档可以帮助我搞清楚。

无论如何,如果您知道一个解决我问题的好文档,请将其添加为评论。如果我得到它,我会自己检查并自己关闭答案。

1 个答案:

答案 0 :(得分:1)

我认为你的比特错误(用000001替换00000和用111110代替11111),因为它不能处理雪崩替换... 0000011110000变为0000011111000001.

这里http://blog.qartis.com/can-bus/似乎有一个例子。然后该页面链接到http://ghsi.de/CRC/index.php?Polynom=1100010110011001&Message=2AA80,生成一些用于计算CRC-15的C代码。

// 0000011110000 becomes 0000011111000001
public static string BitStuff(string bits)
{
    StringBuilder sb = null;

    char last = ' ';
    int count = 0;

    for (int i = 0; i < bits.Length; i++)
    {
        char ch = bits[i];

        if (ch == last)
        {
            count++;

            if (count == 5)
            {
                if (sb == null)
                {
                    // The maximum length is equal to the length of bits
                    // plus 1 for length 5, 2 for length 9, 3 for length 13...
                    // This because the maximum expanion is for
                    // 00000111100001111... or 11111000011110000...
                    sb = new StringBuilder(bits.Length + (bits.Length - 1) / 4);
                    sb.Append(bits, 0, i);
                }

                sb.Append(ch);
                last = ch == '0' ? '1' : '0';
                sb.Append(last);
                count = 1;

                continue;
            }
        }
        else
        {
            last = ch;
            count = 1;
        }

        if (sb != null)
        {
            sb.Append(ch);
        }
    }

    return sb != null ? sb.ToString() : bits;
}

// Taken from http://ghsi.de/CRC/index.php?Polynom=1100010110011001&Message=2AA80
public static string Crc15(string bits)
{
    var res = new char[15]; // CRC Result
    var crc = new bool[15];

    for (int i = 0; i < bits.Length; i++)
    {
        bool doInvert = (bits[i] == '1') ^ crc[14];         // XOR required?

        crc[14] = crc[13] ^ doInvert;
        crc[13] = crc[12];
        crc[12] = crc[11];
        crc[11] = crc[10];
        crc[10] = crc[9] ^ doInvert;
        crc[9] = crc[8];
        crc[8] = crc[7] ^ doInvert;
        crc[7] = crc[6] ^ doInvert;
        crc[6] = crc[5];
        crc[5] = crc[4];
        crc[4] = crc[3] ^ doInvert;
        crc[3] = crc[2] ^ doInvert;
        crc[2] = crc[1];
        crc[1] = crc[0];
        crc[0] = doInvert;
    }

    // Convert binary to ASCII
    for (int i = 0; i < 15; i++)
    {
        res[14 - i] = crc[i] ? '1' : '0';
    }

    return new string(res);
}

然后:

string bits = "0101010101010000000"; // Example data
string crc = Crc15(bits);

bits = bits + crc;
bits = BitStuff(bits);

bits += '1'; // CRC delimiter

bits += 'x'; // ACK slot TODO

bits += '1'; // ACK delimiter
bits += "1111111"; // EOF

请注意,您必须输入ACK插槽的值