200分求C#代码 [C# CRC16 校验问题] (有源C++ 代码)

shilei831115 2009-02-11 01:19:17

200分求教以下要求的C# 代码,最后入口要封装成一个。

回答的人多了,都符合要求的话 在追加100分。


原意描述:

CRC 是先调入一值是全“1”的 16 位寄存器,然后调用一过程将消息中连续的 8 位字
节各当前寄存器中的值进行处理。仅每个字符中的 8Bit 数据对 CRC 有效,起始位和停止位
以及奇偶校验位均无效。
CRC 校验字节的生成步骤如下:
① 装一个 16 位寄存器,所有数位均为 1。
② 取被校验串的一个字节与 16 位寄存器的高位字节进行“异或”运算。运算结果放
入这个 16 位寄存器。
③ 把这个 16 寄存器向右移一位。
④ 若向右(标记位)移出的数位是 1,则生成多项式 1010 0000 0000 0001 和这个寄
存器进行“异或”运算;若向右移出的数位是 0,则返回③。
⑤ 重复③和④,直至移出 8 位。
⑥ 取被校验串的下一个字节
⑦ 重复③~⑥,直至被校验串的所有字节均与 16 位寄存器进行“异或”运算,并移位
8 次。
⑧ 这个 16 位寄存器的内容即 2 字节 CRC 错误校验码。
校验码按照先高字节后低字节的顺序存放。


C++ 代码
...全文
794 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
darkly001 2010-07-30
  • 打赏
  • 举报
