⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.pas

📁 计算CRC16/CRC8/CRC32的程序
💻 PAS
📖 第 1 页 / 共 2 页
字号:
; 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.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -