CRC12 ,16 ,32校验方法

CRC12 ,16 ,32校验方法

VB.NET语言版

1、CRC-16 

CRC-16码由两个字节构成,在开始时CRC寄存器的每一位都预置为1,然后把CRC寄存器与8-bit的数据进行异或,之后对CRC寄存器从高到低进行移位,在最高位(MSB)的位置补零,而最低位(LSB,移位后已经被移出CRC寄存器)如果为1,则把寄存器与预定义的多项式码进行异或,否则如果 LSB为零,则无需进行异或。重复上述的由高至低的移位8次,第一个8-bit数据处理完毕,用此时CRC寄存器的值与下一个8-bit数据异或并进行如前一个数据似的8次移位。所有的字符处理完成后CRC寄存器内的值即为最终的CRC值。
校验原理:
       1.设置CRC寄存器,并给其赋值FFFF(hex)。
  2.将数据的第一个8-bit字符与16位CRC寄存器的低8位进行异或,并把结果存入CRC寄存器。
  3.CRC寄存器向右移一位,MSB补零,移出并检查LSB。
  4.如果LSB为0,重复第三步;若LSB为1,CRC寄存器与多项式码相异或。
  5.重复第3与第4步直到8次移位全部完成。此时一个8-bit数据处理完毕。
  6.重复第2至第5步直到所有数据全部处理完成。
  7.最终CRC寄存器的内容即为CRC值。
实现方法:

 Function CRC16(data() As Byte) As String 
   Dim CRC16Lo As Byte, CRC16Hi As Byte   ’CRC寄存器 
   Dim CL As Byte, CH As Byte        ’多项式码&HA001 
   Dim SaveHi As Byte, SaveLo As Byte 
   Dim I As Integer 
   Dim Flag As Integer 

   CRC16Lo = &HFF 
   CRC16Hi = &HFF 
   CL = &H1 
   CH = &HA0 

   For I = 0 To Ubound(data) 
    CRC16Lo = CRC16Lo Xor data(I) ’每一个数据与CRC寄存器进行异或 
    For Flag = 0 To 7 
     SaveHi = CRC16Hi 
     SaveLo = CRC16Lo 
     CRC16Hi = CRC16Hi \\ 2      ’高位右移一位 
     CRC16Lo = CRC16Lo \\ 2      ’低位右移一位 

     If ((SaveHi And &H1) = &H1) Then ’如果高位字节最后一位为1 
      CRC16Lo = CRC16Lo Or &H80   ’则低位字节右移后前面补1 
     End If              ’否则自动补0 

     If ((SaveLo And &H1) = &H1) Then ’如果LSB为1,则与多项式码进行异或 
      CRC16Hi = CRC16Hi Xor CH 
      CRC16Lo = CRC16Lo Xor CL 
     End If 

    Next Flag 
   Next I 

   Dim ReturnData(1) As Byte 
   ReturnData(0) = CRC16Hi       ’CRC高位 
   ReturnData(1) = CRC16Lo       ’CRC低位 
   CRC16 = ReturnData 
  End Function 


 

C语言版本的

print?//   
// CRC16码表   
static WORD const wCRC16Table[256] = {   
    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,  
    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,  
    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,   
    0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,  
    0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,    
    0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,  
    0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,  
    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,  
    0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,  
    0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,     
    0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,  
    0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,  
    0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,  
    0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,  
    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,     
    0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,  
    0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,  
    0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,  
    0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,  
    0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,     
    0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,  
    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,  
    0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,  
    0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,  
    0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,    
    0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,  
    0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,  
    0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,  
    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,  
    0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,    
    0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,  
    0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040};  
//
// CRC16码表
static WORD const wCRC16Table[256] = { 
	0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
	0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
	0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 
	0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
	0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,  
	0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
	0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
	0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
	0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
	0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,   
	0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
	0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
	0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
	0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
	0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,   
	0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
	0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
	0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
	0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
	0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,   
	0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
	0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
	0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
	0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
	0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,  
	0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
	0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
	0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
	0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
	0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,  
	0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
	0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040}; 
然后在文件中加入下列函数: 

