如何生成CRC-6/CDMA2000-A的CRC表?现有代码生成结果异常
CRC-6/CDMA2000-A 查表生成与计算故障排查
问题说明
我需要创建CRC-6/CDMA2000-A的CRC查表,此前用下述算法生成各类CRC-8的表均正常,但生成CRC-6的表后,无论是表本身还是使用该表计算CRC-6的函数都无法正常工作。
原查表生成代码
const POLYNOMIAL = $27; BitsCRC = 6; var Table: array[0..255] of Byte; i: Integer; j: Integer; temp: Byte; S: String; Mask: Byte; begin mask := (1 shl (BitsCRC - 1)); for i:=0 to 255 do Table[i] := i ; for i:=0 to 255 do begin for j:=7 downto 0 do begin temp := Table[i] and Mask; if (temp <> 0) then begin Table[i] := Table[i] shl 1; Table[i] := Table[i] xor POLYNOMIAL; end else begin Table[i] := Table[i] shl 1; end; end; end; S := ''; for i:=0 to 255 do begin S := S + '$' + IntToHex(Table[i], 2) +', '; if i mod 16 = 15 then begin Memo1.Lines.Add(s); S := ''; end; end; end;
生成的错误数组
$00, $F5, $CD, $38, $9A, $6F, $57, $A2, $34, $C1, $F9, $0C, $AE, $5B, $63, $96, $4F, $BA, $82, $77, $D5, $20, $18, $ED, $7B, $8E, $B6, $43, $E1, $14, $2C, $D9, $9E, $6B, $53, $A6, $04, $F1, $C9, $3C, $AA, $5F, $67, $92, $30, $C5, $FD, $08, $D1, $24, $1C, $E9, $4B, $BE, $86, $73, $E5, $10, $28, $DD, $7F, $8A, $B2, $47, $00, $F5, $CD, $38, $9A, $6F, $57, $A2, $34, $C1, $F9, $0C, $AE, $5B, $63, $96, $4F, $BA, $82, $77, $D5, $20, $18, $ED, $7B, $8E, $B6, $43, $E1, $14, $2C, $D9, $9E, $6B, $53, $A6, $04, $F1, $C9, $3C, $AA, $5F, $67, $92, $30, $C5, $FD, $08, $D1, $24, $1C, $E9, $4B, $BE, $86, $73, $E5, $10, $28, $DD, $7F, $8A, $B2, $47, $00, $F5, $CD, $38, $9A, $6F, $57, $A2, $34, $C1, $F9, $0C, $AE, $5B, $63, $96, $4F, $BA, $82, $77, $D5, $20, $18, $ED, $7B, $8E, $B6, $43, $E1, $14, $2C, $D9, $9E, $6B, $53, $A6, $04, $F1, $C9, $3C, $AA, $5F, $67, $92, $30, $C5, $FD, $08, $D1, $24, $1C, $E9, $4B, $BE, $86, $73, $E5, $10, $28, $DD, $7F, $8A, $B2, $47, $00, $F5, $CD, $38, $9A, $6F, $57, $A2, $34, $C1, $F9, $0C, $AE, $5B, $63, $96, $4F, $BA, $82, $77, $D5, $20, $18, $ED, $7B, $8E, $B6, $43, $E1, $14, $2C, $D9, $9E, $6B, $53, $A6, $04, $F1, $C9, $3C, $AA, $5F, $67, $92, $30, $C5, $FD, $08, $D1, $24, $1C, $E9, $4B, $BE, $86, $73, $E5, $10, $28, $DD, $7F, $8A, $B2, $47
原CRC计算代码
procedure crc6_update(var CRC: Byte; Str: String); var i: Integer; begin for i:=1 to Length(Str) do CRC := CRC_Table[(CRC shl 2) xor ord(Str[i]) ] ; end; CRC := $3f; crc6_update(CRC, '123456789'); Caption := IntToHex(CRC, 2);
问题分析与修正方案
核心问题
- 查表生成逻辑错误:原代码初始将
Table[i]设为i,直接在原数组上循环移位修改,未限制CRC-6的6位宽度,导致移位后高两位数据干扰计算,最终表项出现重复(每64个值循环一次)。 - 计算代码未截断位宽:CRC是6位值,计算时未确保始终只保留低6位,可能引入无效的高两位数据。
修正后的查表生成代码
const POLYNOMIAL = $27; BitsCRC = 6; var Table: array[0..255] of Byte; i: Integer; j: Integer; temp: Byte; S: String; CRC_MASK: Byte; // 用于截断到6位 begin CRC_MASK := (1 shl BitsCRC) - 1; // 0x3F for i := 0 to 255 do begin temp := i; // 以当前字节为初始值 for j := 7 downto 0 do begin // 检查当前字节的最高位 if (temp and $80) <> 0 then begin temp := (temp shl 1) xor POLYNOMIAL; end else begin temp := temp shl 1; end; end; Table[i] := temp and CRC_MASK; // 只保留低6位结果 end; // 输出表的代码不变 S := ''; for i:=0 to 255 do begin S := S + '$' + IntToHex(Table[i], 2) +', '; if i mod 16 = 15 then begin Memo1.Lines.Add(s); S := ''; end; end; end;
修正后的CRC计算代码
procedure crc6_update(var CRC: Byte; Str: String); var i: Integer; index: Byte; begin CRC := CRC and $3F; // 确保初始值是6位有效数据 for i := 1 to Length(Str) do begin // CRC左移2位补0,与输入字节异或得到查表索引 index := (CRC shl 2) xor ord(Str[i]); // 查表后保留低6位 CRC := CRC_Table[index] and $3F; end; end; // 测试代码 var CRC: Byte; begin CRC := $3F; // CRC-6/CDMA2000-A标准初始值 crc6_update(CRC, '123456789'); // 标准结果应为0x00 Caption := IntToHex(CRC, 2); end;
验证说明
CRC-6/CDMA2000-A的标准参数为:
- 多项式:0x27(二进制100111)
- 初始值:0x3F
- 输入反转:无
- 输出反转:无
- 输出异或:0x00
使用修正后的代码计算字符串123456789,结果应为0x00,符合标准校验值。
内容的提问来源于stack exchange,提问作者DoctorWhoWho
相关产品推荐
相关产品推荐

