计算 CAN 总线的 CRC 15

Calculate CRC 15 for CAN BUS

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

场景:

我的输入看起来总是如下所示(其中 x10* 多次标记 x|表示一个段,-是输入法的改变,lbLabeltbTextBoxcbComboBox):

哪个returns这个布局:

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

示例:

00101010101000100100101010100101010(missing 15*x CRC sum)1111111111111

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

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

在下面的方法之后 returns 除数:

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;
}

我遇到的唯一问题是 ^ 的部分:

public static string CRC(this string s)
{
    var dd = s.Correct4CRC();
    var dr = dd.CreateDivisor().ToString();
    int drl = dr.Length;
    var d = dd.Substring(0, drl).CreateDivisor();
    var f = d ^ dr.CreateDivisor();
    var p = true;
    while (p)
    {
        d = dd.Substring(0, drl).CreateDivisor();
        f = d ^ dr.CreateDivisor();
        p = d > dd.CreateDivisor();
    }
    return f.ToString();
}

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

无论如何,如果您知道一个很好的文档,可以解决我的问题,请将其添加为评论。知道了我自己去看看,自己关闭答案。

我认为您的比特填充是错误的(将 00000 替换为 000001,将 11111 替换为 111110),因为它不处理雪崩替换... 0000011110000 变为 0000011111000001。

此处http://blog.qartis.com/can-bus/ there seems to be an example. The page is then linked to 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 槽的值