請教crc16 的原理 |
尚未結案
|
poemkevin
初階會員 發表:26 回覆:77 積分:30 註冊:2002-10-19 發送簡訊給我 |
以下這二個副程式是轉自http://www.ibrtses.com/delphi/dcrc.html
看不太懂它的程式邏輯寫法
是否有前輩願意幫忙指導解釋一下
謝謝! //Delphi CRC16
//位元錯誤循環碼副程式
procedure ByteCrc(data:byte;var crc:word);
var i:BYTE;
Begin
for i:=0 to 7 do
begin
if (( data and $01) xor ( crc and $0001) <> 0 ) then
begin
crc:=crc shr 1; //shift right one position
crc:=crc xor $A001;
end
else crc:=crc shr 1;
data:=data shr 1; //This line isn't Else and executed anyway .
end;
end; function StringCrc(s:shortstring):word;
var len,i:integer;
begin
result:=0;
len:=length(s);
for i:=1 to len do
ByteCrc(ord(s[i]),result);
end; {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject);
var s:shortstring;
h:word; begin
s:=edit1.Text; h:=StringCrc(s);
Edit2.Text:=inttoStr(h); end;
|
poemkevin
初階會員 發表:26 回覆:77 積分:30 註冊:2002-10-19 發送簡訊給我 |
小弟把程式看了好久,
用手算了一陣子, 用上述程式算1A這個值, 結果得出的CRC碼為A0D5,
與用手算的方式推演不同,(手算的答案1A(3141)的crc=2785)
後來仔細去思考過, 才發現它並不是將字元一次做crc的, 而是一個字一個字做crc的, 上一個字再與下一個字的crc值做xor, 小弟參考了論壇上很多前輩的文章, 編寫了一個crc16x副程式,
雖能做crc16(X^16+X^15+X^2+1), 但僅能處理二位數的處理,
而我只能土法練鋼, 仿造手算的方式, 將之變成程式,
寫得有點粗糙.
希望板主或前輩能指導一下. 怎樣才能更精簡它,
將二個副程式合成一個也可 這函式我只會用左移shl的方式, 至於我在網站看到那個寫得蠻精焊的程式,
是用右移法. 只是我一直搞不懂它的運算邏輯為什麼要這樣寫.
只大概明白它的用法, 看了好久還沒辦法很清楚, 真的有點灰心. // Hexadecimal to Binary 16進制轉2進制
function HexToBinS(Hexadecimal: string): string;
const
BCD: array [0..15] of string =
('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
'1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111');
var
i: integer;
begin if pos('$', Hexadecimal) > 0 then
begin
for i := Length(Hexadecimal) downto 1 do
Result := BCD[StrToInt(Hexadecimal[i])] + Result;
end
else
begin
for i := Length(Hexadecimal) downto 1 do
Result := BCD[StrToInt('$' + Hexadecimal[i])] + Result;
end; end; //輸入二位數算出crc碼
function CRC16X(s:shortstring):word;
var len,i,j,k,jk:integer;
su,ss:shortstring;
sk:string;
data,st:word;
begin
result:=$00;
len:=length(s); //求字串長度
su:=''; { if len >2 then
begin
showmessage('只能處理二位數');
exit;
end;
}
//將輸的二個字轉成ascii碼, 例如1A為3141
for i:=1 to len do
begin
su:=su+IntTohex(ord(s[i]),2);
end;
data:=StrToInt('$'+Trim(su));
st:=data;
sk:='';
j:=0;
k:=0;
jk:=0;
repeat
k:=0;
sk:='';
//因為CRC16用到17位bit, 為了運算, 要取值到XXXXX H
sk:=HexToBinS(IntToHex(st,5)); //將之化為二進制字串 if pos('1',sk) > 0 then //取得二進制字串第一個1的位置
begin
k:=pos('1',sk);
delete(sk,1,k-1); //將1前面的0都去除
end; if Length(sk) <= 16 then
begin
j:=j+ abs((17-Length(sk))); //共補了多少個零了, 不能超過16位
if j <=16 then
begin
st:=st shl abs(17-length(sk)); //補零(與17位元比較, 看差幾位, 就補幾個零)
st:=st xor $18005 ; //crc16=x^16+x^15+x^2+1
end else
begin
st:=st shl (16-length(sk)); //若已驗算完了, 看是否補足16個零, 差多少就補多少
break;
end;
end
else begin
st:=st xor $18005 ;
end ;
until (j >= 16 );
result:= st; //將得出的crc值傳回
end; 發表人 - poemkevin 於 2004/08/17 15:36:51
|
poemkevin
初階會員 發表:26 回覆:77 積分:30 註冊:2002-10-19 發送簡訊給我 |
加寫了一個chechksum函數. 真希望有前輩能解答小弟最上面CRC16函數疑問. // S[i]=s1 s2 s3 s4...... =Sum ; Check = Sum(S[i]) mod 255;
function CheckSums(s:String):string;
var
len,i,sum: integer;
begin
len:=0;
i:=0;
sum:=0;
len:=length(s);
for i:=1 to len do
sum:=sum ord(S[i]); result:=inttohex((sum mod 255),2); end;
|
mine
中階會員 發表:28 回覆:129 積分:56 註冊:2004-03-31 發送簡訊給我 |
HIHI
雖然日子有點久了 剛好最近在看這些資料
http://delphi.ktop.com.tw/topic.php?topic_id=54144
http://delphi.ktop.com.tw/topic.php?topic_id=45962
http://delphi.ktop.com.tw/topic.php?topic_id=19517
http://www.summitinstruments.com/library/tn410.pdf
給大大參考一下 搞不懂!搞不懂!永遠都搞不懂!! 發表人 - mine 於 2004/12/10 09:19:54
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |