循环冗余校验码(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
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
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);
}
7、
;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
8、
#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) ;
}
9、
#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]));
}