CRC程序怎么编写啊?(100)

  • 主题发起人 主题发起人 snowdog
  • 开始时间 开始时间
S

snowdog

Unregistered / Unconfirmed
GUEST, unregistred user!
我这里有一个CRC要求,请问怎么编写程序,谢谢错误检测循环冗余校验(CRC)域占用两个字节,包含了一个16位的二进制值。CRC值由传送设备计算出来,然后附加到数据帧上,接收设备在接收数据时重新计算CRC值,然后与接收到的CRC域中的值进行比较,如果这两个值不相等,就发生了错误。CRC运算时,首先将一个16位的寄存器预置为全1,然后连续把数据帧中的每个字节中的8位与该寄存器的当前值进行运算,仅仅每个字节的8个数据位参与生成CRC,起始位和终止位以及可能使用的奇偶位都不影响CRC。在生成CRC时,每个字节的8位与寄存器中的内容进行异或,然后将结果向低位移位,高位则用“0”补充,最低位(LSB)移出并检测,如果是1,该寄存器就与一个预设的固定值(0A001H)进行一次异或运算,如果最低位为0,不作任何处理。上述处理重复进行,直到执行完了8次移位操作,当最后一 位(第8位)移完以后,下一个8位字节与寄存器的当前值进行异或运算,同样进行上述的另一个8次移位异或操作,当数据帧中的所有字节都作了处理,生成的最终值就是CRC值。生成一个CRC的流程为:1、预置一个16位寄存器为0FFFFH(全1),称之为CRC寄存器。2、把数据帧中的第一个字节的8位与CRC寄存器中的低字节进行异或运算,结果存回CRC寄存器。3、将CRC寄存器向右移一位,最高位填以0,最低位移出并检测。4、如果最低位为0:重复第三步(下一次移位);如果最低位为1:将CRC寄存器与一个预设的固定值(0A001H)进行异或运算。5、重复第三步和第四步直到8次移位。这样处理完了一个完整的八位。6、重复第2步到第5步来处理下一个八位,直到所有的字节处理结束。7、最终CRC寄存器得值就是CRC的值。
 
