Как использовать эту функцию CCITT-CRC16? - PullRequest
0 голосов
/ 02 апреля 2019

Более здесь , есть реализация CCITT-CRC16. Для тех, кто избегает ссылок, это написано на C так:

unsigned short crc16(data_p, length)
char *data_p;
unsigned short length;
{
       unsigned char i;
       unsigned int data;
       unsigned int crc;

       crc = 0xffff;

       if (length == 0)
              return (~crc);

       do {
              for (i = 0 data = (unsigned int)0xff & *data_p++;
                  i < 8;
                  i++, data >>= 1) {
                    if ((crc & 0x0001) ^ (data & 0x0001))
                           crc = (crc >> 1) ^ POLY;
                    else
                           crc >>= 1;
              }
       } while (--length);

       crc = ~crc;

       data = crc;
       crc = (crc << 8) | (data >> 8 & 0xFF);

       return (crc);
}

Но я не совсем понимаю, как это применимо к моему делу. Я перевожу с частного / неизвестного языка, который имеет встроенный CCITT CRC16. Он имеет функцию класса CRC следующим образом:

CRCname.put (int byte):

байт - целочисленное значение, используемое для обновления текущего CRC. Только используются младшие 8 битов параметра.

Мне нужны два поля в реализации CCITT-CRC16, которые я нашел, data_p и length, поэтому мой вопрос ... что подразумевается под целочисленным значением, используемым для обновления crc? Внутри кода, который я перевожу, программа довольно часто выполняет crc.put(someChar), затем изменяет someChar перед повторным вызовом crc.put(someChar) и делает это несколько раз. Допустим, я сохранил все эти someChars, один за другим, в массив с именем someChars.

Будет ли CRC, полученный из всех этих символов, вызываться через crc16(someChars, sizeof(someChars)/sizeOf(someChars[0])) ..?

Кроме того, должен ли я использовать тип uint8_t для моего массива?

У меня нет примеров, поэтому я прошу здесь убедиться, что это на 100% правильно.

Ответы [ 3 ]

3 голосов
/ 02 апреля 2019

Есть много альтернативных алгоритмов для вычисления этого CRC: некоторые используют таблицы поиска, некоторые используют битовые операции, некоторые переворачивают некоторые биты, некоторые переворачивают некоторые другие биты ...

Упомянутая вами функция CRCname.put(int byte), скорее всего, является обновлением вычисляемого CRC. То есть он вычисляет одну итерацию вашего внутреннего цикла do/while, используя переданный байт (фактически unsigned char вместо int) в качестве значения для вашей локальной переменной data.

В неизвестном типе CRCname, вероятно, есть переменная-член, в которой хранится ваша переменная crc, конструктор, который устанавливает для нее начальное значение, и int CRCname.getFinalCrcValue(), который выполняет окончательное вычисление.

В любом случае, если у вас нет примера для сравнения выходных данных, маловероятно, что вы все сделаете правильно. Слишком много вещей, которые могут пойти не так.

Что касается типа uint8_t, это не имеет большого значения, если только ваше значение CHAR_BITS не отличается от 8, и если это так, у вас есть большие проблемы!

0 голосов
/ 02 апреля 2019

байт - целочисленное значение, используемое для обновления текущего CRC.Используются только младшие 8 битов параметра.

CRC так не работает.Функция, подобная той, которую вы опубликовали, ожидает получения полного пакета данных.Существует два варианта использования такой функции:

  • Либо пакет содержит только данные, в этом случае функция рассчитает FCS (последовательность проверки кадра), которые должны быть сохранены в конце пакета..
  • Или пакет содержит данные + FCS, и в этом случае вы можете вызвать ту же самую функцию и получить логическое значение 0 в случае успеха или ненулевое в случае ошибок.

Вызов функции «обновить текущий CRC» не имеет никакого смысла, потому что функция не сохраняет предыдущую FCS, а начинает с пустых данных, все = 0xFFFF, как того требует CRC16-CCITT.Если вы хотите постоянно обновлять FCS, вам нужно будет сохранить его, а затем передавать его в функцию при каждом вызове.

Кроме того, сам алгоритм содержит ошибку, char не следует использовать для rawданные, так как он может быть подписан.На самом деле вы должны использовать uint8_t.

По какой-то причине этот код написан в устаревшем стиле K & R.Учитывая низкое качество этого кода ... будьте осторожны с множеством подлых и неправильных реализаций CRC16-CCITT, распространяющихся в интернете.Я много лет использовал гнилой, который очень похож на этот.Пока я не узнал, что на самом деле это был не CRC16-CCITT, а нестандартный.

Звучит так, как будто вам на самом деле нужна версия таблицы поиска, которая выполняет 16/8/4-битный поиск, в зависимости отна сколько ROM памяти вы можете себе позволить.

0 голосов
/ 02 апреля 2019

Будет ли CRC, полученный из всех этих символов, вызываться через crc16(someChars, sizeof(someChars)/sizeOf(someChars[0])) ..?

Если someChars - массив char, то, скорее всего, да (как только вы исправите код, sizeOfsizeof). Обратите внимание, что вам не нужно делить на sizeof(someChars[0]), поскольку размер char в C определен равным 1.

Кроме того, должен ли я использовать тип uint8_t для моего массива?

Функция, которую вы опубликовали, не поддерживает, поэтому нет смысла передавать ей буфер uint8_t. Тем не менее, определенно было бы лучше использовать массив uint8_t для необработанных байтов и соответствующим образом изменить функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...