2017-01-10 4 views
1

Попытка реконструировать протокол последовательного порта. Я не могу воссоздать crc-16 байт.CRC-CCITT Kermit 16 in C#

Согласно документации, это формат пакета

48 45 4c 4f // HELO 
01 00 00 01 // ARG 1 
00 00 00 00 // ARG 2 
00 00 00 00 // ARG 3 
00 00 00 00 // ARG 4 
00 00 00 00 // REQUEST BODY 
5c b1 00 00 // CRC-16 
b7 ba b3 b0 // Bit-wise inversion of HELO command 

Это команда записи, которая была понюхал из последовательного мониторинга

48 45 4c 4f 01 00 00 01 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 5c b1 00 00 b7 ba b3 b0 

я в состоянии воссоздать мелкий пакет, за исключением 2 байтов «5c b1». Согласно документации, байты 5c b1 представляют собой crc-ccit16 по пакету с нулями в слоте crc-16. Функция CRC16 возвращает 5C байт, но не b1.

Я использую следующий код для расчета CRC:

public class Crc16 
{ 
    static ushort[] table = new ushort[256]; 

    public ushort ComputeChecksum(params byte[] bytes) 
    { 
     ushort crc = 0; 
     for (int i = 0; i < bytes.Length; ++i) 
     { 
      byte index = (byte)(crc^bytes[i]); 
      crc = (ushort)((crc >> 8)^table[index]); 
     } 
     return crc; 
    } 

    public byte[] ComputeChecksumBytes(params byte[] bytes) 
    { 
     ushort crc = ComputeChecksum(bytes); 
     return BitConverter.GetBytes(crc); 
    } 

    public Crc16(Crc16Mode mode) 
    { 
     ushort polynomial = (ushort)mode; 
     ushort value; 
     ushort temp; 
     for (ushort i = 0; i < table.Length; ++i) 
     { 
      value = 0; 
      temp = i; 
      for (byte j = 0; j < 8; ++j) 
      { 
       if (((value^temp) & 0x0001) != 0) 
       { 
        value = (ushort)((value >> 1)^polynomial); 
       } 
       else { 
        value >>= 1; 
       } 
       temp >>= 1; 
      } 
      table[i] = value; 
     } 
    } 
} 

     public byte[] getPreCRC16Bytes() 
    { 
      byte[] x = new byte[28]; 
      byte[] cmdBytes = Encoding.ASCII.GetBytes(this.cmd.ToString()); 
      byte[] arg1Bytes = (byte[])this.arg1; 
      byte[] arg2Bytes = (byte[])this.arg2; 
      byte[] arg3Bytes = (byte[])this.arg3; 
      byte[] arg4Bytes = (byte[])this.arg4; 
      byte[] bodyLen = { 0x00, 0x00, 0x00, 0x00 }; 
      byte[] emptyCRC = { 0x00, 0x00, 0x00, 0x00 }; 
      byte[] checksum = Encoding.ASCII.GetBytes(this.checksum); 
      var list = new List<byte>(); 
      list.AddRange(cmdBytes); 
      list.AddRange(arg1Bytes); 
      list.AddRange(arg2Bytes); 
      list.AddRange(arg3Bytes); 
      list.AddRange(arg4Bytes); 
      list.AddRange(bodyLen); 
      list.AddRange(emptyCRC); 
      list.AddRange(checksum); 
      var xx = list.ToArray(); 

     string hex = BitConverter.ToString(cmdBytes).Replace("-", ""); 

     return list.ToArray(); 

    } 

ответ

1

С этого одного примера, как представляется, X-25 16-bit CRC, не CCITT (Кермит) 16-битный CRC. Существует вероятность 1/65536, что это совпадение, так как есть только один пример, поэтому вам нужно попробовать его с помощью нескольких дополнительных нюхаемых пакетов.

Вот простой, бит-в-времени C подпрограмма, которая вычисляет, что CRC (назвав его с mem == NULL возвращает начальное значение для CRC):

unsigned crc16x_25_bit(unsigned crc, void const *mem, size_t len) { 
    unsigned char const *data = mem; 
    if (data == NULL) 
     return 0; 
    crc = ~crc; 
    crc &= 0xffff; 
    while (len--) { 
     crc ^= *data++; 
     for (unsigned k = 0; k < 8; k++) 
      crc = crc & 1 ? (crc >> 1)^0x8408 : crc >> 1; 
    } 
    crc ^= 0xffff; 
    return crc; 
} 

Этот код был порожденных crcany, который также генерирует код для управляемых таблицами версий, как по байт, так и по словам.

+0

Если у вас есть этот код на C#? – user1698144

+0

Нет, это должно быть легко перевести. Или вы можете просто изменить код в своем вопросе. 'polyomial' -' 0x8408'. Исходным значением для 'crc' является' 0xffff' вместо '0'. Вместо 'return crc;', поставьте 'return crc^0xffff;'. Это должно сделать это. Ваш опубликованный код не имеет полинома в любом месте, поэтому вам нужно инициализировать класс с помощью полинома. Или было бы лучше просто сделать это константой в коде. –

+0

По-прежнему не повезло .. – user1698144