如何从HEX值计算CRC-16? [英] How to calculate CRC-16 from HEX values?

查看:179
本文介绍了如何从HEX值计算CRC-16?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的代码中,我需要计算存储为NSdata的HEX值的CRC-16 16位值,下面是用于计算CRC-16的代码片段。



< pre $ void UpdateCRC(unsigned short int * CRC,unsigned char x)
{
//此函数使用在第一个
中传递的初始CRC值//参数,然后根据CRC-16多项式
//参数:
// CRC - 指向开始的指针,使用传递
//的单个字符作为第二个参数对其进行修改CRC值
// x - 要处理的新字符
//返回:
//该函数不返回任何值,但更新变量
//指向通过CRC
static int const Poly = 0xA001;
int i;
bool标志;
* CRC ^ = x; ((* CRC& 1)== 1);
为(i = 0; i <8; i ++)
// CRC-16多项式
{
flag =((* CRC& 1)== 1)
* CRC =(unsigned short int)(* CRC>> 1);
if(flag)
* CRC ^ = Poly;
}
return;
}

保存十六进制值的NSdata

  const char connectByteArray [] = {
0x21,0x01,0x90,0x80,0x5F
};
NSData * data = [NSData dataWithBytes:connectByteArray length:sizeof(connectByteArray)];


解决方案

我解决了使用下面的C程序,我希望它可以帮助某人..cheers !!!

  #include< string.h> 
#include< stdio.h>


const int order = 16;
const unsigned long polynom = 0x8005;
const int direct = 1;
const unsigned long crcinit = 0;
const unsigned long crcxor = 0;
const int refin = 1;
const int refout = 1;

//'order'[1..32]是CRC多项式阶数,不带前导'1'位计数
//'polynom'是没有前导'1'的CRC多项式'bit
//'direct'[0,1]指定算法的类型:1 =直接,不扩充零位
//'crcinit'是属于该算法的初始CRC值
//'crcxor'是最终的异或值
//'refin'[0,1]指定数据字节在处理之前是否被反射(UART)
//'refout'[ 0,1]指定CRC是否在XOR


// //数据字符串

const const unsigned char string [] = {0x05,0x0f, 0x01,0x00,0x00,0x99};

//内部全局值:

unsigned long crcmask;
unsigned long crchighbit;
unsigned long crcinit_direct;
unsigned long crcinit_nondirect;
unsigned long crctab [256];


//子程序

unsigned long反映(unsigned long crc,int bitnum){

//反映较低的'bitnum 'crc'的位

unsigned long i,j = 1,crcout = 0; (crc& i)crcout | =(
b)(i =(无符号长整型)1 <(bitnum-1); i; i>> = 1)焦耳;
j<< = 1;
}
return(crcout);



