рассчитать CR C для Modbus RTU из строк - PullRequest
2 голосов
/ 11 марта 2020

У меня есть строка: 02 03 04 50 00 01. Мне нужно вычислить CR C для этой строки.

У меня есть функция, которая считает CR C:

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;
        }

Я хочу привести строку к массиву ushort:

ushort[] result = cmd.Split(' ').Select(item => Convert.ToUInt16(item, 16)).ToArray();

но мне возвращается такой массив: 2 3 4 80 0 1.

Скажите, пожалуйста, что мне делать, чтобы правильно рассчитать CR C.

1 Ответ

4 голосов
/ 11 марта 2020

Кажется, вы хотите объединить два byte с в ushort, т.е. для данного

  string cmd = "02 03 04 50 00 01";

вы хотите получить

  {0x0203, 0x0405, 0x0001}

Если это ваш случай,

  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();

Давайте посмотрим:

  Console.WriteLine(string.Join(" ", data.Select(item => item.ToString("x4"))));

Результат:

  0203 0450 0001

Редактировать: Если вы хотите не объединять первые skip элементы (см. комментарии ниже), вы можете попробовать изменить 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"))));

Результат: (02 и 03 осталось без изменений, 04 в сочетании с 50, 00 с 01)

  0002 0003 0450 0001
...