循环冗余校验码(Cylclic Redundancy Check Code),简称CRC码。常用的CRC数有8,16,32,CRC位数越大,数据越不易受干扰,但运算时间加长。一般关于通信的书籍都有介绍。简单原理是将要传输的数据视为一堆连续位组成的一整个数值,并将此数值除一个特定的除数,通常以二进制表示,此除数称为衍生多项式(Generation Polynomial). 一般数据量不大时,使用Checksume验错方式就行了;数据量大时,就用CRC了;据理论统计,用CRC16时,超过17个连续位的错误侦测率为99。9969,小于此的为100。 1、CRC-12 的生成多项式为:P(x)=X^12 X^11 X^3 X^2 1
2、 CRC MOV DPH, #table ; 指向余式表下半区 MOV DPL, R0 ; 指向对应单元 CLR A ; MOVC A, @A DPTR ; 读余式的高字节 XRL A, R1 ; 计算余式的高字节 MOV R0, A ; 存入R0 INC DPH ; 指向余式表上半区 CLR A ; MOVC A, @A DPTR ; 读余式的低字节 XRL A, R2 ; 计算余式的低字节 MOV R1, A ; 存入R1 RET 这个是对于三字节的东东,你自己还要造张余式表
3、很简单的查表法 unsigned int UpdateCRC(unsigned char byte,unsigned int crc);#include <stdio.h> #include "crc16.h" static code unsigned int Crc16Table[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; unsigned int UpdateCrc16(unsigned char Octet,unsigned int CRC) { return Crc16Table[ (CRC >> 8) & 255] ^ (CRC << 8) ^ Octet; }
unsigned int UpdateCRC(unsigned char Octet,unsigned int CRC) { return (CRC << 8) ^ Crc16Table[ (CRC >> 8) ^ Octet ]; }
4、 _CRC: MOV A,R7 ;CRC INPUT POINTER MOV R1,A MOV B,R5 MOV DPH,R6;#SRCADR ;CRC INPUT PAGE ADDRESS MOV DPL,R1 MOV RCRC2L,#0 MOV RCRC1H,#0 MOV RCRC1L,#0 CRCA: MOVX A,@DPTR XRL A,RCRC1H XRL A,RCRC2L MOV RXTEMP,A MOV RCRC2L,RCRC1L MOV DPTR,#CRCTAB1 MOVC A,@A DPTR MOV RCRC1H,A MOV A,RXTEMP INC DPH MOVC A,@A DPTR MOV RCRC1L,A MOV DPH,R6;#SRCADR ;CRC INPUT PAGE ADDRESS INC R1 MOV DPL,R1 MOV A,R1 CJNE A,B,CRCAMOV A,RCRC1H XRL A,RCRC2L CPL A MOV RCRC1H,A MOV A,RCRC1L CPL A MOV RCRC1L,A MOV R6,RCRC1H MOV R7,RCRC1L RET ;------------------------------------------- CRCTAB1: DB 000H,089H,012H,09BH,024H,0ADH,036H,0BFH DB 048H,0C1H,05AH,0D3H,06CH,0E5H,07EH,0F7H DB 081H,008H,093H,01AH,0A5H,02CH,0B7H,03EH DB 0C9H,040H,0DBH,052H,0EDH,064H,0FFH,076H DB 002H,08BH,010H,099H,026H,0AFH,034H,0BDH DB 04AH,0C3H,058H,0D1H,06EH,0E7H,07CH,0F5H DB 083H,00AH,091H,018H,0A7H,02EH,0B5H,03CH DB 0CBH,042H,0D9H,050H,0EFH,066H,0FDH,074H DB 004H,08DH,016H,09FH,020H,0A9H,032H,0BBH DB 04CH,0C5H,05EH,0D7H,068H,0E1H,07AH,0F3H DB 085H,00CH,097H,01EH,0A1H,028H,0B3H,03AH DB 0CDH,044H,0DFH,056H,0E9H,060H,0FBH,072H DB 006H,08FH,014H,09DH,022H,0ABH,030H,0B9H DB 04EH,0C7H,05CH,0D5H,06AH,0E3H,078H,0F1H DB 087H,00EH,095H,01CH,0A3H,02AH,0B1H,038H DB 0CFH,046H,0DDH,054H,0EBH,062H,0F9H,070H DB 008H,081H,01AH,093H,02CH,0A5H,03EH,0B7H DB 040H,0C9H,052H,0DBH,064H,0EDH,076H,0FFH DB 089H,000H,09BH,012H,0ADH,024H,0BFH,036H DB 0C1H,048H,0D3H,05AH,0E5H,06CH,0F7H,07EH DB 00AH,083H,018H,091H,02EH,0A7H,03CH,0B5H DB 042H,0CBH,050H,0D9H,066H,0EFH,074H,0FDH DB 08BH,002H,099H,010H,0AFH,026H,0BDH,034H DB 0C3H,04AH,0D1H,058H,0E7H,06EH,0F5H,07CH DB 00CH,085H,01EH,097H,028H,0A1H,03AH,0B3H DB 044H,0CDH,056H,0DFH,060H,0E9H,072H,0FBH DB 08DH,004H,09FH,016H,0A9H,020H,0BBH,032H DB 0C5H,04CH,0D7H,05EH,0E1H,068H,0F3H,07AH DB 00EH,087H,01CH,095H,02AH,0A3H,038H,0B1H DB 046H,0CFH,054H,0DDH,062H,0EBH,070H,0F9H DB 08FH,006H,09DH,014H,0ABH,022H,0B9H,030H DB 0C7H,04EH,0D5H,05CH,0E3H,06AH,0F1H,078H CRCTAB2: DB 000H,011H,023H,032H,046H,057H,065H,074H DB 08CH,09DH,0AFH,0BEH,0CAH,0DBH,0E9H,0F8H DB 010H,001H,033H,022H,056H,047H,075H,064H DB 09CH,08DH,0BFH,0AEH,0DAH,0CBH,0F9H,0E8H DB 021H,030H,002H,013H,067H,076H,044H,055H DB 0ADH,0BCH,08EH,09FH,0EBH,0FAH,0C8H,0D9H DB 031H,020H,012H,003H,077H,066H,054H,045H DB 0BDH,0ACH,09EH,08FH,0FBH,0EAH,0D8H,0C9H DB 042H,053H,061H,070H,004H,015H,027H,036H DB 0CEH,0DFH,0EDH,0FCH,088H,099H,0ABH,0BAH DB 052H,043H,071H,060H,014H,005H,037H,026H DB 0DEH,0CFH,0FDH,0ECH,098H,089H,0BBH,0AAH DB 063H,072H,040H,051H,025H,034H,006H,017H DB 0EFH,0FEH,0CCH,0DDH,0A9H,0B8H,08AH,09BH DB 073H,062H,050H,041H,035H,024H,016H,007H DB 0FFH,0EEH,0DCH,0CDH,0B9H,0A8H,09AH,08BH DB 084H,095H,0A7H,0B6H,0C2H,0D3H,0E1H,0F0H DB 008H,019H,02BH,03AH,04EH,05FH,06DH,07CH DB 094H,085H,0B7H,0A6H,0D2H,0C3H,0F1H,0E0H DB 018H,009H,03BH,02AH,05EH,04FH,07DH,06CH DB 0A5H,0B4H,086H,097H,0E3H,0F2H,0C0H,0D1H DB 029H,038H,00AH,01BH,06FH,07EH,04CH,05DH DB 0B5H,0A4H,096H,087H,0F3H,0E2H,0D0H,0C1H DB 039H,028H,01AH,00BH,07FH,06EH,05CH,04DH DB 0C6H,0D7H,0E5H,0F4H,080H,091H,0A3H,0B2H DB 04AH,05BH,069H,078H,00CH,01DH,02FH,03EH DB 0D6H,0C7H,0F5H,0E4H,090H,081H,0B3H,0A2H DB 05AH,04BH,079H,068H,01CH,00DH,03FH,02EH DB 0E7H,0F6H,0C4H,0D5H,0A1H,0B0H,082H,093H DB 06BH,07AH,048H,059H,02DH,03CH,00EH,01FH DB 0F7H,0E6H,0D4H,0C5H,0B1H,0A0H,092H,083H DB 07BH,06AH,058H,049H,03DH,02CH,01EH,00FH end
5、 uint crc(uchar * byte,uchar nbyte) //CRC校验 { uint data itemp=0; uchar data i,j; bit flag; for(i=0;i<nbyte;i ) { itemp^=(byte[i]<<8); for (j=0;j<8;j ) { flag=itemp&0x8000; itemp<<=1; if(flag) { itemp^=0x1021; } } } return itemp; }
6、 CREATCRC: ; ----- CRC-16 ----- MOV R2,#00H MOV R3,#00H CRCATER2: MOV A,@R0 XRL A,R3 LCALL CRCCRT1 XRL A,R2 MOV R3,A MOV R2,B INC R0 DJNZ R5,CRCATER2 MOV @R0,B INC R0 MOV @R0,A RETCRCCRT1: MOV R7,#08H MOV B,#00H CRT1LOP1: CLR C PUSH ACC MOV A,B RLC A MOV B,A POP ACC RLC A JNC CRT1LOP2 PUSH ACC MOV A,B XRL A,#CRCGENL MOV B,A POP ACC XRL A,#CRCGENH CRT1LOP2: DJNZ R7,CRT1LOP1 RET RECEIVE: SETB F0 LCALL CREATCRC MOV A,CCRC1 XRL A,@R0 JNZ ERRORCRC INC R0 MOV A,CCRC2 XRL A,@R0 JNZ ERRORCRC LJMP EEND ERRORCRC: CLR F0 EEND: RET
7、 1) 求CRC码的运算采用模2运算, 所谓模2运算就是不带进位和借位, 因此加法和减法等价,实际上就是逻辑上的异或运算, 除法可以用多次模2减法实现.2) 所谓CRC码, 就是把数据块左移16位, 然后除以0x11021所得到的余数(由CCITT推荐). 3) 据此写出以下的CRC的C程序. *ptr指向发送数据块的首地址, len是数据块以字节为单位的长度. uint cal_crc(uchar *ptr, uchar len) { uint crc; uchar i; crc=0; while(len--!=0) { for(i=0x80; i!=0; i/=2) { if((crc&0x8000)!=0) {crc*=2; crc^=0x1021;} else crc*=2; if((*ptr&i)!=0) crc^=0x1021; } ptr ; } return(crc); }
8、CRC校验算法 START EQU 2000H ;数据区首址(任意设置128字节数据)。 ERR BIT 00H ;出错标志。 ORG 100H LCALL CRCOUT ;模拟发方生成CRC校验。 LCALL CHECK ;模拟收方进行CRC校验,应该没有差错。 MOV DPTR,#START 20H ;模拟两个字节被破坏。 CLR A MOVX @DPTR,A INC DPTR MOVX @DPTR,A LCALL CHECK ;再次模拟收方进行CRC校验,应该发现差错。 STOP: LJMP STOP NOP NOP NOP CRCOUT: MOV DPTR,#START 80H ;将CRC存放单元初始化为零。 CLR A MOVX @DPTR,A INC DPTR MOVX @DPTR,A LCALL CRC ;计算CRC。 MOV DPTR,#START 80H ;将计算结果存放到数据块之后。 MOV A,R2 MOVX @DPTR,A INC DPTR MOV A,R3 MOVX @DPTR,A RET NOP NOP CRC: MOV DPTR,#START ;(CRC计算模块)先取两字节数据,作为 MOVX A,@DPTR ;最初的被除数。 MOV R2,A INC DPTR MOVX A,@DPTR MOV R3,A MOV R7,#80H ;以后的128字节依次作为被除数的补充。 CRC1: INC DPTR MOVX A,@DPTR ;取一字节数据,作为被除数的补充。 MOV R4,A MOV R5,#8 ;每字节要进行8次模2除法。 CRC2: MOV A,R4 ;三字节被除数的当前余数左移一位。 RLC A MOV R4,A MOV A,R3 RLC A MOV R3,A MOV A,R2 RLC A MOV R2,A JNC CRC3 ;移出的最高位是0,不用处理。 XRL A,#10H ;移出的最高位是1,进行模2处理。 MOV R2,A MOV A,R3 XRL A,#21H MOV R3,A CRC3: DJNZ R5,CRC2 ;处理完一个字节。 DJNZ R7,CRC1 ;处理完全部数据。 RET ;CRC校验码在R2R3之中。 NOP NOP CHECK: CLR ERR ;出错标志初始化。 LCALL CRC ;计算CRC。 MOV A,R2 ;结果为零否? ORL A,R3 JZ CHKE SETB ERR ;结果不为零,设立出错标志。 CHKE: RET END 9、crc16 keil #include "verity.h" static unsigned char auchCRCHi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 } ; /* Table of CRC values for low-order byte */ static char auchCRCLo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 } ;
unsigned char nLRC(unsigned char *str,unsigned int len) { unsigned int tmp; for(tmp=0;tmp<len;tmp ) str[tmp]=str[tmp]-0x30; return(LRC(str,len)); } unsigned char LRC(unsigned char *uchMsg, unsigned int usDataLen) { unsigned char uchLRC = 0 ; /* LRC char initialized */ while (usDataLen--) /* pass through message */ uchLRC =*uchMsg ; /* buffer add buffer byte*/ /* without carry */ return((unsigned char)(-(char)(uchLRC))); /* return twos complemen */ } unsigned int nCRC16(unsigned char *puchMsg, unsigned int usDataLen) { unsigned char uchCRCHi = 0xFF ; /* high CRC unsigned char initialized */ unsigned char uchCRCLo = 0xFF ; /* low CRC unsigned char initialized */ unsigned int uIndex ; /* will index into CRC lookup*/ /* table*/ while (usDataLen--) /* pass through message buffer */ { uIndex = uchCRCHi ^ *puchMsg ; /* calculate the CRC */ uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]; uchCRCLo = auchCRCLo[uIndex] ; } return ((uchCRCHi<<8)|uchCRCLo) ; } 10、crc16 #define POLY_CRC16 0xA001
static BYTE TABLE1[256]; /* crc16 values */ static BYTE TABLE2[256]; /* crc16 values */ /* crc_init: prepare crc16 preset tables must be called once at init (before any crc calculation) */ void crc_init (void) { WORD mask, bit, crc, mem; for( mask = 0; mask < 0x100; mask ) { crc = mask; for( bit = 0; bit < 8; bit ) { mem = crc & 0x0001 ; crc /= 2; if ( mem != 0 ) crc ^= POLY_CRC16 ; } TABLE2[mask] = crc & 0xff; TABLE1[mask] = crc >> 8; } } /* crc_make: calculates a crc16 size: size of the frame (including header) buff: pointer to the first byte of the frame (slave number) return: CRC16 in MOTOROLA format (high byte / low byte) */ WORD crc_make (WORD size, BYTE *buff) { BYTE car, i; BYTE crc[2]; crc[0] = 0xff; crc[1] = 0xff; for ( i = 0; i < size; i ) { car = buff[i]; car ^= crc[0]; crc[0] = crc[1] ^ TABLE2[car]; crc[1] = TABLE1[car]; } return (*(WORD*)(&crc[0])); } 11、crc16 keil c51(铁匠)
#pragma small #include <reg52.h> unsigned int CRC_16(unsigned int c,unsigned char d); unsigned int crc16=0; void main(void) { // unsigned char crcbuff[] = {31,3,0,1,0,7}; unsigned char crcbuff[] = "123456789"; unsigned char *p; // unsigned int crc16 = 0xffff; p=crcbuff; while(*p !='/0') { crc16 = CRC_16(crc16,*p ); } p=crcbuff; } unsigned int CRC_16(unsigned int c,unsigned char d) { unsigned int data e; unsigned char data f; e = c^(unsigned int)d; for(f=0;f<8;f ) { if(e&1) { e >>= 1; e ^= 0xa001; } else e >>= 1; } return e; } // 使用字符串"123456789"测试,crc16初始值为0时 // 结果为0xbb3d 符合crc caculator 12、/ //网站上的算法大都是查512字节表的,对单片机来讲,太浪费空间了。 //据老古网上资料,修改并测试通过以下算法: unsigned int crc_ta[16]={ 0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7, 0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef, };
unsigned int Crc16(unsigned char *ptr, unsigned char len) { unsigned int crc; unsigned char da; crc=0; while(len--!=0) { da=crc>>12; crc<<=4; crc^=crc_ta[da^(*ptr/16)]; da=crc>>12; crc<<=4; crc^=crc_ta[da^(*ptr&0x0f)]; ptr++; } return(crc); }
|