Calculate 16 bit CRC in java and append it at the end of the byte array

自闭症网瘾萝莉.ら 提交于 2019-12-24 00:44:56

问题


I have the following buffer

byte pingBuff[] ={0x01, 0x01,0x00,0x01,0x00,0x20}

I need to calculate 16 bit CRC of these 6 bytes and append it at the end of the

pingBuff[]

I have done it using C++ and tried to change that code in java like below but it didnot work.

    package org.totalbeginner.tutorial;

    public class CRCLikeC
    {
      /* Table of CRC values for high–order byte */
      char auchCRCHi[] = {
      0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
      0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
      0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
      0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
      0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
      0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
      0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
      0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
      0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
      0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
      0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
      0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
      0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
      0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
      0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
      0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
      0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
      0x40
      } ;

      /* Table of CRC values for low–order byte */
      char auchCRCLo[] = {
      0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
      0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
      0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
      0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
      0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
      0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
      0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
      0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
      0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
      0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
      0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
      0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
      0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
      0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
      0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
      0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
      0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
      0x40
      } ;

      int CRC16(char puchMsg, int usDataLen)
      {
         char uchCRCHi = 0xFF ; /* high byte of CRC initialized */
         char uchCRCLo = 0xFF ; /* low byte of CRC initialized */
         int uIndex ; /* will index into CRC lookup table */

         while (usDataLen--) /* pass through message buffer */
         {
          uIndex = uchCRCHi ^ puchMsg++ ; /* calculate the CRC */
          uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
          uchCRCLo = auchCRCLo[uIndex] ;
         }

        return (uchCRCHi << 8 | uchCRCLo) ;
        }

    }

in the line

while (usDataLen--)

the error seen is "cannot convert from int to boolean"

and in the line

uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;

the error seen is "cannot convert from int to char"

Actually the code in the c used unsigned char , i converted them to char . and i converted unsinged short to int in this java implementation.

Please suggest how can i improve this method of crc calculation . Or is there any other way of calculating crc from hex bytes . I have searched other method but it didnot work for the hex bytes in pingBuff[].


回答1:


Regarding the first issue: in c (or c++ for that matter), an int of 0 is evaluated as false, and any other value is evaluated to true. Java does not perform these implicit casts, so you need to manually check your int is larger than 0 (see "correction 1" in the code below).

Regarding the second issue: in Java, the ^ operator is defined only between ints. So when you perform in on two chars, they are both promoted to ints and only then XORed. The result is, of course, an int, which cannot be assigned to a char - you must explicitly cast it back down to a char. Note that since the MSBs of both ints are known to be zeros (as they were promoted from chars), this is perfectly safe, and does not risk any data loss.

  int CRC16(char puchMsg, int usDataLen)
  {
     char uchCRCHi = 0xFF ; /* high byte of CRC initialized */
     char uchCRCLo = 0xFF ; /* low byte of CRC initialized */
     int uIndex ; /* will index into CRC lookup table */

     // Correction 1: compare the int to 0
     while (usDataLen-- > 0) /* pass through message buffer */
     {
      uIndex = uchCRCHi ^ puchMsg++ ; /* calculate the CRC */
      uchCRCHi = (char) (uchCRCLo ^ auchCRCHi[uIndex]); // Correction 2: explicit ca
      uchCRCLo = auchCRCLo[uIndex] ;
     }

    return (uchCRCHi << 8 | uchCRCLo) ;
    }



回答2:


Unlike C, the condition in a java while() statement must be a boolean, so change it to while(usDataLen-- > 0).

For the second one, it should be uchCRCHi = (char) (uchCRCLo ^ auchCRCHi[uIndex]); You can see this discussion.




回答3:


public int calcCRC(byte[] bitPlane) {

            crc = 0;

            for (int i = 0; i < bitPlane.length; i++) {
                byte element = bitPlane[i];
                crc ^= (element << 8);
                for (int j = 0; j < 8; j++) {
                    boolean carry = ((crc & 0x8000) != 0);
                    crc <<= 1;
                    if (carry) {
                        crc ^= 0x1021;
                    }
                }

            }


            return crc;

        }



回答4:


I know this is very old but if someone around still need this I made a version for Java that worked for me. It receives and returns a String, so you can convert your data to String and use it as it is or take it as a clue to make the a version that works with bytes (I think it's very straightforward).

Hope it helps!

I'ts here

Edit:

You can use like this: Let's say that you have some data and you need its crc. You first convert it to string and then use the process() function like this:

String crc = CRCITU.process(data);
// for example
CRCITU.process("0d0103588990501766460026"); // will return "7bf9"

Then in your case you convert it back to bytes and append it to the end of the original data.

If you have any problem post an issue in the GitHub repository and I'll try to help you.



来源:https://stackoverflow.com/questions/20878300/calculate-16-bit-crc-in-java-and-append-it-at-the-end-of-the-byte-array

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!