CRC16_C语言实现

计算实现CRC16,

可以通过配置,初值、多项式、输出入是否反转、输出是否反转、结果异或值来选定不同的模式。

 

/*
**************************************************************************************************************
* 函数名称:     InvertUint8
* 函数功能:     将uint8类型的数字进行bit全部反转
* 函数入口:     dBuf    [out]   待反转的值
                srcBuf  [in]    反转后的值
* 函数返回:        计算CRC的结果
***************************************************************************************************************/

static void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf)
{
    int i;
    unsigned char tmp[4];
    tmp[0] = 0;
    for(i=0;i< 8;i++)
    {
        if(srcBuf[0]& (1 << i))
        tmp[0]|=1<<(7-i);
    }
    dBuf[0] = tmp[0];
}

/*
**************************************************************************************************************
* 函数名称:     InvertUint16
* 函数功能:     将uint16类型的数字进行bit全部反转
* 函数入口:     dBuf    [out]   待反转的值
                srcBuf  [in]    反转后的值
* 函数返回:        计算CRC的结果
***************************************************************************************************************/
static void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf)
{
    int i;
    unsigned short tmp[4];
    tmp[0] = 0;
    for(i=0;i< 16;i++)
    {
        if(srcBuf[0]& (1 << i))
            tmp[0]|=1<<(15 - i);
    }
    dBuf[0] = tmp[0];
}


/*
**************************************************************************************************************
* 函数名称:     CRC16
* 函数功能:     计算CRC16
* 函数入口:     puchMsg    [in]    待计算的数据
                usDataLen  [in]    待计算数据的长度
* 函数返回:        计算CRC的结果
***************************************************************************************************************/
unsigned short CRC16(unsigned char *puchMsg, unsigned int usDataLen)
{
    unsigned short wCRCin = 0xFFFF;        //初始值,根据模式进行设置
    unsigned short wCPoly = 0x1021;        //多项式,根据模式进行设置
    unsigned char wChar = 0;

    while (usDataLen--)
    {
        wChar = *(puchMsg++);
        
        InvertUint8(&wChar,&wChar);     //输入数据反转,根据模式进行选择是否启用
        
        wCRCin ^= (wChar << 8);
        for(int i = 0;i < 8;i++)
        {
            if(wCRCin & 0x8000)
                wCRCin = (wCRCin << 1) ^ wCPoly;
            else
                wCRCin = wCRCin << 1;
        }
    }
    
    InvertUint16(&wCRCin,&wCRCin);        //输出数据反转,根据模式进行选择是否启用
    
    wCRCin &= 0xFFFF;
    
    wCRCin ^= 0xFFFF;                    //输出异或,根据模式设置异或的数值
    
    return (wCRCin) ;
}
CRC16.c

 

 

#include <stdio.h>

/*
**************************************************************************************************************
* 函数名称:     InvertUint8
* 函数功能:     将uint8类型的数字进行bit全部反转
* 函数入口:     dBuf    [out]   待反转的值
                srcBuf  [in]    反转后的值
* 函数返回:        计算CRC的结果
***************************************************************************************************************/

static void InvertUint8(unsigned char *dBuf,unsigned char *srcBuf)
{
    int i;
    unsigned char tmp[4];
    tmp[0] = 0;
    for(i=0;i< 8;i++)
    {
        if(srcBuf[0]& (1 << i))
        tmp[0]|=1<<(7-i);
    }
    dBuf[0] = tmp[0];
}

/*
**************************************************************************************************************
* 函数名称:     InvertUint16
* 函数功能:     将uint16类型的数字进行bit全部反转
* 函数入口:     dBuf    [out]   待反转的值
                srcBuf  [in]    反转后的值
* 函数返回:        计算CRC的结果
***************************************************************************************************************/
static void InvertUint16(unsigned short *dBuf,unsigned short *srcBuf)
{
    int i;
    unsigned short tmp[4];
    tmp[0] = 0;
    for(i=0;i< 16;i++)
    {
        if(srcBuf[0]& (1 << i))
            tmp[0]|=1<<(15 - i);
    }
    dBuf[0] = tmp[0];
}


/*
**************************************************************************************************************
* 函数名称:     CRC16
* 函数功能:     计算CRC16
* 函数入口:     puchMsg    [in]    待计算的数据
                usDataLen  [in]    待计算数据的长度
* 函数返回:        计算CRC的结果
***************************************************************************************************************/
unsigned short CRC16(unsigned char *puchMsg, unsigned int usDataLen)
{
    unsigned short wCRCin = 0xFFFF;        //初始值,根据模式进行设置
    unsigned short wCPoly = 0x1021;        //多项式,根据模式进行设置
    unsigned char wChar = 0;

    while (usDataLen--)
    {
        wChar = *(puchMsg++);
        
        InvertUint8(&wChar,&wChar);     //输入数据反转,根据模式进行选择是否启用
        
        wCRCin ^= (wChar << 8);
        for(int i = 0;i < 8;i++)
        {
            if(wCRCin & 0x8000)
                wCRCin = (wCRCin << 1) ^ wCPoly;
            else
                wCRCin = wCRCin << 1;
        }
    }
    
    InvertUint16(&wCRCin,&wCRCin);        //输出数据反转,根据模式进行选择是否启用
    
    wCRCin &= 0xFFFF;
    
    wCRCin ^= 0xFFFF;                    //输出异或,根据模式设置异或的数值
    
    return (wCRCin) ;
}



int main(int argc,char *argv[])
{
    unsigned char     in_data[4]={0x31,0x32,0x33,0x34};
    unsigned int     in_len = 4;
    unsigned short     out_data;
    
    out_data = CRC16(in_data,in_len);
    printf("CRC16 %02X \r\n",out_data);
    

    
    return 0;
}

 

posted @ 2021-05-24 18:15  doitjust  阅读(916)  评论(0编辑  收藏  举报