У меня есть терминал, который обменивается данными через RS232 COM с компьютером. Протокол, который мне дал, говорит о том, что мне нужно отправить определенную комбинацию байтов и CRC 16 IBM вычисление данных, отправленных в концеРасчет CRC-16 C#
Мне также было предоставлено C-приложение, которое я могу проверить с помощью этого приложения записывает журнал с данными отправки и полученными данными. В этом журнале я вижу, отправляю ли я терминал этой строке hexString = "02 00 04 a0 00 01 01 03"
. Я также должен отправить этот результат данных CRC16 IBM 06 35.
Мне удалось каким-то образом перевести метод C, который был приведен в качестве примера, на C#. Но мой результат далек от того, что я знаю, я должен получить.
Я протестировал отправку данных из журнала, и все в порядке. Должно быть, мои расчеты сделаны неправильно. Я делаю что-то неправильно здесь?
Вот мой код:
CRC класс:
public enum Crc16Mode : ushort
{
ARINC_NORMAL = 0XA02B, ARINC_REVERSED = 0xD405, ARINC_REVERSED_RECIPROCAL = 0XD015,
CCITT_NORMAL = 0X1021, CCITT_REVERSED = 0X8408, CCITT_REVERSED_RECIPROCAL = 0X8810,
CDMA2000_NORMAL = 0XC867, CDMA2000_REVERSED = 0XE613, CDMA2000_REVERSED_RECIPROCAL = 0XE433,
DECT_NORMAL = 0X0589, DECT_REVERSED = 0X91A0, DECT_REVERSED_RECIPROCAL = 0X82C4,
T10_DIF_NORMAL = 0X8BB7, T10_DIF_REVERSED = 0XEDD1, T10_DIF_REVERSED_RECIPROCAL = 0XC5DB,
DNP_NORMAL = 0X3D65, DNP_REVERSED = 0XA6BC, DNP_REVERSED_RECIPROCAL = 0X9EB2,
IBM_NORMAL = 0X8005, IBM_REVERSED = 0XA001, IBM_REVERSED_RECIPROCAL = 0XC002,
OPENSAFETY_A_NORMAL = 0X5935, OPENSAFETY_A_REVERSED = 0XAC9A, OPENSAFETY_A_REVERSED_RECIPROCAL = 0XAC9A,
OPENSAFETY_B_NORMAL = 0X755B, OPENSAFETY_B_REVERSED = 0XDDAE, OPENSAFETY_B_REVERSED_RECIPROCAL = 0XBAAD,
PROFIBUS_NORMAL = 0X1DCF, PROFIBUS_REVERSED = 0XF3B8, PROFIBUS_REVERSED_RECIPROCAL = 0X8EE7
}
public class Crc16
{
readonly 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 ushort CalculateCRC(byte[] data)
{
Crc16 crcCalc = new Crc16(Crc16Mode.IBM_NORMAL);
ushort crc = crcCalc.ComputeChecksum(data);
return crc;
}
В этом методе вы можете выбрать полином из Enum.
Главных в программе Класс:
статической силы основной (String [] арг) { попробовать { Metode м = новый Metode();
string hexString = "02 00 04 a0 00 01 01 03";
byte[] bytes = m.HexStringToByteArray(hexString);
ushort crc = m.CalculateCRC(bytes);
string hexResult;
int myInt = crc;
hexResult = myInt.ToString("X");
//Console.WriteLine(crc.ToString());
Console.WriteLine(hexResult);
Console.ReadLine();
}
catch (Exception ex)
{
Metode m = new Metode();
m.writeError(ex.Message);
}
}
Преобразование из шестнадцатеричной в массив байтов:
public byte[] HexStringToByteArray(string hexString)
{
hexString = hexString.Replace(" ", "");
return Enumerable.Range(0, hexString.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hexString.Substring(x, 2), 16))
.ToArray();
}
Преобразовать из массива байтов в шестнадцатеричной строки:
public string ByteArrayToHexString(byte[] byteArray)
{
return BitConverter.ToString(byteArray);
}
Что я здесь делаю неправильно?
UPDATE:
Благодаря @MarkAdler мне удалось перевести расчет. То, что я не заметил допоздна, был тот факт, что расчет CRC должен был быть в Интернете DATA, отправленный на терминал, а не все сообщение!
Таким образом, hexString должен был быть фактически «a0 00 01 01», данные без STX/length/ETX.
Вот код для этого конкретного CRC16 Исчисления в C#:
public ushort CalculateCRC(byte[] data, int len)
{
int crc = 0, i = 0;
while (len-- != 0)
{
crc ^= data[i++] << 8;
for (int k = 0; k < 8; k++)
crc = ((crc & 0x8000) != 0) ? (crc << 1)^0x8005 : (crc << 1);
}
return (ushort)(crc & 0xffff);
}
* Что я здесь делаю неправильно? * Написал ли это сам? https://www.nuget.org/packages?q=Tags%3A%22Crc16%22 –
можете ли вы разместить главную в классе программы: Методы m = новые методы(); код полностью? – Thennarasan
Можете ли вы предоставить ссылку на документацию, с которой вы пытаетесь работать? –