回复


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Monitoring_On_line.ClassInfo
{
public class CRC16
{

public CRC16()
{
}


private readonly byte[] _auchCRCHi = new byte[]//crc高位表
{
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;

private readonly byte[] _auchCRCLo = new byte[]//crc低位表
{
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;


public ushort CalculateCrc16( byte[] buffer )
{
byte crcHi = 0xff; // 高位初始化

byte crcLo = 0xff; // 低位初始化

for ( int i = 0; i < buffer.Length; i++ )
{
int crcIndex = crcHi ^ buffer[ i ]; //查找crc表值

crcHi = (byte)( crcLo ^ _auchCRCHi[crcIndex ] );
crcLo = _auchCRCLo[ crcIndex ] ;
}

return (ushort)( crcHi << 8 | crcLo );
}



CalculateCrc16返回的是一个ushort类型的值,如果要返回Crc高字节和低字节,可重写CalculateCrc16函数为:
public ushort CalculateCrc16( byte[] buffer, out byte crcHi, out byte crcLo )
{
crcHi = 0xff; // high crc byte initialized
crcLo = 0xff; // low crc byte initialized

for ( int i = 0; i < buffer.Length - CRC_LEN; i++ )
{
int crcIndex = crcHi ^ buffer[ i ]; // calculate the crc lookup index

crcHi = (byte)( crcLo ^ _auchCRCHi[ crcIndex ] );
crcLo = _auchCRCLo[ crcIndex ] ;
}

return (ushort)( crcHi << 8 | crcLo );
}






}
}


调用方式:

private void button1_Click(object sender, EventArgs e)
{
byte[] by = new byte[2];
by[0] = Convert.ToByte("79", 16);
by[1] = Convert.ToByte("83", 16);
ClassInfo.CRC16 CRC = new Monitoring_On_line.ClassInfo.CRC16();

MessageBox.Show(CRC.CalculateCrc16(by).ToString("X"));
}

H_noob 2010-06-01
  • 打赏
  • 举报
回复
帮顶 UP↗
胖大叔_Pendas 2010-04-14
  • 打赏
  • 举报
回复
有分数就是好用,利益驱使一切,哎。
zhangshuang2n 2010-02-03
  • 打赏
  • 举报
回复
学习了,很有用
tmlihan 2009-07-07
  • 打赏
  • 举报
回复
找半天都找不到,结果楼主分这么多,一下就有了,价值激励的作用啊
shilei831115 2009-02-11
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 hhhh63 的回复:]
如果是一个实际的应用程序的话,我觉得应该用汇编写CRC校验,象这一句“向右移位,移出位为1”,在汇编里面就一条指令。用C++和C#编译完成后的代码可能是汇编的几十倍甚至几百倍。处理大型数据会有问题。

当然,如果是做实验的话,用什么语言就无所谓了。
[/Quote]

仅仅是应用而已

呵呵 已经搞定阿

马上揭帖
hhhh63 2009-02-11
  • 打赏
  • 举报
回复
如果是一个实际的应用程序的话,我觉得应该用汇编写CRC校验,象这一句“向右移位,移出位为1”,在汇编里面就一条指令。用C++和C#编译完成后的代码可能是汇编的几十倍甚至几百倍。处理大型数据会有问题。

当然,如果是做实验的话,用什么语言就无所谓了。
langcai1981 2009-02-11
  • 打赏
  • 举报
回复
帮顶了,二进制转换没用过,贴出7楼在博客园的代码!
using System;

namespace CRC
{
/// <summary>
/// CRC16 的摘要说明。
/// </summary>
public class CRC16:ICRC
{
#region CRC 16 位校验表

/// <summary>
/// 16 位校验表 Upper 表
/// </summary>
public ushort[] uppercrctab = new ushort[]
{
0x0000,0x1231,0x2462,0x3653,0x48c4,0x5af5,0x6ca6,0x7e97,
0x9188,0x83b9,0xb5ea,0xa7db,0xd94c,0xcb7d,0xfd2e,0xef1f
};

/// <summary>
/// 16 位校验表 Lower 表
/// </summary>
public ushort[] lowercrctab = new ushort[]
{
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef
};
#endregion

ushort crc = 0;

/// <summary>
/// 校验后的结果
/// </summary>
public long Value
{
get
{
return crc;
}
set
{
crc = (ushort)value;
}
}

/// <summary>
/// 设置crc 初始值
/// </summary>
public void Reset()
{
crc = 0;
}

/// <summary>
/// Crc16
/// </summary>
/// <param name="ucrc"></param>
/// <param name="buf"></param>
public void Crc(ushort ucrc,byte[] buf)
{
crc = ucrc;
Crc(buf);
}

/// <summary>
/// Crc16
/// </summary>
/// <param name="bval"></param>
public void Crc(int bval)
{
ushort h = (ushort)((crc >> 12) & 0x0f);
ushort l = (ushort)((crc >> 8 ) & 0x0f);
ushort temp = crc;
temp =(ushort)(((temp & 0x00ff) << 8) | bval);
temp =(ushort)(temp ^(uppercrctab[(h -1) + 1] ^ lowercrctab[(l - 1) + 1]));
crc = temp;
}


/// <summary>
/// Crc16
/// </summary>
/// <param name="buffer"></param>
public void Crc(byte[] buffer)
{
Crc(buffer,0,buffer.Length);
}

/// <summary>
/// Crc16
/// </summary>
/// <param name="buf"></param>
/// <param name="off"></param>
/// <param name="len"></param>
public void Crc(byte[] buf,int off,int len)
{
if (buf == null)
{
throw new ArgumentNullException("buf");
}

if (off < 0 || len < 0 || off + len > buf.Length)
{
throw new ArgumentOutOfRangeException();
}
for (int i = off; i < len ; i ++)
{
Crc(buf[i]);
}
}
}
}
泡面之夏 2009-02-11
  • 打赏
  • 举报
回复
友情帮顶
ls3697264 2009-02-11
  • 打赏
  • 举报
回复
UP
Fibona 2009-02-11
  • 打赏
  • 举报
回复
C#的代码:

http://www.cnblogs.com/canny/archive/2004/12/27/82470.html

shilei831115 2009-02-11
  • 打赏
  • 举报
回复
就看要求就可以了,

后面的C++ 代码 仅供参考
huarunwei 2009-02-11
  • 打赏
  • 举报
回复
难度太大,没能力解决,帮顶了。
tinalucky 2009-02-11
  • 打赏
  • 举报
回复
哈,好长的代码,没看,帮顶撒!
shilei831115 2009-02-11
  • 打赏
  • 举报
回复
顶者有分 阿
shilei831115 2009-02-11
  • 打赏
  • 举报
回复

C++ 算法代码


#define CRC16

typedef unsigned short crc;

#define CRC_NAME "CRC-16"

#define POLYNOMIAL 0x8005 //生成多项式

#define INITIAL_REMAINDER 0x0000 //寄存器初始化

#define FINAL_XOR_VALUE 0x0000





#define WIDTH (8 * sizeof(crc))

#define TOPBIT (1 << (WIDTH - 1))

#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8))

#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH))

//建立CRC16映射表

/*********************************************************************

*

* 函数名称: crcInit()

*

* 描述: Populate the partial CRC lookup table.

*

* 注意: This function must be rerun any time the CRC standard

* is changed. If desired,it can be run "offline"" and

* the table results stored in an embedded system'ss ROM.

*

*返回值: 空值.

*

********************************************************************/

void crcInit(void)

{

crc remainder;

int dividend;

unsigned char bit;

/*

* 计算所有可能的余数.

*/

for (dividend = 0; dividend < 256; ++dividend)

{

/*

* Start with the dividend followed by zeros.

*/

remainder = dividend << (WIDTH - 8);

/*

* 执行模2除法, 每次一位.

*/

for (bit = 8; bit > 0; --bit)

{

/*

* Try to divide the current data bit.

*/

if (remainder & TOPBIT)

{

remainder = (remainder << 1) ^ POLYNOMIAL;

}

else

{

remainder = (remainder << 1);

}

}

/*

* 储存结果到表中去

*/

crcTable[dividend] = remainder;

}

} /* crcInit() */







//返回值即为所求CRC值

/*********************************************************************

*

* Function: crcFast()

*

* Description: Compute the CRC of a given message.

*

* Notes: crcInit() must be called first.

*

* Returns: The CRC of the message.

********************************************************************/

crc crcFast(unsigned char const message[], int nBytes)

{



crc remainder = INITIAL_REMAINDER;

unsigned char data;

int byte;

/*

*使用多项式对消息求校验码,每次一个字节

*/

for (byte = 0; byte < nBytes; ++byte)

{

data = REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8));

remainder = crcTable[data] ^ (remainder << 8);

}



