CRC32和CRC16效验源码分享

1 篇文章 0 订阅

开发环境:VC6++,可以移植到其他环境

关于CRC效验原理可以参考博客https://blog.csdn.net/zjli321/article/details/52998468

CRC效验通常有两种方法,一种是模2除法,另一种是查表法(这种表也只先通过模2除法算好,然后调用)

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

#include<stdio.h>
/****用于填写CRC类型的的枚举选项****/
enum CrcInversionOption
{
    CrcInversionFalse=0,
    CrcInversionTure
    
};

/*******************************************************************************************/
/*Local Macro and Tyedef                                                                                                                                 */
/*******************************************************************************************/
typedef struct _Crc16Mode_Type
{
    unsigned short Polynom;
    unsigned short Seed;
    unsigned char IsDataInInversion;    //填enum类型是否反序
    unsigned char IsDataOutInversion;   //填enum类型是否反序
    unsigned short ResultXorData;       
} Crc16Mode_Type;

typedef struct _Crc32Mode_Type
{
    unsigned long Polynom;
    unsigned long Seed;
    unsigned char IsDataInInversion;    //填enum类型是否反序
    unsigned char IsDataOutInversion;   //填enum类型是否反序
    unsigned long ResultXorData;      
} Crc32Mode_Type;

 

/***************************************************************************************************
*时间:2019/05/30
*函数作用:求数据的按位反转
*函数名:unsigned long bitrev(unsigned long input, int bw) 
*形参内容:待输入的按位反转 unsigned long input  待输入的按位反转的长度 int bw
*
*返回值: 反转之后的值 var 
******************************************************************************************************/ 
static unsigned long bitrev(unsigned long input, int bw)  
{  
    int i;  
    unsigned long var;  
    var = 0;  
    for(i=0;i<bw;i++)  
    {  
        if(input & 0x01)  
        {  
            var |= 1<<(bw-1-i);  
        }  
        input>>=1;  
    }  
    return var;  
}

/*************************************************************************************************************
*时间:2019/06/01
*函数作用:求32位CRC的效验码、支持CRC32和CRC_MPEG_2的两种类型
*函数名:unsigned long Crc32_GetCrc(Crc32Mode_Type CrcMode, unsigned int *DataAddrStart, unsigned long Length)  
*形参内容:CrcMode CRC32类型参数   *DataAddrStart 要效验的数据首地址   Length要效验的数据长度
*反序多相式简写:
*返回值: 运算后的CRC效验码
***************************************************************************************************************/
unsigned long Crc32_GetCrc(Crc32Mode_Type CrcMode, unsigned char *DataAddrStart, unsigned long Length)
{
   unsigned int i,j = 0;
   unsigned char *data=DataAddrStart;
   unsigned long crc =CrcMode.Seed;

  if(CrcInversionFalse==CrcMode.IsDataInInversion)
  {
       while ((Length--) != 0)
       {  
           crc ^= (unsigned long)data[j] << 24;
           j++;

           for (i = 0; i < 8; ++i)
           {
             if ((crc & 0x80000000) != 0)
             {
                 crc = (crc << 1) ^ CrcMode.Polynom;    //0x04C11DB7
             }
             else
             {
                 crc <<= 1;
             }
           }
        }
  }

  if(CrcInversionTure==CrcMode.IsDataInInversion)
  {
        CrcMode.Polynom=bitrev(CrcMode.Polynom,32);   //因为上面输入反序算法有问题,所以当使用到输入反序的时候调用下面
        while((Length--)!=0) 
        {
            
            crc ^= (unsigned int)data[j];
        
            j++;

            for (i=0; i<8; i++)       //右移,相当于反转数据,同时也需要反转POLY
            {  
                if(crc&1)  
                {  
                    crc=CrcMode.Polynom^(crc>>1);  
                }  
                else  
                {  
                    crc=crc>>1;  
                }  
            }     
        }
      if(CrcInversionTure==CrcMode.IsDataOutInversion)   //判断数据输出是否需要反转      //输出反转,相当于算法的不翻转,与下面的反转抵消。
      {crc=bitrev(crc,32);}
   }

   if(CrcInversionTure==CrcMode.IsDataOutInversion)   //判断数据输出是否需要反转
   {crc=bitrev(crc,32);}
  
   return crc^=CrcMode.ResultXorData;

}