view plaincopy to clipboardprint?//   
// 函数功能: CRC16效验   
// 输入参数: pDataIn: 数据地址   
//           iLenIn: 数据长度              
// 输出参数: pCRCOut: 2字节校验值    
void CCRCDlg::CRC16(const CHAR* pDataIn, int iLenIn, WORD* pCRCOut)  
{  
    WORD wResult = 0;  
    WORD wTableNo = 0;  
  
    for(int i = 0; i < iLenIn; i++)  
    {  
        wTableNo = ((wResult & 0xff) ^ (pDataIn[i] & 0xff));  
        wResult = ((wResult >> 8) & 0xff) ^ wCRC16Table[wTableNo];  
    }  
  
    *pCRCOut = wResult;  
}  
//
// 函数功能: CRC16效验
// 输入参数: pDataIn: 数据地址
//           iLenIn: 数据长度           
// 输出参数: pCRCOut: 2字节校验值 
void CCRCDlg::CRC16(const CHAR* pDataIn, int iLenIn, WORD* pCRCOut)
{
	WORD wResult = 0;
	WORD wTableNo = 0;

	for(int i = 0; i < iLenIn; i++)
	{
		wTableNo = ((wResult & 0xff) ^ (pDataIn[i] & 0xff));
		wResult = ((wResult >> 8) & 0xff) ^ wCRC16Table[wTableNo];
	}

	*pCRCOut = wResult;
}
 
二.CRC16(MODBUS)

view plaincopy to clipboardprint?//   
// CRC MODBUS 效验   
// 输入参数: pDataIn: 数据地址   
//           iLenIn: 数据长度              
// 输出参数: pCRCOut: 2字节校验值    
void CCRCDlg::CheckCRCModBus(const CHAR* pDataIn, int iLenIn, WORD* pCRCOut)  
{  
    WORD wHi = 0;  
    WORD wLo = 0;  
    WORD wCRC;  
    wCRC = 0xFFFF;  
  
    for (int i = 0; i < iLenIn; i++)  
    {  
        wCRC = CalcCRCModBus(*pDataIn, wCRC);  
        pDataIn++;  
    }  
  
    wHi = wCRC / 256;  
    wLo = wCRC % 256;     
    wCRC = (wHi << 8) | wLo;  
  
    *pCRCOut = wCRC;  
}  
  
WORD CCRCDlg::CalcCRCModBus(CHAR cDataIn, WORD wCRCIn)  
{  
    WORD wCheck = 0;  
    wCRCIn = wCRCIn ^ cDataIn;  
  
    for(int i = 0; i < 8; i++)  
    {  
        wCheck = wCRCIn & 1;  
        wCRCIn = wCRCIn >> 1;  
        wCRCIn = wCRCIn & 0x7fff;  
  
        if(wCheck == 1)  
        {  
            wCRCIn = wCRCIn ^ 0xa001;  
        }  
        wCRCIn = wCRCIn & 0xffff;  
    }  
  
    return wCRCIn;  
}  
//
// CRC MODBUS 效验
// 输入参数: pDataIn: 数据地址
//           iLenIn: 数据长度           
// 输出参数: pCRCOut: 2字节校验值 
void CCRCDlg::CheckCRCModBus(const CHAR* pDataIn, int iLenIn, WORD* pCRCOut)
{
	WORD wHi = 0;
	WORD wLo = 0;
	WORD wCRC;
	wCRC = 0xFFFF;

	for (int i = 0; i < iLenIn; i++)
	{
		wCRC = CalcCRCModBus(*pDataIn, wCRC);
		pDataIn++;
	}

	wHi = wCRC / 256;
	wLo = wCRC % 256;	
	wCRC = (wHi << 8) | wLo;

	*pCRCOut = wCRC;
}

WORD CCRCDlg::CalcCRCModBus(CHAR cDataIn, WORD wCRCIn)
{
	WORD wCheck = 0;
	wCRCIn = wCRCIn ^ cDataIn;

	for(int i = 0; i < 8; i++)
	{
		wCheck = wCRCIn & 1;
		wCRCIn = wCRCIn >> 1;
		wCRCIn = wCRCIn & 0x7fff;

		if(wCheck == 1)
		{
			wCRCIn = wCRCIn ^ 0xa001;
		}
		wCRCIn = wCRCIn & 0xffff;
	}

	return wCRCIn;
} 
三.CRC16(CCITT的0XFFFF)

view plaincopy to clipboardprint?//   
// 函数功能: CRC16效验(CCITT的0XFFFF效验)   
// 输入参数: pDataIn: 数据地址   
//           iLenIn: 数据长度              
// 输出参数: pCRCOut: 2字节校验值     
void CCRCDlg::CRCCCITT(const CHAR* pDataIn, int iLenIn, WORD* pCRCOut)  
{  
    WORD wTemp = 0;   
    WORD wCRC = 0xffff;   
  
    for(int i = 0; i < iLenIn; i++)   
    {          
        for(int j = 0; j < 8; j++)   
        {   
            wTemp = ((pDataIn[i] << j) & 0x80 ) ^ ((wCRC & 0x8000) >> 8);   
  
            wCRC <<= 1;   
  
            if(wTemp != 0)    
            {  
                wCRC ^= 0x1021;   
            }  
        }   
    }   
  
    *pCRCOut = wCRC;  
}  


 2、32位操作方法

'VB源代码
'注意:本代码仅运行于VB 2005,不适用VB 2003

Public Class ClsoCRC
Public Shared ReadOnly Table As UInteger()

Shared Sub New()
ReDim Table(256)
For i As UInteger = 0 To 255
Dim r As UInteger = i
For j As Integer = 0 To 7
If (r And 1) <> 0 Then
r = (r >> 1) Xor 3988292384
Else
r >>= 1
End If
Next
Table(i) = r
Next
End Sub

Private _value As UInteger = UInteger.MaxValue

''' <summary>初始化类,重新计算CRC前请先调用本过程。</summary>
Public Sub Init()
_value = UInt32.MaxValue
End Sub

''' <summary>更新并计算单个字节。(追加方式)</summary>
''' <param name="b">数据字节。</param>
Public Sub UpdateByte(ByVal b As Byte)
_value = Table(UInt32toByte(_value) Xor b) Xor (_value >> 8)
End Sub

''' <summary>更新类并开始计算CRC。</summary>
''' <param name="data">需要计算的数据组。</param>
''' <param name="offset">偏移,一般设为0。</param>
''' <param name="size">大小,一般设为数据组的Length。</param>
Public Sub Update(ByVal data As Byte(), ByVal offset As UInt32, ByVal size As UInt32)
For i As UInteger = 0 To size - 1
_value = Table(UInt32toByte(_value) Xor data(offset + i)) Xor (_value >> 8)
Next
End Sub

''' <summary>获取CRC数据。</summary>
Public Function GetDigest() As UInt32
Return _value Xor UInt32.MaxValue
End Function

''' <summary>计算并获取CRC数据。(利用静态实例化实现)</summary>
''' <param name="data">需要计算的数据组。</param>
''' <param name="offset">偏移,一般设为0。</param>
''' <param name="size">大小,一般设为数据组的Length。</param>
Public Shared Function CalculateDigest(ByVal data As Byte(), ByVal offset As UInt32, ByVal size As UInt32) As UInt32
Dim crc As New ClsoCRC
'crc.Init()
crc.Update(data, offset, size)
Return crc.GetDigest
End Function

''' <summary>校验摘要</summary>
''' <param name="digest">摘要</param>
''' <param name="data">数据组</param>
''' <param name="offset">偏移</param>
''' <param name="size">大小</param>
Private Shared Function VerifyDigest(ByVal digest As UInt32, ByVal data As Byte(), ByVal offset As UInt32, ByVal size As UInt32) As Boolean
Return CalculateDigest(data, offset, size) = digest
End Function

''' <summary>返回BYTE (CLE添加)</summary>
Private Shared Function UInt32toByte(ByVal UInt32Value As UInteger) As Byte
Return UInt32Value Mod 256
End Function

End Class

 

http://www.cnblogs.com/clso/archive/2010/11/29/1891082.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值