?? main.pas
字號:
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
if HighFirst then // 數據流高位先行
begin
crc := crc xor (data shl 24);
for i:=0 to 7 do
if (crc and $80000000) <> 0 then // 只測試最高位
crc := (crc shl 1) xor genpoly // 最高位為1,移位和異或處理
else crc := crc shl 1; // 否則只移位(乘2)
Result := crc;
end
else // 數據流低位先行
begin
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;
end;
///////////////////////////////////////////////////////////
// 32位CRC:生成CRC32表(256項),用于快速查表計算
// 在程序初始化時就先調用,預先生成CRC32Tab[256]查表數據
///////////////////////////////////////////////////////////
procedure InitCRC32Table(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
if HighFirst then // 數據流高位先行
begin
crc := CRC32Tab[(crc shr 24) xor data] xor (crc shl 8);
Result := crc;
end
else // 數據流低位先行
begin
crc := CRC32Tab[Byte(crc xor data)] xor (crc shr 8);
Result := crc;
end;
end;
///////////////////////////////////////////////////////////
// 測試比較CRC16/CRC8/CRC32的不同算法
// 若CRC初始值為0,則結果與快速查表表格數據相同
///////////////////////////////////////////////////////////
procedure TForm1.TestCRC16BtnClick(Sender: TObject);
var data, crc, crcstart: Word;
begin
HighFirst := HighFirstRB.Checked;
GenPoly16 := StrToIntDef(GenPoly16Edit.Text,0);
InitCRC16Table(GenPoly16); // 先生成CRC16表(256項),用于快速查表計算
crcstart := StrToIntDef(CRCStartEdit.Text,0); // CRC初始值
Memo1.Clear;
Memo1.Lines.Add('16bit CRC');
for data:=0 to 255 do
begin
if BitCalcRB.Checked then
crc := CalCRC16(data,crcstart,GenPoly16) // 按位計算CRC
else
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
HighFirst := HighFirstRB.Checked;
GenPoly8 := StrToIntDef(GenPoly8Edit.Text,0);
InitCRC8Table(GenPoly8); // 先生成CRC8表(256項),用于快速查表計算
crcstart := StrToIntDef(CRCStartEdit.Text,0); // CRC初始值
Memo1.Clear;
Memo1.Lines.Add('8bit CRC');
for data:=0 to 255 do
begin
if BitCalcRB.Checked then
crc := CalCRC8(data,crcstart,GenPoly8) // 按位計算CRC
else
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
HighFirst := HighFirstRB.Checked;
GenPoly32 := StrToIntDef(GenPoly32Edit.Text,0);
InitCRC32Table(GenPoly32); // 先生成CRC32表(256項),用于快速查表計算
crcstart := StrToIntDef(CRCStartEdit.Text,0); // CRC初始值
Memo1.Clear;
Memo1.Lines.Add('32bit CRC');
for data:=0 to 255 do
begin
if BitCalcRB.Checked then
crc := CalCRC32(data,crcstart,GenPoly32) // 按位計算CRC
else
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
HighFirst := HighFirstRB.Checked;
GenPoly16 := StrToIntDef(GenPoly16Edit.Text,0);
InitCRC16Table(GenPoly16); // 先生成CRC16表(256項),用于快速查表計算
crc := StrToIntDef(CRCStartEdit.Text,0); // CRC初始值
databuf := GetDataFromText(Memo1.Text); // 從文本中讀取數據
for i:=1 to Length(databuf) do
begin
data := Ord(databuf[i]); // 字符轉為8位數據
if BitCalcRB.Checked then
crc := CalCRC16(data,crc,GenPoly16) // 按位計算CRC
else
crc := QuickCRC16(data,crc); // 快速查表計算CRC
end;
CRC16ResultEdit.Text := '$' + IntToHex(crc,4); // 顯示結果
end;
procedure TForm1.CalCRC8BtnClick(Sender: TObject);
var
i: Integer;
databuf: String;
data, crc: Byte;
begin
HighFirst := HighFirstRB.Checked;
GenPoly8 := StrToIntDef(GenPoly8Edit.Text,0);
InitCRC8Table(GenPoly8); // 先生成CRC8表(256項),用于快速查表計算
crc := StrToIntDef(CRCStartEdit.Text,0); // CRC初始值
databuf := GetDataFromText(Memo1.Text); // 從文本中讀取數據
for i:=1 to Length(databuf) do
begin
data := Ord(databuf[i]); // 字符轉為8位數據
if BitCalcRB.Checked then
crc := CalCRC8(data,crc,GenPoly8) // 按位計算CRC
else
crc := QuickCRC8(data,crc); // 快速查表計算CRC
end;
CRC8ResultEdit.Text := '$' + IntToHex(crc,2); // 顯示結果
end;
procedure TForm1.CalCRC32BtnClick(Sender: TObject);
var
i: Integer;
databuf: String;
data, crc: DWord;
begin
HighFirst := HighFirstRB.Checked;
GenPoly32 := StrToIntDef(GenPoly32Edit.Text,0);
InitCRC32Table(GenPoly32); // 先生成CRC32表(256項),用于快速查表計算
crc := StrToIntDef(CRCStartEdit.Text,0); // CRC初始值
databuf := GetDataFromText(Memo1.Text); // 從文本中讀取數據
for i:=1 to Length(databuf) do
begin
data := Ord(databuf[i]); // 字符轉為8位數據
if BitCalcRB.Checked then
crc := CalCRC32(data,crc,GenPoly32) // 按位計算CRC
else
crc := QuickCRC32(data,crc); // 快速查表計算CRC
end;
if FlipResultCB.Checked then crc := not crc;
CRC32ResultEdit.Text := '$' + IntToHex(crc,8); // 顯示結果
// 由于是低位先行,計算得到的CRC-32也要按低字節在先的順序排列
// 比如數據12 34,計算CRC-32=59408466,結果要按66 84 40 59順序
// 最后驗證數據正確性時,12 34 66 84 40 59的CRC-32=0
end;
end.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -