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++ 代码

解决方案 »

  1.   


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

  2.   


    C++ 算法代码
    #define CRC16typedef 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() */
      

  3.   

    C#的代码:http://www.cnblogs.com/canny/archive/2004/12/27/82470.html
      

  4.   

    如果是一个实际的应用程序的话,我觉得应该用汇编写CRC校验,象这一句“向右移位,移出位为1”,在汇编里面就一条指令。用C++和C#编译完成后的代码可能是汇编的几十倍甚至几百倍。处理大型数据会有问题。当然,如果是做实验的话,用什么语言就无所谓了。
      

  5.   

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