循环冗余校验码(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,CRCA
- MOV 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
- 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
- RET
- CRCCRT1:
- 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 */
- 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);
- }