function crc16(len: Byte; ptr: PByte): LongWord;var i, : Integer; ch: Byte; crc: LongWord; begin crc := $445a; while (len > 0) do begin dec(len); ch := ptr^; inc(ptr); for i:=0 to 8-1 do begin if (crc and $8000) <> 0 then begin crc := crc shl 1; if (ch and $80) <> 0 then crc := crc or 1; crc := crc xor $1021; end else begin crc := crc shl 1; if (ch and $80) <> 0 then crc := crc or 1; end; ch := ch shl 1; end; end; result := crc; end; function CRC16(CRC: Word; Data: Pointer; DataSize: LongWord): Word; assembler;asm AND EDX,EDX JZ @Exit AND ECX,ECX JLE @Exit PUSH EBX PUSH EDI XOR EBX,EBX LEA EDI,CS:[OFFSET @CRC16]@Start: MOV BL,[EDX] XOR BL,AL SHR AX,8 XOR AX,[EDI + EBX * 2] INC EDX DEC ECX JNZ @Start POP EDI POP EBX@Exit: RET NOP@CRC16: DW 00000h, 0C0C1h, 0C181h, 00140h, 0C301h, 003C0h, 00280h, 0C241h DW 0C601h, 006C0h, 00780h, 0C741h, 00500h, 0C5C1h, 0C481h, 00440h DW 0CC01h, 00CC0h, 00D80h, 0CD41h, 00F00h, 0CFC1h, 0CE81h, 00E40h DW 00A00h, 0CAC1h, 0CB81h, 00B40h, 0C901h, 009C0h, 00880h, 0C841h DW 0D801h, 018C0h, 01980h, 0D941h, 01B00h, 0DBC1h, 0DA81h, 01A40h DW 01E00h, 0DEC1h, 0DF81h, 01F40h, 0DD01h, 01DC0h, 01C80h, 0DC41h DW 01400h, 0D4C1h, 0D581h, 01540h, 0D701h, 017C0h, 01680h, 0D641h DW 0D201h, 012C0h, 01380h, 0D341h, 01100h, 0D1C1h, 0D081h, 01040h DW 0F001h, 030C0h, 03180h, 0F141h, 03300h, 0F3C1h, 0F281h, 03240h DW 03600h, 0F6C1h, 0F781h, 03740h, 0F501h, 035C0h, 03480h, 0F441h DW 03C00h, 0FCC1h, 0FD81h, 03D40h, 0FF01h, 03FC0h, 03E80h, 0FE41h DW 0FA01h, 03AC0h, 03B80h, 0FB41h, 03900h, 0F9C1h, 0F881h, 03840h DW 02800h, 0E8C1h, 0E981h, 02940h, 0EB01h, 02BC0h, 02A80h, 0EA41h DW 0EE01h, 02EC0h, 02F80h, 0EF41h, 02D00h, 0EDC1h, 0EC81h, 02C40h DW 0E401h, 024C0h, 02580h, 0E541h, 02700h, 0E7C1h, 0E681h, 02640h DW 02200h, 0E2C1h, 0E381h, 02340h, 0E101h, 021C0h, 02080h, 0E041h DW 0A001h, 060C0h, 06180h, 0A141h, 06300h, 0A3C1h, 0A281h, 06240h DW 06600h, 0A6C1h, 0A781h, 06740h, 0A501h, 065C0h, 06480h, 0A441h DW 06C00h, 0ACC1h, 0AD81h, 06D40h, 0AF01h, 06FC0h, 06E80h, 0AE41h DW 0AA01h, 06AC0h, 06B80h, 0AB41h, 06900h, 0A9C1h, 0A881h, 06840h DW 07800h, 0B8C1h, 0B981h, 07940h, 0BB01h, 07BC0h, 07A80h, 0BA41h DW 0BE01h, 07EC0h, 07F80h, 0BF41h, 07D00h, 0BDC1h, 0BC81h, 07C40h DW 0B401h, 074C0h, 07580h, 0B541h, 07700h, 0B7C1h, 0B681h, 07640h DW 07200h, 0B2C1h, 0B381h, 07340h, 0B101h, 071C0h, 07080h, 0B041h DW 05000h, 090C1h, 09181h, 05140h, 09301h, 053C0h, 05280h, 09241h DW 09601h, 056C0h, 05780h, 09741h, 05500h, 095C1h, 09481h, 05440h DW 09C01h, 05CC0h, 05D80h, 09D41h, 05F00h, 09FC1h, 09E81h, 05E40h DW 05A00h, 09AC1h, 09B81h, 05B40h, 09901h, 059C0h, 05880h, 09841h DW 08801h, 048C0h, 04980h, 08941h, 04B00h, 08BC1h, 08A81h, 04A40h DW 04E00h, 08EC1h, 08F81h, 04F40h, 08D01h, 04DC0h, 04C80h, 08C41h DW 04400h, 084C1h, 08581h, 04540h, 08701h, 047C0h, 04680h, 08641h DW 08201h, 042C0h, 04380h, 08341h, 04100h, 081C1h, 08081h, 04040hend;
 
汇编啊。都忘记了。太底层了。
 
CRC16:{ compute updated CRC }Function UpdateCRC16(crc : Word; data : Byte) : Word;begin UpDateCRC16 := (crc SHL 8) xor (CRC16Table[(crc SHR 8) xor data]);end;function CRC16(InData: Pointer; Len: Integer; Init: WORD): WORD;var p:PByte;begin Result:=Init; p:=InData; while Len>0 do begin Result:=UpdateCRC16(Result,p^); p:=PByte(Integer(p)+1); Dec(Len); end;end;{ initialize CRC table }procedure InitCRC16Table;Var i : Integer; { calculate CRC table entry } Function CalcTable(data, genpoly, accum : Word) : Word; Var i : Word; begin data := data SHL 8; For i := 8 downto 1 do begin if (((data xor accum) and $8000) <> 0) then accum := (accum SHL 1) xor genpoly else accum := accum SHL 1; data := data SHL 1; end; CalcTable := accum; end; begin for i := 0 to 255 do CRC16Table := CalcTable(i, POLY, 0);end;
 
后退
顶部