I am trying to generate a CRC-16 using C#. The hardware I am using for RS232 requires the input string to be HEX. The screenshot below shows the correct conversion, For a test, I need 8000 to be 0xC061, however the C# method that generates CRC-16 must be able to convert any given HEX string.
I have tried using Nito.KitchenSink.CRC
I have also tried the below which generates 8009 when 8000 is inputted -
public string CalcCRC16(string strInput)
{
ushort crc = 0x0000;
byte[] data = GetBytesFromHexString(strInput);
for (int i = 0; i < data.Length; i++)
{
crc ^= (ushort)(data[i] << 8);
for (int j = 0; j < 8; j++)
{
if ((crc & 0x8000) > 0)
crc = (ushort)((crc << 1) ^ 0x8005);
else
crc <<= 1;
}
}
return crc.ToString("X4");
}
public Byte[] GetBytesFromHexString(string strInput)
{
Byte[] bytArOutput = new Byte[] { };
if (!string.IsNullOrEmpty(strInput) && strInput.Length % 2 == 0)
{
SoapHexBinary hexBinary = null;
try
{
hexBinary = SoapHexBinary.Parse(strInput);
if (hexBinary != null)
{
bytArOutput = hexBinary.Value;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
return bytArOutput;
}
Step-01: Calculation Of CRC At Sender Side-A string of n 0's is appended to the data unit to be transmitted. Here, n is one less than the number of bits in CRC generator. Binary division is performed of the resultant string with the CRC generator. After division, the remainder so obtained is called as CRC.
The Cyclic Redundancy Check 16 is a hash function that produces a checksum that is used to detect errors in transmissions. The CRC16 calculation module is an iterative CRC calculator that can be used to cumulatively update a CRC checksum for every incoming byte.
Designing polynomials The most commonly used polynomial lengths are 9 bits (CRC-8), 17 bits (CRC-16), 33 bits (CRC-32), and 65 bits (CRC-64). A CRC is called an n-bit CRC when its check value is n-bits.
We now have what we need to compute CRC-16/MODBUS, which has both a non-zero Init value ( 0xffff ) and RefIn and RefOut as true. We start with the message with the bits in each byte reflected and the first 16 bits inverted. That is 7f f7 03 c0 00 80 . Divide by 0x18005 and you get the remainder 0xb393 .
Here we go; note that this is a specific flavor of CRC-16 - it is confusing to say just "CRC-16". This borrows some implementation specifics from http://www.sanity-free.com/ - note I have made it static
rather than instance-based.
using System;
static class Program
{
static void Main()
{
string input = "8000";
var bytes = HexToBytes(input);
string hex = Crc16.ComputeChecksum(bytes).ToString("x2");
Console.WriteLine(hex); //c061
}
static byte[] HexToBytes(string input)
{
byte[] result = new byte[input.Length / 2];
for(int i = 0; i < result.Length; i++)
{
result[i] = Convert.ToByte(input.Substring(2 * i, 2), 16);
}
return result;
}
public static class Crc16
{
const ushort polynomial = 0xA001;
static readonly ushort[] table = new ushort[256];
public static ushort ComputeChecksum(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;
}
static Crc16()
{
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;
}
}
}
}
In Addition, If you want CRC16-CCITT.
private ushort Crc16Ccitt(byte[] bytes)
{
const ushort poly = 4129;
ushort[] table = new ushort[256];
ushort initialValue = 0xffff;
ushort temp, a;
ushort crc = initialValue;
for (int i = 0; i < table.Length; ++i)
{
temp = 0;
a = (ushort)(i << 8);
for (int j = 0; j < 8; ++j)
{
if (((temp ^ a) & 0x8000) != 0)
temp = (ushort)((temp << 1) ^ poly);
else
temp <<= 1;
a <<= 1;
}
table[i] = temp;
}
for (int i = 0; i < bytes.Length; ++i)
{
crc = (ushort)((crc << 8) ^ table[((crc >> 8) ^ (0xff & bytes[i]))]);
}
return crc;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With