/*

* 最后剩余的就是CRC

*/

return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);



} /* crcFast() */

shilei831115 2009-02-11
  • 打赏
  • 举报
回复

C++ 代码如下

unsigned long LLHCRC::reflect(unsigned long data, unsigned char nBits)
{
unsigned long reflection = 0x00000000;
unsigned char bit;

/*
/*
* Reflect the data about the center bit.
*/
//for (bit = nBits-1; bit >=0 ; --bit)
for (bit = 0; bit < nBits ; ++bit)
{
/*
* If the LSB bit is set, set the reflection of it.
*/
if (data & 0x01)
{
reflection |= (1 << ((nBits - 1) - bit));
}

data = (data >> 1);
}

return (reflection);

}
void LLHCRC::crcInit(void)
{
crc remainder;
int dividend;
unsigned char bit;
/*
* Compute the remainder of each possible dividend.
*/
for (dividend = 0; dividend < 256; ++dividend)
{
/*
* Start with the dividend followed by zeros.
*/
remainder = dividend << (WIDTH - 8);

/*
* Perform modulo-2 division, a bit at a time.
*/
for (bit = 8; bit > 0; --bit)
{
/*
* Try to divide the current data bit.
*/
if (remainder & TOPBIT)
{
remainder = (remainder << 1) ^ POLYNOMIAL;
}
else
{
remainder = (remainder << 1);
}
}

/*
* Store the result into the table.
*/
crcTable[dividend] = remainder;
}
}
unsigned long LLHCRC::crcFast(unsigned char const message[], int nBytes)
{
unsigned char data;
int byte;
if(m_nWorkMode==0)
return crcFastSingle(message,nBytes);
/*
* Divide the message by the polynomial, a byte at a time.
*/
for (byte = 0; byte < nBytes; ++byte)
{
data = REFLECT_DATA(message[byte]) ^ (m_remainder >> (WIDTH - 8));
m_remainder = crcTable[data] ^ (m_remainder << 8);
}
return 0;//用GetCRC()得到最后的CRC值
}

///设置工作模式,0-计算完一组数据的CRC后,立即返回CRC值,
///1-可以计算多组数据,生成一个CRC值,调用者必须显示调用GETCRC()函数才能得到CRC
// 莫志勇 2008-8-13,
// 添加LLHCRC的工作模式,兼容原有的无工作模式的状态,
// 原有的LLHCRC只能计算计算一组数据的CRC,计算完毕立即返回CRC值,相当于工作模式0。
void LLHCRC::SetWorkMode(int nWorkMode)
{
m_nWorkMode=nWorkMode;
}
///必须在工作模式1下调用,否则只返回0
//读取一次CRC值后,CRC值自动回复到初始状态。可以再次计算。
unsigned long LLHCRC::GetCRC()
{
if(m_nWorkMode==1)
{
DWORD CRC=m_remainder;
m_remainder=INITIAL_REMAINDER;
return (REFLECT_REMAINDER(CRC) ^ FINAL_XOR_VALUE);
}
else
return 0;
}

unsigned long LLHCRC::crcFastSingle(unsigned char const message[], int nBytes)
{
if(m_nWorkMode==1)
return 0;

unsigned char data;
int byte;
unsigned long remainder=INITIAL_REMAINDER;
/*
* Divide the message by the polynomial, a byte at a time.
*/
for (byte = 0; byte < nBytes; ++byte)
{
data = REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8));
remainder = crcTable[data] ^ (remainder << 8);
}

return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
}

110,525

社区成员

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

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

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