I have string: 02 03 04 50 00 01
. I need to calculate the CRC for this string.
I have a function that counts a CRC:
public static UInt16 ModRTU_CRC(ushort[] buf, int len)
{
UInt16 crc = 0xFFFF;
for (int pos = 0; pos < len; pos++)
{
crc ^= (UInt16)buf[pos];
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
crc >>= 1;
}
}
return crc;
}
I want to cast a string to an array of ushort:
ushort[] result = cmd.Split(' ').Select(item => Convert.ToUInt16(item, 16)).ToArray();
but such an array is returned to me: 2 3 4 80 0 1
.
Please tell me what should I do in order to correctly calculate the CRC.
It seems, you want to combine two byte
s into ushort
, i.e. for given
string cmd = "02 03 04 50 00 01";
you want to get
{0x0203, 0x0405, 0x0001}
If it's you case,
using System.Linq;
...
string cmd = "02 03 04 50 00 01";
ushort[] result = cmd
.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select((value, index) => new { index, value = Convert.ToInt32(value, 16) })
.GroupBy(item => item.index / 2, item => item.value)
.Select(group => (UInt16)(group.Aggregate((s, a) => s * 256 + a)))
.ToArray();
Let's have a look:
Console.WriteLine(string.Join(" ", data.Select(item => item.ToString("x4"))));
Outcome:
0203 0450 0001
Edit: If you want not to combine first skip
items (see comments below), you can try modifying GroupBy
:
int skip = 2;
ushort[] data = source
.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select((value, index) => new { index, value = Convert.ToInt32(value, 16) })
.GroupBy(item => item.index >= skip ? item.index / 2 : -item.index - 1,
item => item.value)
.Select(group => (UInt16)(group.Aggregate((s, a) => s * 256 + a)))
.ToArray();
Console.WriteLine(string.Join(" ", data.Select(item => item.ToString("x4"))));
Outcome: (02
and 03
left intact, 04
combined with 50
, 00
with 01
)
0002 0003 0450 0001