卡农钢琴曲教程教学:怎样在VB、C、DELPHI、汇编语言中使用CRC算法
来源:百度文库 编辑:偶看新闻 时间:2024/04/30 22:19:49
在无线电通信中,为了保证数据在传输中的完整性,我们通常需要检查其内容,最愚蠢的办法不过是回滚数据咯,需要让主机逐字节检查,不过那种方法很占用通信的时间。CRC效验是一种更好的方法。这样不必每回都回滚数据,只需通过CRC码来检测其完整性。大大节省了时间。
为方便解释其原理,总结了CRC所有操作:
1.装一个16位的寄存器,所有数位均为1
2.取被校验串的一个字节与16位寄存器的高位字节进行"异或"运算.运算结果放入这个16位寄存器.
3.把这个16位寄存器向右移一位.
4.若向右(标记位)移出的位数是1,则生成多项式1010 0000 0000 0001和这个寄存器进行"异或"运算;若向右移出的位数是0,则返回步骤3.
5.重复步骤3和4,直至移出8位.
6.取被校验串的下一个字节
7.重复步骤3~6,直至被校验串的所有字节均与16位寄存器进行"异或"运算,并移位8次.
8.这个16位寄存器的内容即2字节CRC错误校验码.
生成CRC的代码:
C语言:
////////////////////////////////////////////////////////////////////////////
// Deions: 计算指定数据的CRC值, 依据的是国家标准协议中所定义的算法 //
// Parameters: //
// BYTE * 要计算CRC的数据 //
// int 被计算CRC的数据的字节数 //
////////////////////////////////////////////////////////////////////////////
WORD __fastcall TGBAdapterListener::GetCRCWord(BYTE * Buf, int BufLen)
{
WORD wRet = 0xFFFF;
for (int iIndex = 0; iIndex < BufLen; iIndex ++)
{
wRet = (WORD)(HIBYTE(wRet) ^ Buf[iIndex]);
for (int iLooper = 0; iLooper < 8; iLooper ++)
{
if (wRet & 0x0001)
{
wRet = (wRet >> 1) ^ 0xA001;
}
else
wRet = (wRet >> 1);
}
}
return wRet;
}
DELPHI语言:
\\一
GetCRCWord(Buf:array of byte; BufLen:integer):WORD;
var
wRet:WORD;
iIndex:integer;
iLooper:integer;
begin
wRet := $FFFF;
for iIndex :=0 to BufLen-1 do
begin
wRet := WORD(Hi(wRet) xor Buf[iIndex]);
for iLooper := 0 to 7 do
begin
if (wRet and $0001) = 1 then
wRet := (wRet shr 1) xor $A001
else
wRet := wRet shr 1;
end;
end;
result := wRet;
end;
\\二
GetCRCWord_2(Buf:PChar; BufLen:integer):WORD;
var
wRet:WORD;
iIndex:integer;
iLooper:integer;
begin
wRet := $FFFF;
for iIndex :=0 to BufLen-1 do
begin
wRet := WORD(Hi(wRet) xor Ord(Buf[iIndex]));
for iLooper := 0 to 7 do
begin
if (wRet and $0001) = 1 then
wRet := (wRet shr 1) xor $A001
else
wRet := wRet shr 1;
end;
end;
result := wRet;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
s:string;
len:integer;
a:array of byte;
crc16:integer;
begin
s := 'asdasd';
len := length(s);
SetLength(a, len);
CopyMemory(a,Pchar(s),len);
crc16 := GetCRCWord(a,len);
ShowMessage(IntToHex(crc16,4));
end;
procedure TForm1.Button2Click(Sender: TObject);
var
s:string;
len:integer;
crc16:integer;
begin
s := 'asdasd';
len := length(s);
crc16 := GetCRCWord_2(Pchar(s),len);
ShowMessage(IntToHex(crc16,4));
end;
////////////////////////////////////////////////////////////////////////////
VB算法:
Public CRC16(data() As Byte) As Byte()
Dim CRC16Lo As Byte, CRC16Hi As Byte 'CRC寄存器
Dim CL As Byte, CH As Byte '多项式码&HA001
Dim SaveHi As Byte, SaveLo As Byte
Dim i As Integer
Dim Flag As Integer
Dim ReturnData(1) As Byte
CRC16Lo = &HFF
CRC16Hi = &HFF
CL = &H1
CH = &HA0
For Ii = 0 To UBound(data)
CRC16Lo = CRC16Lo Xor data(Ii) '每一个数据与CRC寄存器进行异或
For Flag = 0 To 7
SaveHi = CRC16Hi
SaveLo = CRC16Lo
CRC16Hi = CRC16Hi \ 2 '高位右移一位
CRC16Lo = CRC16Lo \ 2 '低位右移一位
If ((SaveHi And &H1) = &H1) Then '如果高位字节最后一位为1
CRC16Lo = CRC16Lo Or &H80 '则低位字节右移后前面补1
End If '否则自动补0
If ((SaveLo And &H1) = &H1) Then '如果LSB为1,则与多项式码进行异或
CRC16Hi = CRC16Hi Xor CH
CRC16Lo = CRC16Lo Xor CL
End If
Next Flag
Next Ii
ReturnData(0) = CRC16Lo 'CRC低位
ReturnData(1) = CRC16Hi 'CRC高位
CRC16 = ReturnData
End
C算法:
void crc16(unsigned char r_data[],unsigned int length)
{
unsigned char cl,ch;
unsigned char savehi,savelo;
int ii,flag;
crc16hi=0xFF;
crc16lo=0xFF;
cl=0x1;
ch=0xA0;
for (ii=0;ii
crc16lo=(crc16lo ^ r_data[ii]);
for (flag=0;flag<8;flag++)
{
savehi=crc16hi;
savelo=crc16lo;
crc16hi=(crc16hi>>1);
crc16lo=(crc16lo>>1);
if ((savehi & 0x01)==0x01)
crc16lo=(crc16lo | 0x80);
if ((savelo & 0x01)==0x01)
{
crc16hi = (crc16hi ^ ch);
crc16lo = (crc16lo ^ cl);
}
}
}
}
汇编算法 :
;**********************************************************
;CRC16校验子程序
;R1 需进行CRC校验数据起始地址
;CRC16_L CRC校验数据低字节 CRC16_H CRC校验数据高字节
;R7 需进行CRC校验的字节数
;**********************************************************
CRC16:
MOV CRC16_L,#0FFH
MOV CRC16_H,#0FFH
CRC16_LOOP1:
MOVX A,@R1
XRL CRC16_L,A
MOV R6,#08H
CRC16_LOOP2:
MOV R3,CRC16_L
MOV R4,CRC16_H
CLR C
MOV A,CRC16_H
RRC A
MOV CRC16_H,A
MOV A,CRC16_L
RRC A
MOV CRC16_L,A
JNC CRC16_STEP
XRL CRC16_L,#01H
XRL CRC16_H,#0A0H
CRC16_STEP:
DJNZ R6,CRC16_LOOP2
INC R1
DJNZ R7,CRC16_LOOP1
RETI