crc16位校验码c#算法,可用马上结贴!

wanabe 2011-04-19 12:44:59
crc16位校验码c#算法,可用马上结贴!

举个例子
输入字节数组byte[]{ 47 78 00 01 00 00 00 BC 00 00 00 01 00 00 00 BC 00 02 54 D2}

得出校验码 0x6A6B
...全文
4454 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
frankayn 2013-05-26
  • 打赏
  • 举报
回复
非常感谢walkghost!!! 用于计算 “CRC16=X16+X15+X2+1,即权值=0xA001”,反转ansi-crc16(右移); 0x8005(左移)和0xA001(右移)只是高低位互反,有些硬件的存储模式不一样,会根据情况调整使用的具体方法. x16+x12+x5+1为ccitt-crc16。 CRC的正序和反转问题,比如前面ccitt-crc16的正序是0x1021,如果是反转就是0x8408(就是将0x1021倒过来低位变高位)为什么要反转?这是因为数据传输可能是先传低位再传高位(比如串口就是低位在前高位在后)。反转的CRC算法与正序类似,需要注意移位的方向相反。 在walkghost提供的文章中简单改动,用于嵌入式系统。再次感谢! unsigned short crc2(unsigned char *message, unsigned int len) { u16 xda, xdapoly; u8 i, j, xdabit; xda = 0xFFFF; xdapoly = 0xA001; for (i = 0; i < len; i++) { xda ^= message[i]; for (j = 0; j < 8; j++) { xdabit = (u8)(xda & 0x01); xda >>= 1; if (xdabit == 1) xda ^= xdapoly; } } return xda; }
walkghost 2011-04-20
  • 打赏
  • 举报
回复
我只做过这一种CRC16的算法。实在不行你就拿VC6把他们给你的C++代码的算法编译成DLL,然后用C#调用吧。
walkghost 2011-04-20
  • 打赏
  • 举报
回复
PS:查表也是另外一种算法。
walkghost 2011-04-20
  • 打赏
  • 举报
回复
我提供的算法在我使用的CRC16校验的过程中是没有问题的。
qldsrx 2011-04-20
  • 打赏
  • 举报
回复
我现在开始怀疑输入的字节数组有误,你确定是byte[]{ 47 78 00 01 00 00 00 BC 00 00 00 01 00 00 00 BC 00 02 54 D2}吗?
我现在也头疼了,CRC16的算法就那么一个,但是版本却五花八门,没有找到两个能计算出相同结果的版本。与此相比,CRC32的版本也是很多,但是比较了下结果都一样。CRC32的结果是可以验证的,RAR中就用了那个校验的,如果和RAR中校验不一样的就肯定是错误的RAR计算,现在CRC16的结果无法验证,不知道谁的正确,不管结果是什么,但都不影响校验,你现在唯一能做的,就是问对方要CRC16的C++源码版本,然后根据它那个版本翻译到C#中,只有这样才能保证校验结果完全一样。
这里有个功能强大的CRC的C#版本:http://www.codeproject.com/articles/35134/How-to-calculate-CRC-in-Csharp.aspx
这里也有个版本,功能也不差,项目本身有错误,你只要复制里面的CRCTool类的代码处理用就可以了:http://www.codeproject.com/KB/cs/marcelcrcencoding.aspx
我已经验证过了,CRC-CCITT的校验结果不一样,但是CRC32的校验结果完全一样,因此计算方法上应该是没问题的,什么造成的不一样也无从分析,因为我就压根不知道谁对谁错。
wanabe 2011-04-19
  • 打赏
  • 举报
回复
crc-16/ccitt
wanabe 2011-04-19
  • 打赏
  • 举报
回复
是啊。这个我还是知道的。。。关键就是他算的和我算的不一样
qldsrx 2011-04-19
  • 打赏
  • 举报
回复
另外关于CRC校验的验证是这样的:
当你对一串字节数组计算出校验码后,将得到的校验码拼接到原来的字节数组后面,CRC16的话就拼接2个字节上去,发送新的字节数组给对方,对方将收到的字节数组进行CRC校验,其校验结果应该为0
wanabe 2011-04-19
  • 打赏
  • 举报
回复
我看看
qldsrx 2011-04-19
  • 打赏
  • 举报
回复

static ulong CRC_any(byte[] blk_adr, ulong ulPoly, ulong ulInit, ulong ulXorOut, ulong ulMask)
{
ulong crc = ulInit;
byte ucByte;
int blk_len = blk_adr.Length;
int i;
bool iTopBitCRC;
bool iTopBitByte;
ulong ulTopBit;
if (ulMask > 0xffff)
ulTopBit = 0x80000000;
else
ulTopBit = ((ulMask + 1) >> 1);

for (int j = 0; j < blk_len; j++)
{
ucByte = blk_adr[j];
for (i = 0; i < 8; i++)
{
iTopBitCRC = (crc & ulTopBit) != 0;
iTopBitByte = (ucByte & 0x80) != 0;
if (iTopBitCRC != iTopBitByte)
{
crc = (crc << 1) ^ ulPoly;
}
else
{
crc = (crc << 1);
}
ucByte <<= 1;
}
}
return (ulong)((crc ^ ulXorOut) & ulMask);
}

经检验,这段CRC校验代码肯定正确,可计算任意位数的CRC,如果得不到你想要的CRC值,那是参数设置上的问题,下面就对参数进行详细解释:
第一个参数:输入要校验的字节数组。
第二个参数:Poly值,如果是CRC16,那么就是0x8005,如果是CRC-CCITT,那么就是0x1201,这些值网上可以查到。
第三个参数:CRC初始值,这个很重要,一般我们都是用0作为初始值,但是你的例子中是用0xffff作为初始值,你之所以得到不同的结果,就是这个CRC初始值作怪,询问下对方,那个CRC初始值是多少。
第四个参数:取反输出设置,用在加密上,一般设置0即可。
第五个参数:标志位,如果你你是CRC16,就用0xFFFF,输出16位校验码,如果是CRC8,就用0xFF,输出8位校验码。
GeminiXXXCC 2011-04-19
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 qldsrx 的回复:]

引用 20 楼 wanabe 的回复:
反正是不对呀,我看好像也没问题
郁闷,别人用c++算的是0x6A6B,我算的是0xA4E5。。。校验不过。。。

能不能让他给出C++的源码,只要照着翻译到C#中就可以了。

-----------------
我现在死活理解不了那个多项式除法,怎么就可以无视借位直接用异或运算来着,其它的都看懂了。
[/Quote]

对啊,楼主有C++代码,就照着用C#写一下就OK。
注意数据长度和符号就行。
qldsrx 2011-04-19
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 wanabe 的回复:]
反正是不对呀,我看好像也没问题
郁闷,别人用c++算的是0x6A6B,我算的是0xA4E5。。。校验不过。。。
[/Quote]
能不能让他给出C++的源码,只要照着翻译到C#中就可以了。

-----------------
我现在死活理解不了那个多项式除法,怎么就可以无视借位直接用异或运算来着,其它的都看懂了。
wanabe 2011-04-19
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 geminixxxcc 的回复:]

按照我们公司的CRC16算法,楼主这20个数据数组得到的校验和是0x01d9。
我们这边有单片机的C,MFC的C++,还有C#三种语言写的检验函数,都是这个结果...
[/Quote]
我用你的也是这个结果,有crc-ccitt的吗
wanabe 2011-04-19
  • 打赏
  • 举报
回复
对方说是CRC-CCITT
GeminiXXXCC 2011-04-19
  • 打赏
  • 举报
回复
按照我们公司的CRC16算法,楼主这20个数据数组得到的校验和是0x01d9。
我们这边有单片机的C,MFC的C++,还有C#三种语言写的检验函数,都是这个结果...
wanabe 2011-04-19
  • 打赏
  • 举报
回复
我正在装VC试试,看看到底谁错了
wanabe 2011-04-19
  • 打赏
  • 举报
回复
反正是不对呀,我看好像也没问题
郁闷,别人用c++算的是0x6A6B,我算的是0xA4E5。。。校验不过。。。
GeminiXXXCC 2011-04-19
  • 打赏
  • 举报
回复
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace Tools
{
static class Calculate
{
public static ushort BytesCheck(byte[] bytes, int length)
{
ushort result = 0;
for (int i = 0; i < length; ++i)
{
result = ByteCheck(result, bytes[i]);
}
return result;
}

public static ushort BytesCheck(List<byte> bytes, int length)
{
ushort result = 0;
for (int i = 0; i < length; ++i)
{
result = ByteCheck(result, bytes[i]);
}
return result;
}

public static ushort BytesCheck(List<List<byte>> bytes)
{
ushort result = 0;
foreach (List<byte> buffer in bytes)
{
foreach (byte data in buffer)
{
result = ByteCheck(result, data);
}
}
return result;
}

public static ushort ByteCheck(int crc, byte data)
{
uint m = (uint)(crc << 8 | data);
for (int j = 0; j < 8; ++j)
{
if (((m <<= 1) & (uint)0x1000000) != 0)
{
m ^= (uint)0x800500;
}
}
return (ushort)(m >> 8);
}
}
}

前几天和同事调试了一天的SerialPort通讯,应该没问题了。
qldsrx 2011-04-19
  • 打赏
  • 举报
回复
额,你给的那个好像已经是C#版本的了,现在问题就是不知道哪个对?不过我猜测都可以用。
qldsrx 2011-04-19
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wanabe 的回复:]
我网上 找 了个是 这样的,看看有没没问题,
public static ushort getCRC_CCITT(byte[] data, int len)
{
byte hbit = 0;
ushort crc = 0xffff;

for (int i = 0; i < len; i++)
{
hbit = (byte)((crc & 0xff0……
[/Quote]
发现我这里的版本和你找的有出入,前面那个CRC的表是一样的,只不过后面那个getCRC_CCITT不一样,我还是按照你给的来修改下吧。
加载更多回复(13)

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