/*************************************************************************************************************
*时间:2019/05/31
*函数作用:求16位CRC的效验码、支持CRC16 IBM、MAXIM、USB、MODBUS、CCITT、CCITT-FALSE、X25、XMODEM和DNP九种模式
*函数名:unsigned long Crc32_GetCrc(Crc32Mode_Type CrcMode, unsigned int *DataAddrStart, unsigned long Length)  
*形参内容:CrcMode CRC16类型参数   *DataAddrStart 要效验的数据首地址   Length要效验的数据长度
*反序多相式简写:
*返回值: 运算后的CRC效验码
***************************************************************************************************************/
unsigned short Crc16_GetCrc(Crc16Mode_Type CrcMode, unsigned char *DataAddrStart, unsigned long Length)
{
    unsigned char *data=DataAddrStart;  //数据首地址  
    unsigned short wCRCin = CrcMode.Seed;  
    unsigned short wCPoly = CrcMode.Polynom;  
    unsigned char wChar = 0; 
    int i;
    while (Length--)     
    {      
       wChar = *(DataAddrStart++); 
       if(CrcInversionTure==CrcMode.IsDataInInversion)
       {wChar=(unsigned char)bitrev(wChar,8);}

        wCRCin ^= (wChar << 8);  
         
         for(i = 0; i < 8; i++) 
         {  
             if(wCRCin & 0x8000)  
             {
                 wCRCin = (wCRCin << 1) ^ wCPoly; 
             }            
             else  
             {
                 wCRCin = wCRCin << 1;  
             }
         }  
    }  
    if(CrcInversionTure==CrcMode.IsDataInInversion)
    {wCRCin=(unsigned short)bitrev(wCRCin,16);}
    return wCRCin^=CrcMode.ResultXorData;
}


/***供函数验证使用****/
void main()
{

    unsigned char id[]={0x12,0x34,0x56,0x78,0x90};
    unsigned long Crc=0;
    unsigned long CrcS=0;
    Crc32Mode_Type Crc32Inversion;
    Crc16Mode_Type Crc16Inversion;
/*****需要调用的CRX32效验多项式、初始值、反序、输出异或值配置******************************************* /
    Crc32Inversion.Polynom=0x04C11DB7;
    Crc32Inversion.Seed=0x00000000;
    Crc32Inversion.IsDataInInversion=CrcInversionFalse;
    Crc32Inversion.IsDataOutInversion=CrcInversionTure;
    Crc32Inversion.ResultXorData=0x00000000;

/***************************************************************************************************** /   
    CrcS=Crc32_GetCrc(Crc32Inversion,id,sizeof(id));
    printf("Crcs=%08X\n",CrcS);

    CrcS=Crc32_GetCrc(Crc32Inversion,id,sizeof(id));
    printf("Crcs=%08X\n",CrcS);

  /*****需要调用的CRX16效验多项式、初始值、反序、输出异或值配置*********************************************** /            Crc16Inversion.Seed=0xFFFF;
    Crc16Inversion.Polynom=0x1021;
    Crc16Inversion.IsDataInInversion=CrcInversionTure;
    Crc16Inversion.IsDataOutInversion=CrcInversionTure;
    Crc16Inversion.ResultXorData=0xFFFF;

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

    Crc=Crc16_GetCrc(Crc16Inversion,id,sizeof(id));
    printf("Crcv=0x%04X\n",Crc);

    Crc=Crc16_GetCrc(Crc16Inversion,id,sizeof(id));

    printf("Crcv=0x%04X\n",Crc);
    return;
}

编译输出结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值