|
#1
|
|||
|
|||
расчет CRC16
Надо подсчитать контрольную сумму пол полиному X^16+X^15+X^2+1.
есть код: Код:
var Form1: TForm1; implementation CONST crctab: ARRAY[0..255] OF WORD = ( $0000, $1021, $2042, $3063, $4084, $50a5, $60c6, $70e7, $8108, $9129, $a14a, $b16b, $c18c, $d1ad, $e1ce, $f1ef, $1231, $0210, $3273, $2252, $52b5, $4294, $72f7, $62d6, $9339, $8318, $b37b, $a35a, $d3bd, $c39c, $f3ff, $e3de, $2462, $3443, $0420, $1401, $64e6, $74c7, $44a4, $5485, $a56a, $b54b, $8528, $9509, $e5ee, $f5cf, $c5ac, $d58d, $3653, $2672, $1611, $0630, $76d7, $66f6, $5695, $46b4, $b75b, $a77a, $9719, $8738, $f7df, $e7fe, $d79d, $c7bc, $48c4, $58e5, $6886, $78a7, $0840, $1861, $2802, $3823, $c9cc, $d9ed, $e98e, $f9af, $8948, $9969, $a90a, $b92b, $5af5, $4ad4, $7ab7, $6a96, $1a71, $0a50, $3a33, $2a12, $dbfd, $cbdc, $fbbf, $eb9e, $9b79, $8b58, $bb3b, $ab1a, $6ca6, $7c87, $4ce4, $5cc5, $2c22, $3c03, $0c60, $1c41, $edae, $fd8f, $cdec, $ddcd, $ad2a, $bd0b, $8d68, $9d49, $7e97, $6eb6, $5ed5, $4ef4, $3e13, $2e32, $1e51, $0e70, $ff9f, $efbe, $dfdd, $cffc, $bf1b, $af3a, $9f59, $8f78, $9188, $81a9, $b1ca, $a1eb, $d10c, $c12d, $f14e, $e16f, $1080, $00a1, $30c2, $20e3, $5004, $4025, $7046, $6067, $83b9, $9398, $a3fb, $b3da, $c33d, $d31c, $e37f, $f35e, $02b1, $1290, $22f3, $32d2, $4235, $5214, $6277, $7256, $b5ea, $a5cb, $95a8, $8589, $f56e, $e54f, $d52c, $c50d, $34e2, $24c3, $14a0, $0481, $7466, $6447, $5424, $4405, $a7db, $b7fa, $8799, $97b8, $e75f, $f77e, $c71d, $d73c, $26d3, $36f2, $0691, $16b0, $6657, $7676, $4615, $5634, $d94c, $c96d, $f90e, $e92f, $99c8, $89e9, $b98a, $a9ab, $5844, $4865, $7806, $6827, $18c0, $08e1, $3882, $28a3, $cb7d, $db5c, $eb3f, $fb1e, $8bf9, $9bd8, $abbb, $bb9a, $4a75, $5a54, $6a37, $7a16, $0af1, $1ad0, $2ab3, $3a92, $fd2e, $ed0f, $dd6c, $cd4d, $bdaa, $ad8b, $9de8, $8dc9, $7c26, $6c07, $5c64, $4c45, $3ca2, $2c83, $1ce0, $0cc1, $ef1f, $ff3e, $cf5d, $df7c, $af9b, $bfba, $8fd9, $9ff8, $6e17, $7e36, $4e55, $5e74, $2e93, $3eb2, $0ed1, $1ef0); {$R *.dfm} function crc16(cp:Byte;crc:WORD):Word; begin //UpdCrc crc16:= crctab[((crc SHR 8) AND 255)] XOR (crc SHL 8) XOR cp end; procedure TForm1.btn1Click(Sender: TObject); var crc:Word; i:Integer; Buf:byte; begin if length(edt3.text)=0 then ShowMessage('Поле входных данных не заполнено'); crc:=$FFFF; for i:=1 to Length(edt3.Text) do begin crc:=crc16(byte(edt3.Text[i]),crc); end; edt2.Text:=IntToHex(crc,0); end; Где я не прав? Почему выдается не верный ответ? Заранее благодарен. |
#2
|
|||
|
|||
Может кто поможет переконвертировать код С в Delphi?
while (len--) crc = (crc >> 8) ^ Crc16Table[(crc & 0xFF) ^ *pcBlock++]; return crc; |
#3
|
||||
|
||||
Я помогу, если дашь не "отгрызок" кода, а полный фрагмент.
Да и зачем? Google, запрос "crc16 delphi" Третий результат - ссылка на тему в "programmersforum", где есть прямая ссылка на юнит CRC16/32 с примером использования. Но, насколько я понял, ошибка гораздо проще. Тут: Код:
crc:=$FFFF; crc:=0; Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj Последний раз редактировалось PhoeniX, 28.06.2010 в 13:57. |
#4
|
|||
|
|||
Я по этому примеру и делаю.
crc должен принимать значение $FFFF (данные с вики) -> Код:
Name : CRC-16 Poly : 0x8005 x^16 + x^15 + x^2 + 1 Init : 0xFFFF Revert: true XorOut: 0x0000 Check : 0x4B37 ("123456789") MaxLen: 4095 байт (32767 бит) - обнаружение одинарных, двойных, тройных и всех нечетных ошибок Но я пробовал и с 0, все равно считает не верно: так как при вычислении КС, ответ приписанный к входным данным, при повторном вычислении, должен возвращать в ответ 0. Т.е. Вх: F70302640008 КС: 10FD. А при Вх: F7030264000810FD КС: 00 . Вот так должна работать программа. А у меня получается с начальным значением Crc =$FFFF: Вх: F70302640008 КС:712C Вх: F70302640008712C КС: 4F55. С начальным значением CRC = 0: Вх: F70302640008 КС: F5D5. Вх: F70302640008F5D5 КС: 28C5. Еще сейчас пришлю весь код программы. |
#5
|
|||
|
|||
Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) lbl1: TLabel; lbl2: TLabel; lbl3: TLabel; btn1: TButton; btn2: TButton; edt2: TEdit; edt3: TEdit; btn3: TButton; procedure btn2Click(Sender: TObject); procedure btn1Click(Sender: TObject); procedure edt3KeyPress(Sender: TObject; var Key: Char); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation CONST crctab: ARRAY[0..255] OF WORD = ( $0000, $1021, $2042, $3063, $4084, $50a5, $60c6, $70e7, $8108, $9129, $a14a, $b16b, $c18c, $d1ad, $e1ce, $f1ef, $1231, $0210, $3273, $2252, $52b5, $4294, $72f7, $62d6, $9339, $8318, $b37b, $a35a, $d3bd, $c39c, $f3ff, $e3de, $2462, $3443, $0420, $1401, $64e6, $74c7, $44a4, $5485, $a56a, $b54b, $8528, $9509, $e5ee, $f5cf, $c5ac, $d58d, $3653, $2672, $1611, $0630, $76d7, $66f6, $5695, $46b4, $b75b, $a77a, $9719, $8738, $f7df, $e7fe, $d79d, $c7bc, $48c4, $58e5, $6886, $78a7, $0840, $1861, $2802, $3823, $c9cc, $d9ed, $e98e, $f9af, $8948, $9969, $a90a, $b92b, $5af5, $4ad4, $7ab7, $6a96, $1a71, $0a50, $3a33, $2a12, $dbfd, $cbdc, $fbbf, $eb9e, $9b79, $8b58, $bb3b, $ab1a, $6ca6, $7c87, $4ce4, $5cc5, $2c22, $3c03, $0c60, $1c41, $edae, $fd8f, $cdec, $ddcd, $ad2a, $bd0b, $8d68, $9d49, $7e97, $6eb6, $5ed5, $4ef4, $3e13, $2e32, $1e51, $0e70, $ff9f, $efbe, $dfdd, $cffc, $bf1b, $af3a, $9f59, $8f78, $9188, $81a9, $b1ca, $a1eb, $d10c, $c12d, $f14e, $e16f, $1080, $00a1, $30c2, $20e3, $5004, $4025, $7046, $6067, $83b9, $9398, $a3fb, $b3da, $c33d, $d31c, $e37f, $f35e, $02b1, $1290, $22f3, $32d2, $4235, $5214, $6277, $7256, $b5ea, $a5cb, $95a8, $8589, $f56e, $e54f, $d52c, $c50d, $34e2, $24c3, $14a0, $0481, $7466, $6447, $5424, $4405, $a7db, $b7fa, $8799, $97b8, $e75f, $f77e, $c71d, $d73c, $26d3, $36f2, $0691, $16b0, $6657, $7676, $4615, $5634, $d94c, $c96d, $f90e, $e92f, $99c8, $89e9, $b98a, $a9ab, $5844, $4865, $7806, $6827, $18c0, $08e1, $3882, $28a3, $cb7d, $db5c, $eb3f, $fb1e, $8bf9, $9bd8, $abbb, $bb9a, $4a75, $5a54, $6a37, $7a16, $0af1, $1ad0, $2ab3, $3a92, $fd2e, $ed0f, $dd6c, $cd4d, $bdaa, $ad8b, $9de8, $8dc9, $7c26, $6c07, $5c64, $4c45, $3ca2, $2c83, $1ce0, $0cc1, $ef1f, $ff3e, $cf5d, $df7c, $af9b, $bfba, $8fd9, $9ff8, $6e17, $7e36, $4e55, $5e74, $2e93, $3eb2, $0ed1, $1ef0); {$R *.dfm} function crc16(data:Byte;crc:WORD):Word; begin //UpdCrc crc16:=crctab[((crc shr 8) and 255)] xor (crc SHL 8) XOR data ; end; procedure TForm1.btn2Click(Sender: TObject); begin Close; end; procedure TForm1.btn1Click(Sender: TObject); var crc:Word; i,j:Integer; st:string; begin if length(edt3.text)=0 then ShowMessage('Поле данных пусто'); crc:=$FFFF; for i:=1 to Length(edt3.Text) do begin crc:=crc16(Byte(edt3.Text[i]),crc); end; edt2.Text:=IntToHex(crc,0); end; procedure TForm1.edt3KeyPress(Sender: TObject; var Key: Char); begin if Key in [#8,'0'..'9','a'..'f','A'..'F'] then Key:=System.UpCase(Key) else begin ShowMessage('Недопустимый формат данных'); Key:=#0; end; end; |
#6
|
||||
|
||||
У меня логичный вопрос: Вы в поле "Edt3" вводите значение в каком виде? HEX? Тогда вам надо считывать из Edit по ДВА символа и переводить их в байты, а не просто преобразовывать...
Код:
Procedure TForm1.btn1Click(Sender: TObject); Var crc: Word; i: Integer; b: Byte; Begin If edt3.text = '' Then // Лишняя функция Length была ShowMessage('Поле данных пусто'); Else Begin // Если поле данных было не пусто - продолжаем crc := $FFFF; // crc := 0; ? i := 1; While i<Length(edt3.Text) Do Begin b := StrToInt('$' + edt3.Text[i] + edt3.Text[i + 1]); // Преобразуем 2 символа в байт crc := crc16(b, crc); inc(i, 2); // Смещаем позицию на 2 символа End; End; edt2.Text := IntToHex(crc, 0); End; Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj Последний раз редактировалось PhoeniX, 28.06.2010 в 17:11. |
#7
|
|||
|
|||
Спасибо, теперь понял.
только вот видимо проблема у меня еще и функции crc16, так как при вычислении КС, ответ приписанный к входным данным, при повторном вычислении, должен возвращать в ответ 0. Т.е. Вх: F70302640008 КС: 10FD. А при Вх: F7030264000810FD КС: 00. Код:
function crc16(data:Byte;crc:WORD):Word; begin //UpdCrc crc16:=crctab[((crc shr 8) and 255)] xor (crc SHL 8) XOR data ; end; А получается: Вх: F70302640008 КС: D368 Вх: F70302640008D368 КС: 7EB2 все С# функция выглядит вот так Код:
unsigned short Crc16(unsigned char * pcBlock, unsigned short len) { unsigned short crc = 0xFFFF; while (len--) crc = (crc >> 8) ^ Crc16Table[(crc & 0xFF) ^ *pcBlock++]; return crc; может найдутся люди, которые перефразируют ее в Delphi? |
#8
|
||||
|
||||
Код:
crc = (crc >> 8) ^ Crc16Table[(crc & 0xFF) ^ *pcBlock++]; Код:
crc:= (crc srh 8) xor Crc16Table[(crc and $FF) xor data]; А где ты вот такое Код:
crc16:=crctab[((crc shr 8) and 255)] xor (crc SHL 8) XOR data ; ============== Добавлено спустя 100500 секунд Нашёл, вопрос снят. Хрен знает, что это значит. Но вроде не одно и то же. Оставайтесь хорошими людьми... VK id2634397, ds [at] phoenix [dot] dj Последний раз редактировалось PhoeniX, 29.06.2010 в 00:48. |
#9
|
|||
|
|||
Спасибо, всем! Все заработало.
выкладываю рабочий код. Код:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) lbl1: TLabel; lbl2: TLabel; lbl3: TLabel; btn1: TButton; btn2: TButton; edt2: TEdit; edt3: TEdit; btn3: TButton; procedure btn2Click(Sender: TObject); procedure edt3KeyPress(Sender: TObject; var Key: Char); procedure btn1Click(Sender: TObject); procedure btn3Click(Sender: TObject); private { Private declarations } public { Public declarations } end; type TBuffer = array of Byte; var Form1: TForm1; implementation CONST crctab: ARRAY[0..255] OF WORD = ( $0000, $C0C1, $C181, $0140, $C301, $03C0, $0280, $C241, $C601, $06C0, $0780, $C741, $0500, $C5C1, $C481, $0440, $CC01, $0CC0, $0D80, $CD41, $0F00, $CFC1, $CE81, $0E40, $0A00, $CAC1, $CB81, $0B40, $C901, $09C0, $0880, $C841, $D801, $18C0, $1980, $D941, $1B00, $DBC1, $DA81, $1A40, $1E00, $DEC1, $DF81, $1F40, $DD01, $1DC0, $1C80, $DC41, $1400, $D4C1, $D581, $1540, $D701, $17C0, $1680, $D641, $D201, $12C0, $1380, $D341, $1100, $D1C1, $D081, $1040, $F001, $30C0, $3180, $F141, $3300, $F3C1, $F281, $3240, $3600, $F6C1, $F781, $3740, $F501, $35C0, $3480, $F441, $3C00, $FCC1, $FD81, $3D40, $FF01, $3FC0, $3E80, $FE41, $FA01, $3AC0, $3B80, $FB41, $3900, $F9C1, $F881, $3840, $2800, $E8C1, $E981, $2940, $EB01, $2BC0, $2A80, $EA41, $EE01, $2EC0, $2F80, $EF41, $2D00, $EDC1, $EC81, $2C40, $E401, $24C0, $2580, $E541, $2700, $E7C1, $E681, $2640, $2200, $E2C1, $E381, $2340, $E101, $21C0, $2080, $E041, $A001, $60C0, $6180, $A141, $6300, $A3C1, $A281, $6240, $6600, $A6C1, $A781, $6740, $A501, $65C0, $6480, $A441, $6C00, $ACC1, $AD81, $6D40, $AF01, $6FC0, $6E80, $AE41, $AA01, $6AC0, $6B80, $AB41, $6900, $A9C1, $A881, $6840, $7800, $B8C1, $B981, $7940, $BB01, $7BC0, $7A80, $BA41, $BE01, $7EC0, $7F80, $BF41, $7D00, $BDC1, $BC81, $7C40, $B401, $74C0, $7580, $B541, $7700, $B7C1, $B681, $7640, $7200, $B2C1, $B381, $7340, $B101, $71C0, $7080, $B041, $5000, $90C1, $9181, $5140, $9301, $53C0, $5280, $9241, $9601, $56C0, $5780, $9741, $5500, $95C1, $9481, $5440, $9C01, $5CC0, $5D80, $9D41, $5F00, $9FC1, $9E81, $5E40, $5A00, $9AC1, $9B81, $5B40, $9901, $59C0, $5880, $9841, $8801, $48C0, $4980, $8941, $4B00, $8BC1, $8A81, $4A40, $4E00, $8EC1, $8F81, $4F40, $8D01, $4DC0, $4C80, $8C41, $4400, $84C1, $8581, $4540, $8701, $47C0, $4680, $8641, $8201, $42C0, $4380, $8341, $4100, $81C1, $8081, $4040 ); {$R *.dfm} function crc16(twoSym:array of Word; size:Word):Word; var i:Integer; crc:Word; begin crc:=$FFFF; for i:=0 to ((size div 2)-1) do begin crc:= (crc shr 8) xor CrcTab[(crc and $FF) xor twoSym[i]]; end; Result:=crc; end; function StrToByte(p1:string):integer; const hex:array['A'..'F'] of Word=(10,11,12,13,14,15); var Int,i:Integer; begin Int:=0; for i := 1 to Length(P1) do if P1[i] < 'A' then Int := Int * 16 + ORD(P1[i]) - 48 else Int := Int * 16 + HEX[p1[i]]; Result:=int; end; procedure TForm1.btn2Click(Sender: TObject); begin Close; end; procedure TForm1.edt3KeyPress(Sender: TObject; var Key: Char); begin if Key in [#8,'0'..'9','a'..'f','A'..'F'] then Key:=System.UpCase(Key) else begin ShowMessage('Недопустимый формат'); Key:=#0; end; end; Procedure TForm1.btn1Click(Sender: TObject); Var crc: Word; i,j: Integer; b: array[1..100] of Word; Begin If edt3.text = '' Then ShowMessage('Поле данных пусто') Else Begin j:=1; for i := 1 to Length(edt3.Text) do begin b[i]:=StrToByte(edt3.Text[j]+edt3.Text[j+1]); j:=j+2; end; crc:= crc16(b, Length(edt3.Text)); edt2.Text :=IntToHex(crc, 2); End; End; procedure TForm1.btn3Click(Sender: TObject); var D:Word; i:Integer; begin edt2.Clear; for i := 1 to Length(edt3.Text) do begin D:=StrToByte(edt3.Text[i]); edt2.Text:=edt2.Text+IntToHex(D,0); end; end; end. |
#10
|
|||
|
|||
Еще маленький вопрос.
Где менять отображение в поле edit, справа налево и наоборот? Т.е. Программа высчитывает CRC=FD10 последовательности F70302640008. А надо, чтоб отображалось 10FD, так как это верный ответ. |
#11
|
|||
|
|||
Усе, Гуд!
Функцию просто надо было поправить вот так. Код:
function crc16(twoSym:array of Word; size:Word):Word; var i:Integer; crc:Word; begin crc:=$FFFF; for i:=0 to ((size div 2)-1) do begin crc:= (crc shr 8) xor CrcTab[(crc and $FF) xor twoSym[i]]; end; Result:=(crc shr 8) or (crc shl 8); end; Кто считает, что извращено слишком, готов услышать конструктивную критику=) |