Расчет CRC16 - перевод с C на JAVA

В настоящее время я пишу программу JAVA, которая должна отправлять данные в декодер MyLaps через сокет (протокол P3). Двоичные данные должны включать 2-байтовый код CRC. В документации MyLaps есть код на C для вычисления CRC. В нем также говорится, что WORD определен как беззнаковый 16-битный тип.

C-код

    WORD CRC16Table[256] ;
    
    // initialize the CRC16 table
    extern void InitCRC16( void ) {
      WORD i, j ;
      WORD crc ;
      for ( i = 0 ; i < 256 ; i += 1 ) {
        for ( crc = i << 8, j = 0 ; j < 8 ; j += 1 )
          crc = ( crc << 1 ) ^ ( ( crc & 0x8000 ) ? 0x1021 : 0 ) ;
        CRC16Table[ i ] = crc ;
      }
    } 

    // calculate the crc of a char array pointed at by p
    extern WORD CalcCRC16( unsigned char * p, WORD size ) {
      WORD crc = 0xFFFF ;
      WORD i ;
      for ( i = 0 ; i < size ; i++, p++ ) // for all chars
        crc = CRC16Table[ ( ( crc >> 8 ) & 255 ) ] ^ ( crc << 8 ) ^ *p ;
      return crc ;
    }

Я хотел преобразовать этот C-код в код Java. Поскольку java не знает 2-байтового числа без знака, я использовал тип данных char, который также является 2-байтовым.

JAVA-код

    // initialize the CRC16 table
    public static char[] InitCRC16() {
      char i, j;
      char crc;
      char[] CRC16Table = new char[256];
    
      for (i = 0; i < 256; i++) {
        crc = (char) (i << 8);
        for (j = 0; j < 8; j++) {
          crc = (char) ((crc << 1) ^ (((crc & 0x8000) != 0) ? 0x1021 : 0));
        }
        CRC16Table[i] = crc;
      }
      return CRC16Table;
    }
    
    // calculate the crc of a char array        
    public static char CalcCRC16(byte[] p, char[] CRC16Table) {
      char CRC;
      CRC = 0xFFFF;
      for (int ptr = 0; ptr < p.length; ptr++) {
        CRC = (char) (CRC16Table[(( (char) CRC >> 8) & 0xFF)] ^ ((char) CRC << 8) ^ p[ptr]);
      }
      return (char) CRC;
    }

Отправляя данные в декодер MyLaps, я всегда получаю ошибку CRC, поэтому должна быть ошибка при преобразовании кода из C в JAVA.

Кто-нибудь может помочь?

Java знает беззнаковый 16-битный числовой тип. К счастью для вас, это char, который вы выбрали для этой цели.

John Bollinger 22.02.2023 18:38

«Отправляя данные в декодер MyLaps, я всегда получаю ошибку CRC» — вы можете начать с меньшего, сравнив таблицы CRC после инициализации. Они одинаковы?

Ted Lyngmo 22.02.2023 18:42

это отвечает на ваш вопрос?

Elliott Frisch 22.02.2023 18:48

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

Old Dog Programmer 22.02.2023 19:07
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В версии для Java происходит много ненужного приведения, что иронично, поскольку проблема, по-видимому, в одном из мест, где вы неправильно адаптируете задействованные преобразования типов.

Учитывая задействованные типы данных, этот код C...

        crc = CRC16Table[ ( ( crc >> 8 ) & 255 ) ] ^ ( crc << 8 ) ^ *p ;

... не эквивалентен этому коду Java...

        CRC = (char) (CRC16Table[(( (char) CRC >> 8) & 0xFF)] ^ ((char) CRC << 8) ^ p[ptr]);

. Вам не нужно большинство этих (char) приведений, но *p в версии C, C unsigned char, не эквивалентен p[ptr] в версии Java, Java byte (который подписан). И в C, и в Java есть автоматическое повышение до int для арифметических операндов. В C это всегда будет расширять *p начальными нулевыми битами, но в Java это будет расширять p[ptr] начальными 1 битами, когда его значение отрицательно. Некоторые из этих битов находятся в той части числа, которая будет влиять на результат даже при логических операциях & (которые не позволяют усечь результат, чтобы он соответствовал char).

Вы, кажется, хотите этого:

        CRC = (char) (CRC16Table[(CRC >> 8) & 0xFF] ^ (CRC << 8) ^ (p[ptr] & 0xFF));

Привет Джон, ты мой герой, это было проблемой. Большое спасибо! Пришлось сделать одну небольшую корректировку, вычисление CRC выдало синтаксическую ошибку, пришлось изменить на CRC = (char) (CRC16Table[(CRC >> 8) & 0xFF] ^ (CRC << 8) ^ (p[ptr] & 0xFF)); Oliver

Oliver 22.02.2023 19:36

Я рад, что это помогло, @Oliver, и я отредактировал этот ответ, чтобы устранить описанную вами ошибку.

John Bollinger 22.02.2023 19:39

Другие вопросы по теме