$ b void generate_crc_table(){

//使表算法使用CRC查找表

int i,j;
unsigned long bit,crc; (i = 0; i <256; i ++){

crc =(unsigned long)i;


if(refin)crc = reflect(crc,8);
crc<< = order-8; $ j
$ b for(j = 0; j <8; j ++){

bit = crc& crchighbit;
crc<< = 1;
if(bit)crc ^ = polynom;


if(refin)crc = reflect(crc,order);
crc& = crcmask;
crctab [i] = crc;
}
}



unsigned long crctablefast(unsigned char * p,unsigned long len){

//不增加零字节的快速查找表算法,例如用于pkzip。
//只能用于8,16,24或32的多项式订单。

unsigned long crc = crcinit_direct;

if(refin)crc = reflect(crc,order); $(!refin)while(len--)crc =(crc < * p ++]; $(bc& 0xff)^ * p ++];

if(refout ^ refin)crc = reflect(crc,order);
crc ^ = crcxor;
crc& = crcmask;

return(crc);




unsigned long crctable(unsigned char * p,unsigned long len){

//正常查找表算法增加零字节。
//只能用于8,16,24或32的多项式订单。

unsigned long crc = crcinit_nondirect;

if(refin)crc = reflect(crc,order);如果(!refin)while(len--)crc =((crc <8)| * p ++)^ crctab [(crc>>(order-8))& ; 0xff的]; $(bc> 8)|(* p ++<(order-8)))^ crctab [crc& 0xff的]; (++ len< order / 8)crc =(crc< 8)^ crctab [(crc>>(order-8))& amp; ; 0xff的];
else while(++ len< order / 8)crc =(crc>> 8)^ crctab [crc& 0xff的];

if(refout ^ refin)crc = reflect(crc,order);
crc ^ = crcxor;
crc& = crcmask;

return(crc);



$ b unsigned long crcbitbybit(unsigned char * p,unsigned long len){

// bit by bit algorithm with增加零字节。
//不使用查找表,适用于1 ... 32之间的多项式顺序。

unsigned long i,j,c,bit;
unsigned long crc = crcinit_nondirect;

for(i = 0; i
c =(unsigned long)* p ++;
if(refin)c = reflect(c,8); $ j
$ b bit = crc& crchighbit;
crc<< = 1;
if(c& j)crc | = 1;
if(bit)crc ^ = polynom;



(i = 0; i
bit = crc& crchighbit;
crc<< = 1;
if(bit)crc ^ = polynom;
}

if(refout)crc = reflect(crc,order);
crc ^ = crcxor;
crc& = crcmask;

return(crc);



$ b unsigned long crcbitbybitfast(unsigned char * p,unsigned long len){

//快速逐位算法没有增加零字节。
//不使用查找表,适用于1 ... 32之间的多项式顺序。

unsigned long i,j,c,bit;
unsigned long crc = crcinit_direct;

for(i = 0; i
c =(unsigned long)* p ++;
if(refin)c = reflect(c,8); $ j
$ b bit = crc& crchighbit;
crc<< = 1;
if(c& j)bit ^ = crchighbit;
if(bit)crc ^ = polynom;



if(refout)crc = reflect(crc,order);
crc ^ = crcxor;
crc& = crcmask;

return(crc);
}



int main(){

//用于检查四种不同CRC计算类型的测试程序:
// crcbit(),crcbitfast(),crctable()和crctablefast(),参见上文。
//参数在这个程序的顶部。
//结果将打印在控制台上。

int i;
unsigned long bit,crc;


//首先计算整个CRC和CRC高位的常数位掩码

crcmask =((((unsigned long)1 <<为了-1)) - 1) - ;< 1)| 1;
crchighbit =(无符号长整型)1 <<(order-1);

$ b $ //检查参数

if(order< 1 || order> 32){
printf(ERROR,invalid order,它必须在1..32. \\\
之间);
return(0);如果(polynom!=(polynom& crcmask)){
printf(ERROR,invalid polynom.\\\
);
}


return(0); (crcinit& crcmask)){
printf(ERROR,invalid crcinit.\\\
);
}

if(crcinit!=
return(0); (crcxor& crcmask)){
printf(ERROR,invalid crcxor.\\\
);
}

if(crcxor!=
return(0);
}


//生成查找表

generate_crc_table();


//计算丢失的初始CRC值

if(!direct){

crcinit_nondirect = crcinit;
crc = crcinit;
for(i = 0; i
bit = crc& crchighbit;
crc<< = 1;
if(bit)crc ^ = polynom;
}
crc& = crcmask;
crcinit_direct = crc;
}

其他{

crcinit_direct = crcinit;
crc = crcinit;
for(i = 0; i
bit = crc& 1;
if(bit)crc ^ = polynom;
crc>> = 1;
if(bit)crc | = crchighbit;
}
crcinit_nondirect = crc;



//使用上面的CRC参数调用CRC算法并将结果输出到控制台

printf(\\\
);
printf(由Sven Reifegerste(zorc / reflex)\\\
于2003年1月13日写的CRC tester v1.1);
printf(------------------------------------------- ---------------------------- \\\
);
printf(\\\
);
printf(Parameters:\\\
);
printf(\\\
);
printf(polynom:0x%x \ n,polynom);
printf(order:%d \\\
,order);
printf(crcinit:0x%x direct,0x%x nondirect \\\
,crcinit_direct,crcinit_nondirect);
printf(crcxor:0x%x \\\
,crcxor);
printf(refin:%d \\\
,refin);
printf(refout:%d \\\
,refout);
printf(\\\
);
printf(data string:'%s'(%d bytes)\\\
,string,strlen(string));
printf(\\\
);
printf(结果:\\\
);
printf(\\\
);
$ b printf(crc bit by bit:0x%x\\\
,crcbitbybit((unsigned char *)string,6));
printf(crc bit bit by fast:0x%x \\\
,crcbitbybitfast((unsigned char *)string,strlen(string))); (!(order& 7))printf(crc table:0x%x \ n,crctable((unsigned char *)string,strlen(string)));
if (!(order& 7))printf(crc table fast:0x%x \\\
,crctablefast((unsigned char *)string,strlen(string)));
if

return(0);
}


In my code i need to calculate CRC-16 16 bit values for the HEX values stored as NSdata, below is the code snippet to calculate CRC-16 in c.

   void UpdateCRC(unsigned short int *CRC, unsigned char x)
{
  // This function uses the initial CRC value passed in the first
  // argument, then modifies it using the single character passed
  // as the second argument, according to a CRC-16 polynomial
  // Arguments:
  //   CRC -- pointer to starting CRC value
  //   x   -- new character to be processed
  // Returns:
  // The function does not return any values, but updates the variable
  // pointed to by CRC
static int const Poly = 0xA001;
int i;
bool flag;
*CRC ^= x;
for (i=0; i<8; i++)
// CRC-16 polynomial
{
  flag = ((*CRC & 1) == 1);
  *CRC = (unsigned short int)(*CRC >> 1);
  if (flag)
      *CRC ^= Poly;
  }
return; 
}

NSdata which holds the hex values like below

const char connectByteArray[] = {
    0x21,0x01,0x90,0x80,0x5F
};
NSData* data = [NSData dataWithBytes: connectByteArray length:sizeof(connectByteArray)];

解决方案

I solved using the following C program, I hope it may help someone ..cheers!!!

#include <string.h>
#include <stdio.h>


const int order = 16;
const unsigned long polynom = 0x8005;
const int direct = 1;
const unsigned long crcinit = 0;
const unsigned long crcxor = 0;
const int refin = 1;
const int refout = 1;

// 'order' [1..32] is the CRC polynom order, counted without the leading '1' bit
// 'polynom' is the CRC polynom without leading '1' bit
// 'direct' [0,1] specifies the kind of algorithm: 1=direct, no augmented zero bits
// 'crcinit' is the initial CRC value belonging to that algorithm
// 'crcxor' is the final XOR value
// 'refin' [0,1] specifies if a data byte is reflected before processing (UART) or not
// 'refout' [0,1] specifies if the CRC will be reflected before XOR


// Data character string

const unsigned char string[] = {0x05,0x0f,0x01,0x00,0x00,0x99};

// internal global values:

unsigned long crcmask;
unsigned long crchighbit;
unsigned long crcinit_direct;
unsigned long crcinit_nondirect;
unsigned long crctab[256];


// subroutines

unsigned long reflect (unsigned long crc, int bitnum) {

    // reflects the lower 'bitnum' bits of 'crc'

    unsigned long i, j=1, crcout=0;

    for (i=(unsigned long)1<<(bitnum-1); i; i>>=1) {
        if (crc & i) crcout|=j;
        j<<= 1;
    }
    return (crcout);
}



void generate_crc_table() {

    // make CRC lookup table used by table algorithms

    int i, j;
    unsigned long bit, crc;

    for (i=0; i<256; i++) {

        crc=(unsigned long)i;
        if (refin) crc=reflect(crc, 8);
        crc<<= order-8;

        for (j=0; j<8; j++) {

            bit = crc & crchighbit;
            crc<<= 1;
            if (bit) crc^= polynom;
        }           

        if (refin) crc = reflect(crc, order);
        crc&= crcmask;
        crctab[i]= crc;
    }
}



unsigned long crctablefast (unsigned char* p, unsigned long len) {

    // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip.
    // only usable with polynom orders of 8, 16, 24 or 32.

    unsigned long crc = crcinit_direct;

    if (refin) crc = reflect(crc, order);

    if (!refin) while (len--) crc = (crc << 8) ^ crctab[ ((crc >> (order-8)) & 0xff) ^ *p++];
    else while (len--) crc = (crc >> 8) ^ crctab[ (crc & 0xff) ^ *p++];

    if (refout^refin) crc = reflect(crc, order);
    crc^= crcxor;
    crc&= crcmask;

    return(crc);
}



unsigned long crctable (unsigned char* p, unsigned long len) {

    // normal lookup table algorithm with augmented zero bytes.
    // only usable with polynom orders of 8, 16, 24 or 32.

    unsigned long crc = crcinit_nondirect;

    if (refin) crc = reflect(crc, order);

    if (!refin) while (len--) crc = ((crc << 8) | *p++) ^ crctab[ (crc >> (order-8))  & 0xff];
    else while (len--) crc = ((crc >> 8) | (*p++ << (order-8))) ^ crctab[ crc & 0xff];

    if (!refin) while (++len < order/8) crc = (crc << 8) ^ crctab[ (crc >> (order-8))  & 0xff];
    else while (++len < order/8) crc = (crc >> 8) ^ crctab[crc & 0xff];

    if (refout^refin) crc = reflect(crc, order);
    crc^= crcxor;
    crc&= crcmask;

    return(crc);
}



unsigned long crcbitbybit(unsigned char* p, unsigned long len) {

    // bit by bit algorithm with augmented zero bytes.
    // does not use lookup table, suited for polynom orders between 1...32.

    unsigned long i, j, c, bit;
    unsigned long crc = crcinit_nondirect;

    for (i=0; i<len; i++) {

        c = (unsigned long)*p++;
        if (refin) c = reflect(c, 8);

        for (j=0x80; j; j>>=1) {

            bit = crc & crchighbit;
            crc<<= 1;
            if (c & j) crc|= 1;
            if (bit) crc^= polynom;
        }
    }   

    for (i=0; i<order; i++) {

        bit = crc & crchighbit;
        crc<<= 1;
        if (bit) crc^= polynom;
    }

    if (refout) crc=reflect(crc, order);
    crc^= crcxor;
    crc&= crcmask;

    return(crc);
}



unsigned long crcbitbybitfast(unsigned char* p, unsigned long len) {

    // fast bit by bit algorithm without augmented zero bytes.
    // does not use lookup table, suited for polynom orders between 1...32.

    unsigned long i, j, c, bit;
    unsigned long crc = crcinit_direct;

    for (i=0; i<len; i++) {

        c = (unsigned long)*p++;
        if (refin) c = reflect(c, 8);

        for (j=0x80; j; j>>=1) {

            bit = crc & crchighbit;
            crc<<= 1;
            if (c & j) bit^= crchighbit;
            if (bit) crc^= polynom;
        }
    }   

    if (refout) crc=reflect(crc, order);
    crc^= crcxor;
    crc&= crcmask;

    return(crc);
}



int main() {

    // test program for checking four different CRC computing types that are:
    // crcbit(), crcbitfast(), crctable() and crctablefast(), see above.
    // parameters are at the top of this program.
    // Result will be printed on the console.

    int i;
    unsigned long bit, crc;


    // at first, compute constant bit masks for whole CRC and CRC high bit

    crcmask = ((((unsigned long)1<<(order-1))-1)<<1)|1;
    crchighbit = (unsigned long)1<<(order-1);


    // check parameters

    if (order < 1 || order > 32) {
        printf("ERROR, invalid order, it must be between 1..32.\n");
        return(0);
    }

    if (polynom != (polynom & crcmask)) {
        printf("ERROR, invalid polynom.\n");
        return(0);
    }

    if (crcinit != (crcinit & crcmask)) {
        printf("ERROR, invalid crcinit.\n");
        return(0);
    }

    if (crcxor != (crcxor & crcmask)) {
        printf("ERROR, invalid crcxor.\n");
        return(0);
    }


    // generate lookup table

    generate_crc_table();


    // compute missing initial CRC value

    if (!direct) {

        crcinit_nondirect = crcinit;
        crc = crcinit;
        for (i=0; i<order; i++) {

            bit = crc & crchighbit;
            crc<<= 1;
            if (bit) crc^= polynom;
        }
        crc&= crcmask;
        crcinit_direct = crc;
    }

    else {

        crcinit_direct = crcinit;
        crc = crcinit;
        for (i=0; i<order; i++) {

            bit = crc & 1;
            if (bit) crc^= polynom;
            crc >>= 1;
            if (bit) crc|= crchighbit;
        }   
        crcinit_nondirect = crc;
    }


    // call CRC algorithms using the CRC parameters above and print result to the console

    printf("\n");
    printf("CRC tester v1.1 written on 13/01/2003 by Sven Reifegerste (zorc/reflex)\n");
    printf("-----------------------------------------------------------------------\n");
    printf("\n");
    printf("Parameters:\n");
    printf("\n");
    printf(" polynom             :  0x%x\n", polynom);
    printf(" order               :  %d\n", order);
    printf(" crcinit             :  0x%x direct, 0x%x nondirect\n", crcinit_direct, crcinit_nondirect);
    printf(" crcxor              :  0x%x\n", crcxor);
    printf(" refin               :  %d\n", refin);
    printf(" refout              :  %d\n", refout);
    printf("\n");
    printf(" data string         :  '%s' (%d bytes)\n", string, strlen(string));
    printf("\n");
    printf("Results:\n");
    printf("\n");

    printf(" crc bit by bit      :  0x%x\n", crcbitbybit((unsigned char *)string, 6));
    printf(" crc bit by bit fast :  0x%x\n", crcbitbybitfast((unsigned char *)string, strlen(string)));
    if (!(order&7)) printf(" crc table           :  0x%x\n", crctable((unsigned char *)string, strlen(string)));
    if (!(order&7)) printf(" crc table fast      :  0x%x\n", crctablefast((unsigned char *)string, strlen(string)));

    return(0);
}

这篇关于如何从HEX值计算CRC-16?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