?? main.pas
字號(hào):
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
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;
CRCStartEdit: TEdit;
Label4: TLabel;
Panel1: TPanel;
HighFirstRB: TRadioButton;
Label5: TLabel;
LowFirstRB: TRadioButton;
Panel2: TPanel;
Label6: TLabel;
BitCalcRB: TRadioButton;
TableCalcRB: TRadioButton;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
FlipResultCB: TCheckBox;
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;
// 生成多項(xiàng)式的值(多項(xiàng)式因子)
// 注意:CRC16是數(shù)據(jù)流的高位先計(jì)算,多項(xiàng)式因子不變
// 而CRC32和CRC8都是數(shù)據(jù)流的低位先計(jì)算,所以多項(xiàng)式因子的高/低位對(duì)調(diào)
// 比如CRC32由$04C11DB7變?yōu)?EDB88320,CRC8由$31變?yōu)?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快速計(jì)算查表
CRC16Tab: array [0..255] of Word; // CRC16快速計(jì)算查表
CRC8Tab : array [0..255] of Byte; // CRC8 快速計(jì)算查表
HighFirst: Boolean; // 數(shù)據(jù)流高位先行的標(biāo)志
implementation
{$R *.DFM}
///////////////////////////////////////////////////////////
// 16位CRC:按位計(jì)算,速度最慢,占用空間最少
///////////////////////////////////////////////////////////
function CalCRC16(data, crc, genpoly: Word): Word;
var i: Integer;
begin
if HighFirst then // 數(shù)據(jù)流高位先行
begin
// 方法1:摘自XMODEM協(xié)議
crc := crc xor (data shl 8);
for i:=0 to 7 do
if (crc and $8000) <> 0 then // 只測(cè)試最高位
crc := (crc shl 1) xor genpoly // 最高位為1,移位和異或處理
else crc := crc shl 1; // 否則只移位(乘2)
Result := crc;
{
// 方法2:算法有些不同,但結(jié)果相同
data := data shl 8; // 移到高字節(jié)
for i:=7 downto 0 do
begin
if ((data xor crc) and $8000) <> 0 then // 只測(cè)試最高位
crc := (crc shl 1) xor genpoly // 最高位為1,移位和異或處理
else crc := crc shl 1; // 否則只移位(乘2)
data := data shl 1; // 處理下一位
end;
Result := crc;
// 方法3:摘自<<CRC算法原理及C語(yǔ)言實(shí)現(xiàn)>>
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;
}
end
else // 數(shù)據(jù)流低位先行
begin
// 方法1:摘自XMODEM協(xié)議
// CRC-CCITT多項(xiàng)式因子$8408,CRC-16多項(xiàng)式因子$A001
// 高位先行和低位先行的計(jì)算結(jié)果不同
crc := crc xor data;
for i:=0 to 7 do
if (crc and $01) <> 0 then // 只測(cè)試最低位
crc := (crc shr 1) xor genpoly // 最低位為1,移位和異或處理
else crc := crc shr 1; // 否則只移位(除2)
Result := crc;
end;
{
; MCS51的CRC-16計(jì)算函數(shù)(多項(xiàng)式因子為$1021, 高位先行)
; 調(diào)用:CRC16H/CRC16L=原CRC16值(16位,初始值為0000h),A=待計(jì)算數(shù)據(jù)(8位)
; 結(jié)果:CRC16H/CRC16L=計(jì)算后的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項(xiàng)),用于快速查表計(jì)算
// 在程序初始化時(shí)就先調(diào)用,預(yù)先生成CRC16Tab[256]查表數(shù)據(jù)
///////////////////////////////////////////////////////////
procedure InitCRC16Table(genpoly: DWord);
var i: Integer;
begin
for i:=0 to 255 do
CRC16Tab[i] := CalCRC16(i,0,genpoly);
end;
///////////////////////////////////////////////////////////
// 16位CRC:通過(guò)查表快速計(jì)算,速度快,占用空間多
// 要預(yù)先生成CRCTab[256]查表數(shù)據(jù)
///////////////////////////////////////////////////////////
function QuickCRC16(data, crc: Word): Word;
begin
if HighFirst then // 數(shù)據(jù)流高位先行
begin
// 方法1:按字節(jié)計(jì)算CRC,通過(guò)查表(256項(xiàng))快速計(jì)算
// 速度最快,占用空間最多,需要256項(xiàng)數(shù)據(jù)的表格空間
crc := CRC16Tab[(crc shr 8) xor data] xor (crc shl 8);
Result := crc;
{
// 方法2:按半字節(jié)計(jì)算CRC,通過(guò)查表(16項(xiàng))快速計(jì)算
// 速度比較快,占用空間也比較少,只需要表格的前16項(xiàng)數(shù)據(jù)
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;
}
end
else // 數(shù)據(jù)流低位先行
begin
crc := CRC16Tab[Byte(crc xor data)] xor (crc shr 8);
Result := crc;
end;
{
; MCS51的CRC-16快速查表計(jì)算函數(shù)
; 要預(yù)先生成CRC16查表數(shù)據(jù),起始地址CRC16Tab,按高/低字節(jié)順序存放(512字節(jié))
; 調(diào)用:CRC16H/CRC16L=原CRC16值(16位,初始值為0000h),A=待計(jì)算數(shù)據(jù)(8位)
; 結(jié)果:CRC16H/CRC16L=計(jì)算后的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:按位計(jì)算,速度最慢,占用空間最少
///////////////////////////////////////////////////////////
function CalCRC8(data, crc, genpoly: Byte): Byte;
var i: Integer;
begin
if HighFirst then // 數(shù)據(jù)流高位先行
begin
crc := crc xor data;
for i:=0 to 7 do
if (crc and $80) <> 0 then // 只測(cè)試最高位
crc := (crc shl 1) xor genpoly // 最高位為1,移位和異或處理
else crc := crc shl 1; // 否則只移位(乘2)
Result := crc;
end
else // 數(shù)據(jù)流低位先行
begin
// 方法1:摘自XMODEM協(xié)議
crc := crc xor data;
for i:=0 to 7 do
if (crc and $01) <> 0 then // 只測(cè)試最低位
crc := (crc shr 1) xor genpoly // 最低位為1,移位和異或處理
else crc := crc shr 1; // 否則只移位(除2)
Result := crc;
{
// 方法2:算法有些不同,但結(jié)果相同
for i:=0 to 7 do
begin
if ((data xor crc) and $01) <> 0 then // 只測(cè)試最低位
crc := (crc shr 1) xor genpoly // 最低位為1,移位和異或處理
else crc := crc shr 1; // 否則只移位(除2)
data := data shr 1; // 處理下一位
end;
Result := crc;
}
end;
{
; MCS51的CRC-8計(jì)算函數(shù)(多項(xiàng)式因子為$8C, 低位先行)
; 調(diào)用:B=原CRC8值(8位,初始值為00h),A=待計(jì)算數(shù)據(jù)(8位)
; 結(jié)果:B=計(jì)算后的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項(xiàng)),用于快速查表計(jì)算
// 在程序初始化時(shí)就先調(diào)用,預(yù)先生成CRC8Tab[256]查表數(shù)據(jù)
///////////////////////////////////////////////////////////
procedure InitCRC8Table(genpoly: DWord);
var i: Integer;
begin
for i:=0 to 255 do
CRC8Tab[i] := CalCRC8(i,0,genpoly);
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -