CRC校验和C语言实现
1.参考资料参考A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS写给嵌入式程序员的循环冗余校验(CRC)算法入门引导CRC (循环冗余校验)模2运算前言本文首先参考了链接2的博客,上面讲的很详细,从奇偶校验、累加和校验、模2运算到CRC校验和优化。并提供了相应的参考链接,很值得参考。如果要深入理解算法的实现原理需要参考链接1...
·
1.参考资料
- 参考
- 前言
本文首先参考了链接2
的博客,上面讲的很详细,从奇偶校验、累加和校验、模2运算到CRC校验和优化。并提供了相应的参考链接,很值得参考。如果要深入理解算法的实现原理需要参考链接1
2.简单的crc程序
-
参考
-
crc16代码
/* * download from : https://www.cnblogs.com/youthshouting/p/4388232.html * another link : http://mdfs.net/Info/Comp/Comms/CRC16.htm * another link : https://blog.csdn.net/liyuanbhu/article/details/7882789 */ #include <stdio.h> int CalCrc(int crc, const char *buf, int len) { unsigned int byte; unsigned char k; unsigned short ACC,TOPBIT; // unsigned short remainder = 0x0000; unsigned short remainder = crc; TOPBIT = 0x8000; for (byte = 0; byte < len; ++byte) { ACC = buf[byte]; remainder ^= (ACC <<8); for (k = 8; k > 0; --k) { if (remainder & TOPBIT) { remainder = (remainder << 1) ^0x8005; } else { remainder = (remainder << 1); } } } remainder=remainder^0x0000; return remainder; } int main(int argc, char* argv[]) { char buffer[22] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x02, 0x03, 0x04}; unsigned short crc = CalCrc(0, buffer, 20);//计算得到的16位CRC校验码 buffer[21] = (char)crc;//取校验码的低八位 buffer[20] = (char)(crc >> 8);//取校验码的高八位 //接收方在接收到buffer中的数据时,代入CalCrc进行计算,若result的值为0,则说明数据传输过程无误 unsigned short result = CalCrc(0, buffer, 22); if (result == 0){ printf("crc result is right\n"); } return 0; }
3.crc16查表法
- 参考
- Programming Embedded Systems in C and C++, section 6
- 代码
-
crc.h
/* * copy from : https://blog.csdn.net/liyuanbhu/article/details/7882789 * refer from book : Programming Embedded Systems in C and C++, section 6 */ /* crc.h */ #ifndef CRC_H_INCLUDED #define CRC_H_INCLUDED /* * The CRC parameters. Currently configured for CCITT. * Simply modify these to switch to another CRC Standard. */ /* #define POLYNOMIAL 0x8005 #define INITIAL_REMAINDER 0x0000 #define FINAL_XOR_VALUE 0x0000 */ #define POLYNOMIAL 0x1021 #define INITIAL_REMAINDER 0xFFFF #define FINAL_XOR_VALUE 0x0000 /* #define POLYNOMIAL 0x1021 #define POLYNOMIAL 0xA001 #define INITIAL_REMAINDER 0xFFFF #define FINAL_XOR_VALUE 0x0000 */ /* * The width of the CRC calculation and result. * Modify the typedef for an 8 or 32-bit CRC standard. */ typedef unsigned short width_t; #define WIDTH (8 * sizeof(width_t)) #define TOPBIT (1 << (WIDTH - 1)) /** * Initialize the CRC lookup table. * This table is used by crcCompute() to make CRC computation faster. */ void crcInit(void); /** * Compute the CRC checksum of a binary message block. * @para message, 用来计算的数据 * @para nBytes, 数据的长度 * @note This function expects that crcInit() has been called * first to initialize the CRC lookup table. */ width_t crcCompute(unsigned char * message, unsigned int nBytes); #endif // CRC_H_INCLUDED
-
crc.c
/* * copy from : https://blog.csdn.net/liyuanbhu/article/details/7882789 * refer from book : Programming Embedded Systems in C and C++, section 6 */ /* *crc.c */ #include "crc.h" /* * An array containing the pre-computed intermediate result for each * possible byte of input. This is used to speed up the computation. */ static width_t crcTable[256]; /** * Initialize the CRC lookup table. * This table is used by crcCompute() to make CRC computation faster. */ void crcInit(void) { width_t remainder; width_t dividend; int bit; /* Perform binary long division, a bit at a time. */ for(dividend = 0; dividend < 256; dividend++) { /* Initialize the remainder. */ remainder = dividend << (WIDTH - 8); /* Shift and XOR with the polynomial. */ for(bit = 0; bit < 8; bit++) { /* Try to divide the current data bit. */ if(remainder & TOPBIT) { remainder = (remainder << 1) ^ POLYNOMIAL; } else { remainder = remainder << 1; } } /* Save the result in the table. */ crcTable[dividend] = remainder; } } /* crcInit() */ /** * Compute the CRC checksum of a binary message block. * @para message, 用来计算的数据 * @para nBytes, 数据的长度 * @note This function expects that crcInit() has been called * first to initialize the CRC lookup table. */ width_t crcCompute(unsigned char * message, unsigned int nBytes) { unsigned int offset; unsigned char byte; width_t remainder = INITIAL_REMAINDER; /* Divide the message by the polynomial, a byte at a time. */ for( offset = 0; offset < nBytes; offset++) { byte = (remainder >> (WIDTH - 8)) ^ message[offset]; remainder = crcTable[byte] ^ (remainder << 8); } /* The final remainder is the CRC result. */ return (remainder ^ FINAL_XOR_VALUE); } /* crcCompute() */
-
main.c
/* * copy from : https://blog.csdn.net/liyuanbhu/article/details/7882789 * refer from book : Programming Embedded Systems in C and C++, section 6 */ #include "crc.h" #include <stdio.h> int main(int argc, char* argv[]) { char buffer[22] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x01, 0x02, 0x03, 0x04}; crcInit(); width_t crc = crcCompute(buffer, 20); //unsigned short crc = CalCrc(0, buffer, 20);//计算得到的16位CRC校验码 buffer[21] = (char)crc;//取校验码的低八位 buffer[20] = (char)(crc >> 8);//取校验码的高八位 //接收方在接收到buffer中的数据时,代入CalCrc进行计算,若result的值为0,则说明数据传输过程无误 width_t result = crcCompute(buffer, 22); //unsigned short result = CalCrc(0, buffer, 22); if (result == 0){ printf("crc result is right\n"); } return 0; }
-
4.crc32
-
参考
-
代码
下面的代码总共使用了四种产生crc校验码的方法/* * download from : http://www.zorc.breitbandkatze.de/crctester.c * a link is : http://www.zorc.breitbandkatze.de/crc.html */ // ---------------------------------------------------------------------------- // CRC tester v1.3 written on 4th of February 2003 by Sven Reifegerste (zorc/reflex) // This is the complete compilable C program, consisting only of this .c file. // No guarantee for any mistakes. // // changes to CRC tester v1.2: // // - remove unneccessary (!(polynom&1)) test for invalid polynoms // (now also XMODEM parameters 0x8408 work in c-code as they should) // // changes to CRC tester v1.1: // // - include an crc&0crcmask after converting non-direct to direct initial // value to avoid overflow // // changes to CRC tester v1.0: // // - most int's were replaced by unsigned long's to allow longer input strings // and avoid overflows and unnecessary type-casting's // ---------------------------------------------------------------------------- // includes: #include <string.h> #include <stdio.h> // CRC parameters (default values are for CRC-32): const int order = 32; const unsigned long polynom = 0x4c11db7; const int direct = 1; const unsigned long crcinit = 0xffffffff; const unsigned long crcxor = 0xffffffff; 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[] = {"123456789"}; // 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, strlen(string))); 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); }
更多推荐
已为社区贡献1条内容
所有评论(0)