CRC 16计算-从C转换为JAVA

edqdpe6u  于 2023-03-01  发布在  Java
关注(0)|答案(1)|浏览(174)

我目前正在编写一个JAVA程序,它必须通过套接字(P3协议)将数据发送到MyLaps解码器。二进制数据必须包括一个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的代码转换中有错误。
有人能帮忙吗?

mnemlml8

mnemlml81#

在Java版本中有很多不必要的强制转换,这很讽刺,因为问题似乎出在您 * 没有 * 正确地适应所涉及的类型转换的地方之一。
考虑到所涉及的数据类型,这个C代码...

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

......不等同于此Java代码......

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

。您不需要这些(char)类型转换中的大多数类型转换,但是C版本中的*p(即C unsigned char)与Java版本中的p[ptr](即Java byte)并不等效(有符号)。在C和Java中,算术操作数都自动提升为int。在C中,*p总是以0为前导,但在Java中当p[ptr]的值为负时,它将以前导1位扩展p[ptr]。其中一些位位于即使使用逻辑&操作也会影响结果的数字部分(模拟结果的截断以适合char)。
你似乎想要这个:

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

相关问题