我需要计算CAN总线的CRC校验和。
情境:
我的输入看起来总是如下(其中x
为1
或0
,*
标记多次x
,|
标记了一个部分,-
是输入法的更改,lb
是Label
,tb
是TextBox
,cb
是{{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;
}
的部分:
^
我知道这可能会因为要求代码而被关闭,但请耐心等待,因为我真的不明白。另一个问题是,没有真正的文档可以帮助我搞清楚。
无论如何,如果您知道一个解决我问题的好文档,请将其添加为评论。如果我得到它,我会自己检查并自己关闭答案。
答案 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插槽的值