谁做过CRC校验程序吗? 最好是8位的 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 以下包括crc的8位、16位、32位的算法,结帖吧,老兄!!uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;type TForm1 = class(TForm) Memo1: TMemo; Label1: TLabel; Label2: TLabel; Label3: TLabel; GenPoly8Edit: TEdit; GenPoly16Edit: TEdit; GenPoly32Edit: TEdit; TestCRC8Btn: TButton; TestCRC16Btn: TButton; TestCRC32Btn: TButton; CalCRC8Btn: TButton; CalCRC16Btn: TButton; CalCRC32Btn: TButton; CRC8ResultEdit: TEdit; CRC16ResultEdit: TEdit; CRC32ResultEdit: TEdit; procedure FormCreate(Sender: TObject); procedure TestCRC16BtnClick(Sender: TObject); procedure TestCRC8BtnClick(Sender: TObject); procedure TestCRC32BtnClick(Sender: TObject); procedure CalCRC16BtnClick(Sender: TObject); procedure CalCRC8BtnClick(Sender: TObject); procedure CalCRC32BtnClick(Sender: TObject); private { Private declarations } public { Public declarations } end;var Form1: TForm1; // 生成多项式的值(多项式因子) // 注意:CRC16是数据流的高位先计算,多项式因子不变 // 而CRC32和CRC8都是数据流的低位先计算,所以多项式因子的高/低位对调 // 比如CRC32由$04C11DB7变为$EDB88320,CRC8由$31变为$8C GenPoly32: DWord; // CRC-32 = X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1 // 00000100 11000001 00011101 10110111($04C11DB7) 低位先行($EDB88320) GenPoly16: Word; // CRC-CCITT16 = X16+X12+X5+1, 00010000 00100001($1021) 高位先行 // CRC-16 = X16+X15+X2+1, 10000000 00000101($8005) 高位先行 GenPoly8: Byte; // CRC-8 = X8+X5+X4+1, 00110001($31) 低位先行($8C) GenPoly4: Byte; // CRC-4 = X4+X1+1, 0011($03) CRC32Tab: array [0..255] of DWord; // CRC32快速计算查表 CRC16Tab: array [0..255] of Word; // CRC16快速计算查表 CRC8Tab : array [0..255] of Byte; // CRC8 快速计算查表implementation{$R *.DFM}///////////////////////////////////////////////////////////// 16位CRC:按位计算,速度最慢,占用空间最少// 注:数据流是高位先行///////////////////////////////////////////////////////////function CalCRC16(data, crc, genpoly: Word): Word;var i: Integer;begin // 方法1:摘自XMODEM协议 crc := crc xor (data shl 8); for i:=0 to 7 do if (crc and $8000) <> 0 then // 只测试最高位 crc := (crc shl 1) xor genpoly // 最高位为1,移位和异或处理 else crc := crc shl 1; // 否则只移位(乘2) Result := crc;{ // 方法2:算法有些不同,但结果相同 data := data shl 8; // 移到高字节 for i:=7 downto 0 do begin if ((data xor crc) and $8000) <> 0 then // 只测试最高位 crc := (crc shl 1) xor genpoly // 最高位为1,移位和异或处理 else crc := crc shl 1; // 否则只移位(乘2) data := data shl 1; // 处理下一位 end; Result := crc; // 方法3:摘自<<CRC算法原理及C语言实现>> for i:=7 downto 0 do begin if (crc and $8000) <> 0 then crc := (crc*2) xor genpoly // 余式CRC乘以2再求CRC else crc := crc*2; if (data and (1 shl i)) <> 0 then crc := crc xor genpoly; // 再加上本位的CRC end; Result := crc;}{; MCS51的CRC-16计算函数(多项式因子为$1021, 高位先行); 调用:CRC16H/CRC16L=原CRC16值(16位,初始值为0000h),A=待计算数据(8位); 结果:CRC16H/CRC16L=计算后的CRC16值(16位)CalCRC16: push 00h ; Save R0 push acc ; Save Acc mov r0,#08 ; 8 Bits In A Byte xrl CRC16H,a ; CRC16H ^= Datalp1: clr c ; 0 Into Low Bit mov a,CRC16L ; CRC16H/CRC16L <<= 1 rlc a mov CRC16L,a mov a,CRC16H rlc a mov CRC16H,a jnc lp2 ; Skip If Bit 15 Wasn't Set xrl CRC16H,#10h ; CRC16H/CRC16L ^= $1021 xrl CRC16L,#21hlp2: djnz r0,lp1 ; Repeat R0 More Times pop acc ; Recover Acc pop 00h ; Recover R0 ret}end;///////////////////////////////////////////////////////////// 16位CRC:生成CRC16表(256项),用于快速查表计算// 在程序初始化时就先调用,预先生成CRC16Tab[256]查表数据///////////////////////////////////////////////////////////procedure InitCRC16Tab(genpoly: DWord);var i: Integer;begin for i:=0 to 255 do CRC16Tab[i] := CalCRC16(i,0,genpoly);end;///////////////////////////////////////////////////////////// 16位CRC:通过查表快速计算,速度快,占用空间多// 要预先生成CRCTab[256]查表数据///////////////////////////////////////////////////////////function QuickCRC16(data, crc: Word): Word;begin // 方法1:按字节计算CRC,通过查表(256项)快速计算 // 速度最快,占用空间最多,需要256项数据的表格空间 crc := CRC16Tab[(crc shr 8) xor data] xor (crc shl 8); Result := crc;{ // 方法2:按半字节计算CRC,通过查表(16项)快速计算 // 速度比较快,占用空间也比较少,只需要表格的前16项数据 crc := CRCTab[(crc shr 12) xor (data shr 4)] xor (crc shl 4); crc := CRCTab[(crc shr 12) xor (data and $0F)] xor (crc shl 4); Result := crc;}{; MCS51的CRC-16快速查表计算函数; 要预先生成CRC16查表数据,起始地址CRC16Tab,按高/低字节顺序存放(512字节); 调用:CRC16H/CRC16L=原CRC16值(16位,初始值为0000h),A=待计算数据(8位); 结果:CRC16H/CRC16L=计算后的CRC16值(16位)QuickCRC16: push dph ; Save DPH push dpl ; Save DPL push acc ; Save Acc mov dptr,#CRC16Tab ; Point To Table xrl a,CRC16H ; XOR High Of CRC With Character call UTIL_ADCAD ; Add 'A' To 'DPTR' call UTIL_ADCAD ; Add 'A' To 'DPTR' (Yes, Twice) clr a ; Get High Byte From Table Entry movc a,@a+dptr xrl a,CRC16L ; XOR With Low mov CRC16H,a ; Store To High Of CRC clr a ; Get Low Byte From Table Entry inc dptr movc a,@a+dptr mov CRC16L,a ; Store To Low Of CRC pop acc ; Recover Acc pop dpl ; Recover DPL pop dph ; Recover DPH ret}end; ///////////////////////////////////////////////////////////// 8位CRC:按位计算,速度最慢,占用空间最少// 注:数据流是低位先行,与16位CRC相反///////////////////////////////////////////////////////////function CalCRC8(data, crc, genpoly: Byte): Byte;var i: Integer;begin // 方法1:摘自XMODEM协议, 模仿CRC16计算方法, 但是低位先行 crc := crc xor data; for i:=0 to 7 do if (crc and $01) <> 0 then // 只测试最低位 crc := (crc shr 1) xor genpoly // 最低位为1,移位和异或处理 else crc := crc shr 1; // 否则只移位(除2) Result := crc;{ // 方法2:算法有些不同,但结果相同 for i:=0 to 7 do begin if ((data xor crc) and $01) <> 0 then // 只测试最低位 crc := (crc shr 1) xor genpoly // 最低位为1,移位和异或处理 else crc := crc shr 1; // 否则只移位(除2) data := data shr 1; // 处理下一位 end; Result := crc;}{; MCS51的CRC-8计算函数(多项式因子为$8C, 低位先行); 调用:B=原CRC8值(8位,初始值为00h),A=待计算数据(8位); 结果:B=计算后的CRC8值(8位)CalCRC8: push 00h ; Save R0 push acc ; Save Acc mov r0,#08 ; 8 Bits In A Byte xrl b,a ; CRC8 ^= Datalp1: clr c ; 0 Into High Bit mov a,b ; CRC8 >>= 1 rrc a mov b,a jnc lp2 ; Skip If Bit 0 Wasn't Set xrl b,#8Ch ; CRC8 ^= $8Clp2: djnz r0,lp1 ; Repeat R0 More Times pop acc ; Recover Acc pop 00h ; Recover R0 ret}end;///////////////////////////////////////////////////////////// 8位CRC:生成CRC8表(256项),用于快速查表计算// 在程序初始化时就先调用,预先生成CRC8Tab[256]查表数据///////////////////////////////////////////////////////////procedure InitCRC8Tab(genpoly: DWord);var i: Integer;begin for i:=0 to 255 do CRC8Tab[i] := CalCRC8(i,0,genpoly);end;///////////////////////////////////////////////////////////// 8位CRC:通过查表快速计算,速度快,占用空间多// 注:数据流是低位先行,与16位CRC相反// 要预先生成CRC8Tab[256]查表数据///////////////////////////////////////////////////////////function QuickCRC8(data, crc: Byte): Word;begin crc := CRC8Tab[crc xor data]; Result := crc;{; MCS51的CRC-8快速查表计算函数; 要预先生成CRC8查表数据,起始地址CRC8Tab,按顺序存放(256字节); 调用:B=原CRC8值(8位,初始值为00h),A=待计算数据(8位); 结果:B=计算后的CRC8值(8位)QuickCRC8: push dph ; Save DPH push dpl ; Save DPL push acc ; Save Acc mov dptr,#CRC8Tab ; Point To Table xrl a,b ; XOR In CRC movc a,@a+dptr ; Get New CRC Byte mov b,a ; Store Back pop acc ; Recover Acc pop dpl ; Recover DPL pop dph ; Recover DPH ret}end;///////////////////////////////////////////////////////////// 32位CRC:按位计算,速度最慢,占用空间最少// 注:数据流是低位先行,与16位CRC相反///////////////////////////////////////////////////////////function CalCRC32(data, crc, genpoly: DWord): DWord;var i: Integer;begin // 方法1:摘自XMODEM协议, 模仿CRC16计算方法, 但是低位先行 crc := crc xor data; for i:=0 to 7 do if (crc and $01) <> 0 then // 只测试最低位 crc := (crc shr 1) xor genpoly // 最低位为1,移位和异或处理 else crc := crc shr 1; // 否则只移位(除2) Result := crc;end;///////////////////////////////////////////////////////////// 32位CRC:生成CRC32表(256项),用于快速查表计算// 在程序初始化时就先调用,预先生成CRC32Tab[256]查表数据///////////////////////////////////////////////////////////procedure InitCRC32Tab(genpoly: DWord);var i: Integer;begin for i:=0 to 255 do CRC32Tab[i] := CalCRC32(i,0,genpoly);end;///////////////////////////////////////////////////////////// 32位CRC:通过查表快速计算,速度快,占用空间多// 注:数据流是低位先行,与16位CRC相反// 要预先生成CRC32Tab[256]查表数据///////////////////////////////////////////////////////////function QuickCRC32(data, crc: DWord): DWord;begin crc := CRC32Tab[Byte(crc xor data)] xor (crc shr 8); Result := crc;end; ///////////////////////////////////////////////////////////// 初始化///////////////////////////////////////////////////////////procedure TForm1.FormCreate(Sender: TObject);begin GenPoly8 := StrToInt(GenPoly8Edit.Text); InitCRC8Tab(GenPoly8); // 先生成CRC8表(256项),用于快速查表计算 GenPoly16 := StrToInt(GenPoly16Edit.Text); InitCRC16Tab(GenPoly16); // 先生成CRC16表(256项),用于快速查表计算 GenPoly32 := StrToInt(GenPoly32Edit.Text); InitCRC32Tab(GenPoly32); // 先生成CRC32表(256项),用于快速查表计算end;///////////////////////////////////////////////////////////// 测试比较CRC16/CRC8/CRC32的不同算法// 若CRC初始值为0,则结果与快速查表表格数据相同///////////////////////////////////////////////////////////procedure TForm1.TestCRC16BtnClick(Sender: TObject);var data, crc, crcstart: Word;begin crcstart := $1234; // $0000; Memo1.Clear; Memo1.Lines.Add('16bit CRC'); for data:=0 to 255 do begin crc := CalCRC16(data,crcstart,GenPoly16); // 按位计算CRC Memo1.Text := Memo1.Text + IntToHex(crc, 4) + ' '; end; Memo1.Lines.Add(''); Memo1.Lines.Add('16bit Quick CRC'); for data:=0 to 255 do begin crc := QuickCRC16(data,crcstart); // 按字节查表计算CRC Memo1.Text := Memo1.Text + IntToHex(crc, 4) + ' '; end;end;procedure TForm1.TestCRC8BtnClick(Sender: TObject);var data, crc, crcstart: Byte;begin crcstart := $12; // $00 Memo1.Clear; Memo1.Lines.Add('8bit CRC'); for data:=0 to 255 do begin crc := CalCRC8(data,crcstart,GenPoly8); // 按位计算CRC Memo1.Text := Memo1.Text + IntToHex(crc, 2) + ' '; end; Memo1.Lines.Add(''); Memo1.Lines.Add('8bit Quick CRC'); for data:=0 to 255 do begin crc := QuickCRC8(data,crcstart); // 按字节查表计算CRC Memo1.Text := Memo1.Text + IntToHex(crc, 2) + ' '; end;end;procedure TForm1.TestCRC32BtnClick(Sender: TObject);var data, crc, crcstart: DWord;begin crcstart := $12345678; // $00000000; Memo1.Clear; Memo1.Lines.Add('32bit CRC'); for data:=0 to 255 do begin crc := CalCRC32(data,crcstart,GenPoly32); // 按位计算CRC Memo1.Text := Memo1.Text + IntToHex(crc, 8) + ' '; end; Memo1.Lines.Add(''); Memo1.Lines.Add('32bit Quick CRC'); for data:=0 to 255 do begin crc := QuickCRC32(data,crcstart); // 按字节查表计算CRC Memo1.Text := Memo1.Text + IntToHex(crc, 8) + ' '; end;end;///////////////////////////////////////////////////////////// 从文本字串中分解出16进制的数据,返回这些8位数据组成的字串// 文本字串分解规则:// 1.数据是用16进制表示的8位数据(如FC,3D等)// 2.每个数据只取最后两个16进制字符,如1F3D只取3D,前面多余部分抛弃// 3.每个数据之间用空格或回车换行等格式符号隔开///////////////////////////////////////////////////////////function GetDataFromText(str: String): String;var i, p1, p2: Integer;begin Result := ''; while str <> '' do begin i := 0; p1 := Pos(' ',str); p2 := Pos(#13#10,str); if p1=1 then // 空格在最前面 begin Delete(str,1,1); continue; end; if p2=1 then // #13#10在最前面 begin Delete(str,1,2); continue; end; if (p1=0) and (p2=0) and (str<>'') then // 都没有找到,结束 begin i := StrToIntDef('$'+str,0); Delete(str,1,Length(str)); end; if ((p1>0) and (p2=0)) or // 找到空格 ((p1>0) and (p2>0) and (p1<p2)) then // 或都找到,但空格在前 begin i := StrToIntDef('$'+Copy(str,1,p1-1),0); Delete(str,1,p1); end; if ((p1=0) and (p2>0)) or // 找到#13#10 ((p1>0) and (p2>0) and (p1>p2)) then // 或都找到,但空格在后 begin i := StrToIntDef('$'+Copy(str,1,p2-1),0); Delete(str,1,p2+1); end; Result := Result + Chr(i); // 8位数据转为字符 end; // whileend;///////////////////////////////////////////////////////////// 计算一组数据的CRC16/CRC8/CRC32结果// 数据来源于文本框中的数据字串///////////////////////////////////////////////////////////procedure TForm1.CalCRC16BtnClick(Sender: TObject);var i: Integer; databuf: String; data, crc: Word;begin databuf := GetDataFromText(Memo1.Text); // 从文本中读取数据 crc := 0; // CRC初始值 for i:=1 to Length(databuf) do begin data := Ord(databuf[i]); // 字符转为8位数据 crc := CalCRC16(data,crc,GenPoly16); // 按位计算CRC// crc := QuickCRC16(data,crc); // 快速查表计算CRC end; CRC16ResultEdit.Text := 'CRC16 = ' + IntToHex(crc,4); // 显示结果end;procedure TForm1.CalCRC8BtnClick(Sender: TObject);var i: Integer; databuf: String; data, crc: Byte;begin databuf := GetDataFromText(Memo1.Text); // 从文本中读取数据 crc := 0; // CRC初始值 for i:=1 to Length(databuf) do begin data := Ord(databuf[i]); // 字符转为8位数据 crc := CalCRC8(data,crc,GenPoly8); // 按位计算CRC// crc := QuickCRC8(data,crc); // 快速查表计算CRC end; CRC8ResultEdit.Text := 'CRC8 = ' + IntToHex(crc,2); // 显示结果end;procedure TForm1.CalCRC32BtnClick(Sender: TObject);var i: Integer; databuf: String; data, crc: DWord;begin databuf := GetDataFromText(Memo1.Text); // 从文本中读取数据 crc := 0; // CRC初始值 for i:=1 to Length(databuf) do begin data := Ord(databuf[i]); // 字符转为8位数据 crc := CalCRC32(data,crc,GenPoly32); // 按位计算CRC// crc := QuickCRC32(data,crc); // 快速查表计算CRC end; CRC32ResultEdit.Text := 'CRC32 = ' + IntToHex(crc,8); // 显示结果end;end. 谁能帮我把delphi转成 bcb Delphi下如何读写大文件,这个问题困扰我好久了。 【CSDN开心辞典】可用分最多的ID是谁 阻塞模式接受数据不全,崩溃中....... 誰有Delphi6.0的update2補丁,高分購買! 有使用过Idudpserver编写多线程程序的高手吗,麻烦给个DEMO?谢谢!!! 郁闷的求教:delphi菜单中project下的compile和build菜单项有什么区别呀? 自动登陆程序??????? 一个关于WinSocket的问题 大侠帮忙!!! 大家帮帮我,急用!!! 我想在引用另一过程中的一个LABEL的CAPTION值应如何做?
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;type
TForm1 = class(TForm)
Memo1: TMemo;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
GenPoly8Edit: TEdit;
GenPoly16Edit: TEdit;
GenPoly32Edit: TEdit;
TestCRC8Btn: TButton;
TestCRC16Btn: TButton;
TestCRC32Btn: TButton;
CalCRC8Btn: TButton;
CalCRC16Btn: TButton;
CalCRC32Btn: TButton;
CRC8ResultEdit: TEdit;
CRC16ResultEdit: TEdit;
CRC32ResultEdit: TEdit;
procedure FormCreate(Sender: TObject);
procedure TestCRC16BtnClick(Sender: TObject);
procedure TestCRC8BtnClick(Sender: TObject);
procedure TestCRC32BtnClick(Sender: TObject);
procedure CalCRC16BtnClick(Sender: TObject);
procedure CalCRC8BtnClick(Sender: TObject);
procedure CalCRC32BtnClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1; // 生成多项式的值(多项式因子)
// 注意:CRC16是数据流的高位先计算,多项式因子不变
// 而CRC32和CRC8都是数据流的低位先计算,所以多项式因子的高/低位对调
// 比如CRC32由$04C11DB7变为$EDB88320,CRC8由$31变为$8C
GenPoly32: DWord; // CRC-32 = X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+1
// 00000100 11000001 00011101 10110111($04C11DB7) 低位先行($EDB88320)
GenPoly16: Word; // CRC-CCITT16 = X16+X12+X5+1, 00010000 00100001($1021) 高位先行
// CRC-16 = X16+X15+X2+1, 10000000 00000101($8005) 高位先行
GenPoly8: Byte; // CRC-8 = X8+X5+X4+1, 00110001($31) 低位先行($8C)
GenPoly4: Byte; // CRC-4 = X4+X1+1, 0011($03) CRC32Tab: array [0..255] of DWord; // CRC32快速计算查表
CRC16Tab: array [0..255] of Word; // CRC16快速计算查表
CRC8Tab : array [0..255] of Byte; // CRC8 快速计算查表implementation{$R *.DFM}///////////////////////////////////////////////////////////
// 16位CRC:按位计算,速度最慢,占用空间最少
// 注:数据流是高位先行
///////////////////////////////////////////////////////////
function CalCRC16(data, crc, genpoly: Word): Word;
var i: Integer;
begin
// 方法1:摘自XMODEM协议
crc := crc xor (data shl 8);
for i:=0 to 7 do
if (crc and $8000) <> 0 then // 只测试最高位
crc := (crc shl 1) xor genpoly // 最高位为1,移位和异或处理
else crc := crc shl 1; // 否则只移位(乘2)
Result := crc;
{
// 方法2:算法有些不同,但结果相同
data := data shl 8; // 移到高字节
for i:=7 downto 0 do
begin
if ((data xor crc) and $8000) <> 0 then // 只测试最高位
crc := (crc shl 1) xor genpoly // 最高位为1,移位和异或处理
else crc := crc shl 1; // 否则只移位(乘2)
data := data shl 1; // 处理下一位
end;
Result := crc; // 方法3:摘自<<CRC算法原理及C语言实现>>
for i:=7 downto 0 do
begin
if (crc and $8000) <> 0 then
crc := (crc*2) xor genpoly // 余式CRC乘以2再求CRC
else crc := crc*2;
if (data and (1 shl i)) <> 0 then
crc := crc xor genpoly; // 再加上本位的CRC
end;
Result := crc;
}
{
; MCS51的CRC-16计算函数(多项式因子为$1021, 高位先行)
; 调用:CRC16H/CRC16L=原CRC16值(16位,初始值为0000h),A=待计算数据(8位)
; 结果:CRC16H/CRC16L=计算后的CRC16值(16位)
CalCRC16:
push 00h ; Save R0
push acc ; Save Acc
mov r0,#08 ; 8 Bits In A Byte
xrl CRC16H,a ; CRC16H ^= Data
lp1: clr c ; 0 Into Low Bit
mov a,CRC16L ; CRC16H/CRC16L <<= 1
rlc a
mov CRC16L,a
mov a,CRC16H
rlc a
mov CRC16H,a
jnc lp2 ; Skip If Bit 15 Wasn't Set
xrl CRC16H,#10h ; CRC16H/CRC16L ^= $1021
xrl CRC16L,#21h
lp2: djnz r0,lp1 ; Repeat R0 More Times
pop acc ; Recover Acc
pop 00h ; Recover R0
ret
}
end;///////////////////////////////////////////////////////////
// 16位CRC:生成CRC16表(256项),用于快速查表计算
// 在程序初始化时就先调用,预先生成CRC16Tab[256]查表数据
///////////////////////////////////////////////////////////
procedure InitCRC16Tab(genpoly: DWord);
var i: Integer;
begin
for i:=0 to 255 do
CRC16Tab[i] := CalCRC16(i,0,genpoly);
end;///////////////////////////////////////////////////////////
// 16位CRC:通过查表快速计算,速度快,占用空间多
// 要预先生成CRCTab[256]查表数据
///////////////////////////////////////////////////////////
function QuickCRC16(data, crc: Word): Word;
begin
// 方法1:按字节计算CRC,通过查表(256项)快速计算
// 速度最快,占用空间最多,需要256项数据的表格空间
crc := CRC16Tab[(crc shr 8) xor data] xor (crc shl 8);
Result := crc;
{
// 方法2:按半字节计算CRC,通过查表(16项)快速计算
// 速度比较快,占用空间也比较少,只需要表格的前16项数据
crc := CRCTab[(crc shr 12) xor (data shr 4)] xor (crc shl 4);
crc := CRCTab[(crc shr 12) xor (data and $0F)] xor (crc shl 4);
Result := crc;
}
{
; MCS51的CRC-16快速查表计算函数
; 要预先生成CRC16查表数据,起始地址CRC16Tab,按高/低字节顺序存放(512字节)
; 调用:CRC16H/CRC16L=原CRC16值(16位,初始值为0000h),A=待计算数据(8位)
; 结果:CRC16H/CRC16L=计算后的CRC16值(16位)
QuickCRC16:
push dph ; Save DPH
push dpl ; Save DPL
push acc ; Save Acc
mov dptr,#CRC16Tab ; Point To Table
xrl a,CRC16H ; XOR High Of CRC With Character
call UTIL_ADCAD ; Add 'A' To 'DPTR'
call UTIL_ADCAD ; Add 'A' To 'DPTR' (Yes, Twice)
clr a ; Get High Byte From Table Entry
movc a,@a+dptr
xrl a,CRC16L ; XOR With Low
mov CRC16H,a ; Store To High Of CRC
clr a ; Get Low Byte From Table Entry
inc dptr
movc a,@a+dptr
mov CRC16L,a ; Store To Low Of CRC
pop acc ; Recover Acc
pop dpl ; Recover DPL
pop dph ; Recover DPH
ret
}
end;
// 8位CRC:按位计算,速度最慢,占用空间最少
// 注:数据流是低位先行,与16位CRC相反
///////////////////////////////////////////////////////////
function CalCRC8(data, crc, genpoly: Byte): Byte;
var i: Integer;
begin
// 方法1:摘自XMODEM协议, 模仿CRC16计算方法, 但是低位先行
crc := crc xor data;
for i:=0 to 7 do
if (crc and $01) <> 0 then // 只测试最低位
crc := (crc shr 1) xor genpoly // 最低位为1,移位和异或处理
else crc := crc shr 1; // 否则只移位(除2)
Result := crc;
{
// 方法2:算法有些不同,但结果相同
for i:=0 to 7 do
begin
if ((data xor crc) and $01) <> 0 then // 只测试最低位
crc := (crc shr 1) xor genpoly // 最低位为1,移位和异或处理
else crc := crc shr 1; // 否则只移位(除2)
data := data shr 1; // 处理下一位
end;
Result := crc;
}
{
; MCS51的CRC-8计算函数(多项式因子为$8C, 低位先行)
; 调用:B=原CRC8值(8位,初始值为00h),A=待计算数据(8位)
; 结果:B=计算后的CRC8值(8位)
CalCRC8:
push 00h ; Save R0
push acc ; Save Acc
mov r0,#08 ; 8 Bits In A Byte
xrl b,a ; CRC8 ^= Data
lp1: clr c ; 0 Into High Bit
mov a,b ; CRC8 >>= 1
rrc a
mov b,a
jnc lp2 ; Skip If Bit 0 Wasn't Set
xrl b,#8Ch ; CRC8 ^= $8C
lp2: djnz r0,lp1 ; Repeat R0 More Times
pop acc ; Recover Acc
pop 00h ; Recover R0
ret
}
end;///////////////////////////////////////////////////////////
// 8位CRC:生成CRC8表(256项),用于快速查表计算
// 在程序初始化时就先调用,预先生成CRC8Tab[256]查表数据
///////////////////////////////////////////////////////////
procedure InitCRC8Tab(genpoly: DWord);
var i: Integer;
begin
for i:=0 to 255 do
CRC8Tab[i] := CalCRC8(i,0,genpoly);
end;///////////////////////////////////////////////////////////
// 8位CRC:通过查表快速计算,速度快,占用空间多
// 注:数据流是低位先行,与16位CRC相反
// 要预先生成CRC8Tab[256]查表数据
///////////////////////////////////////////////////////////
function QuickCRC8(data, crc: Byte): Word;
begin
crc := CRC8Tab[crc xor data];
Result := crc;
{
; MCS51的CRC-8快速查表计算函数
; 要预先生成CRC8查表数据,起始地址CRC8Tab,按顺序存放(256字节)
; 调用:B=原CRC8值(8位,初始值为00h),A=待计算数据(8位)
; 结果:B=计算后的CRC8值(8位)
QuickCRC8:
push dph ; Save DPH
push dpl ; Save DPL
push acc ; Save Acc
mov dptr,#CRC8Tab ; Point To Table
xrl a,b ; XOR In CRC
movc a,@a+dptr ; Get New CRC Byte
mov b,a ; Store Back
pop acc ; Recover Acc
pop dpl ; Recover DPL
pop dph ; Recover DPH
ret
}
end;///////////////////////////////////////////////////////////
// 32位CRC:按位计算,速度最慢,占用空间最少
// 注:数据流是低位先行,与16位CRC相反
///////////////////////////////////////////////////////////
function CalCRC32(data, crc, genpoly: DWord): DWord;
var i: Integer;
begin
// 方法1:摘自XMODEM协议, 模仿CRC16计算方法, 但是低位先行
crc := crc xor data;
for i:=0 to 7 do
if (crc and $01) <> 0 then // 只测试最低位
crc := (crc shr 1) xor genpoly // 最低位为1,移位和异或处理
else crc := crc shr 1; // 否则只移位(除2)
Result := crc;
end;///////////////////////////////////////////////////////////
// 32位CRC:生成CRC32表(256项),用于快速查表计算
// 在程序初始化时就先调用,预先生成CRC32Tab[256]查表数据
///////////////////////////////////////////////////////////
procedure InitCRC32Tab(genpoly: DWord);
var i: Integer;
begin
for i:=0 to 255 do
CRC32Tab[i] := CalCRC32(i,0,genpoly);
end;///////////////////////////////////////////////////////////
// 32位CRC:通过查表快速计算,速度快,占用空间多
// 注:数据流是低位先行,与16位CRC相反
// 要预先生成CRC32Tab[256]查表数据
///////////////////////////////////////////////////////////
function QuickCRC32(data, crc: DWord): DWord;
begin
crc := CRC32Tab[Byte(crc xor data)] xor (crc shr 8);
Result := crc;
end;
// 初始化
///////////////////////////////////////////////////////////
procedure TForm1.FormCreate(Sender: TObject);
begin
GenPoly8 := StrToInt(GenPoly8Edit.Text);
InitCRC8Tab(GenPoly8); // 先生成CRC8表(256项),用于快速查表计算 GenPoly16 := StrToInt(GenPoly16Edit.Text);
InitCRC16Tab(GenPoly16); // 先生成CRC16表(256项),用于快速查表计算 GenPoly32 := StrToInt(GenPoly32Edit.Text);
InitCRC32Tab(GenPoly32); // 先生成CRC32表(256项),用于快速查表计算
end;///////////////////////////////////////////////////////////
// 测试比较CRC16/CRC8/CRC32的不同算法
// 若CRC初始值为0,则结果与快速查表表格数据相同
///////////////////////////////////////////////////////////
procedure TForm1.TestCRC16BtnClick(Sender: TObject);
var data, crc, crcstart: Word;
begin
crcstart := $1234; // $0000;
Memo1.Clear;
Memo1.Lines.Add('16bit CRC');
for data:=0 to 255 do
begin
crc := CalCRC16(data,crcstart,GenPoly16); // 按位计算CRC
Memo1.Text := Memo1.Text + IntToHex(crc, 4) + ' ';
end; Memo1.Lines.Add('');
Memo1.Lines.Add('16bit Quick CRC');
for data:=0 to 255 do
begin
crc := QuickCRC16(data,crcstart); // 按字节查表计算CRC
Memo1.Text := Memo1.Text + IntToHex(crc, 4) + ' ';
end;
end;procedure TForm1.TestCRC8BtnClick(Sender: TObject);
var data, crc, crcstart: Byte;
begin
crcstart := $12; // $00
Memo1.Clear;
Memo1.Lines.Add('8bit CRC');
for data:=0 to 255 do
begin
crc := CalCRC8(data,crcstart,GenPoly8); // 按位计算CRC
Memo1.Text := Memo1.Text + IntToHex(crc, 2) + ' ';
end; Memo1.Lines.Add('');
Memo1.Lines.Add('8bit Quick CRC');
for data:=0 to 255 do
begin
crc := QuickCRC8(data,crcstart); // 按字节查表计算CRC
Memo1.Text := Memo1.Text + IntToHex(crc, 2) + ' ';
end;
end;procedure TForm1.TestCRC32BtnClick(Sender: TObject);
var data, crc, crcstart: DWord;
begin
crcstart := $12345678; // $00000000;
Memo1.Clear;
Memo1.Lines.Add('32bit CRC');
for data:=0 to 255 do
begin
crc := CalCRC32(data,crcstart,GenPoly32); // 按位计算CRC
Memo1.Text := Memo1.Text + IntToHex(crc, 8) + ' ';
end; Memo1.Lines.Add('');
Memo1.Lines.Add('32bit Quick CRC');
for data:=0 to 255 do
begin
crc := QuickCRC32(data,crcstart); // 按字节查表计算CRC
Memo1.Text := Memo1.Text + IntToHex(crc, 8) + ' ';
end;
end;///////////////////////////////////////////////////////////
// 从文本字串中分解出16进制的数据,返回这些8位数据组成的字串
// 文本字串分解规则:
// 1.数据是用16进制表示的8位数据(如FC,3D等)
// 2.每个数据只取最后两个16进制字符,如1F3D只取3D,前面多余部分抛弃
// 3.每个数据之间用空格或回车换行等格式符号隔开
///////////////////////////////////////////////////////////
function GetDataFromText(str: String): String;
var i, p1, p2: Integer;
begin
Result := '';
while str <> '' do
begin
i := 0;
p1 := Pos(' ',str);
p2 := Pos(#13#10,str); if p1=1 then // 空格在最前面
begin Delete(str,1,1); continue; end;
if p2=1 then // #13#10在最前面
begin Delete(str,1,2); continue; end; if (p1=0) and (p2=0) and (str<>'') then // 都没有找到,结束
begin
i := StrToIntDef('$'+str,0);
Delete(str,1,Length(str));
end;
if ((p1>0) and (p2=0)) or // 找到空格
((p1>0) and (p2>0) and (p1<p2)) then // 或都找到,但空格在前
begin
i := StrToIntDef('$'+Copy(str,1,p1-1),0);
Delete(str,1,p1);
end;
if ((p1=0) and (p2>0)) or // 找到#13#10
((p1>0) and (p2>0) and (p1>p2)) then // 或都找到,但空格在后
begin
i := StrToIntDef('$'+Copy(str,1,p2-1),0);
Delete(str,1,p2+1);
end;
Result := Result + Chr(i); // 8位数据转为字符
end; // while
end;///////////////////////////////////////////////////////////
// 计算一组数据的CRC16/CRC8/CRC32结果
// 数据来源于文本框中的数据字串
///////////////////////////////////////////////////////////
procedure TForm1.CalCRC16BtnClick(Sender: TObject);
var
i: Integer;
databuf: String;
data, crc: Word;
begin
databuf := GetDataFromText(Memo1.Text); // 从文本中读取数据
crc := 0; // CRC初始值
for i:=1 to Length(databuf) do
begin
data := Ord(databuf[i]); // 字符转为8位数据
crc := CalCRC16(data,crc,GenPoly16); // 按位计算CRC
// crc := QuickCRC16(data,crc); // 快速查表计算CRC
end;
CRC16ResultEdit.Text := 'CRC16 = ' + IntToHex(crc,4); // 显示结果
end;procedure TForm1.CalCRC8BtnClick(Sender: TObject);
var
i: Integer;
databuf: String;
data, crc: Byte;
begin
databuf := GetDataFromText(Memo1.Text); // 从文本中读取数据
crc := 0; // CRC初始值
for i:=1 to Length(databuf) do
begin
data := Ord(databuf[i]); // 字符转为8位数据
crc := CalCRC8(data,crc,GenPoly8); // 按位计算CRC
// crc := QuickCRC8(data,crc); // 快速查表计算CRC
end;
CRC8ResultEdit.Text := 'CRC8 = ' + IntToHex(crc,2); // 显示结果
end;procedure TForm1.CalCRC32BtnClick(Sender: TObject);
var
i: Integer;
databuf: String;
data, crc: DWord;
begin
databuf := GetDataFromText(Memo1.Text); // 从文本中读取数据
crc := 0; // CRC初始值
for i:=1 to Length(databuf) do
begin
data := Ord(databuf[i]); // 字符转为8位数据
crc := CalCRC32(data,crc,GenPoly32); // 按位计算CRC
// crc := QuickCRC32(data,crc); // 快速查表计算CRC
end;
CRC32ResultEdit.Text := 'CRC32 = ' + IntToHex(crc,8); // 显示结果
end;end.