Расчет CRC16 для MODBUS RTU

Я пытаюсь подключиться к счетчику промышленного типа с помощью Modbus. Мне нужно вычислить значение CRC16 как два байта для его отправки. Ранее я искал в Google несколько библиотек Arduino и получил ту же функцию, что и ниже. Но я не мог хорошо понять эту функцию.

Мне нужно CRC в виде двух байтов, а в качестве входных данных у меня есть 6 байт.

Может ли кто-нибудь объяснить приведенную ниже функцию и какой аргумент мне нужно предоставить?

uint16_t crc16_update(uint16_t crc, uint8_t a)
  {
    int i;
    crc ^= a;
    for (i = 0; i < 8; ++i)
  {
    if (crc & 1)crc = (crc >> 1) ^ 0xA001;
    else crc = (crc >> 1);
  }
    return crc;
 }

, 👍0

Обсуждение

Я думаю, вам нужно вызывать функцию для каждого байта даты. Первым аргументом будет CRC, возвращенный предыдущим вызовом. Второй аргумент, если это байт данных. Прежде чем вызывать его, вам необходимо установить CRC в 0xFFFF (первый аргумент)., @Gerben

Фу. Вызов функции для каждого байта кажется неэффективным. Я бы предложил переписать это для работы с байтовым буфером., @Duncan C

Компилятор встроит его за вас. Просто укажите флаг оптимизатора., @Kwasmich


1 ответ


1

CRC-16 — это просто термин, описывающий алгоритм. Возможны несколько реализаций. Они отличаются не только используемым полиномом, но и начальным значением.

В вашей конкретной реализации используется полином IBM CRC-16.

Другие возможные полиномы, например:
x^16 + x^15 + x^2 + 1 (IBM)
x^16 + x^12 + x^5 + 1 (CCITT)
x^16 + x^10 + x^8 + x^7 + x^3 + 1 (DECT)
(есть больше в википедии)

На самом деле вы можете взять любой примитивный многочлен. (ОБНОВЛЕНИЕ: отказ от использования примитивного многочлена уменьшит выходное пространство, но все равно будет работать.) Поэтому вам придется выяснить, какой из них у вас есть. использовать, а затем узнать начальное значение.

Предположим, что вы правы с полиномом IBM, а затем предположим, что начальное значение — 0xffff. Вы используете эту функцию следующим образом:

uint16_t crc = 0xffff; // начальное значение
uint8_t a[]; // ваши данные
crc = crc16_update(crc, a[0]);
crc = crc16_update(crc, a[1]);
…
crc = crc16_update(crc, a[n]);
// сделанный
// crc теперь содержит значение данных, хранящихся в
,

Спасибо @Kwasmich. Моему счетчику Modbus нужен массив байтов, содержащий 6 байтов данных и 2 байта CRC. Общая длина массива равна 8. Я попытался получить 2 байта CRC, используя приведенный ниже массив данных. 0x01, 0x04, 0x03, 0xF4, 0x00, 0x01 это должно быть 0x70, 0x7C но у меня есть 0x2E и 0x2B, @user119o

Это означает, что ваше начальное значение и/или полином не соответствует вашим потребностям., @Kwasmich

Эта функция работает правильно. Он такой же, как и предыдущий, и я изменил его под свои требования (массив из 6 элементов). https://gist.github.com/Nsk1107/c0875a55a5d30e00313d6de0930976bf Источник: http://forum.arduino.cc/index.php?topic=421615.0. Я не могу понять, почему это работает :/ :D, @user119o