2012-11-23 9 views
3

펌웨어 업데이트를 위해 CRC16 체크섬을 만들어야합니다. I이 데이터를 전송하면 상기 제어기부호없는 int없이 CRC16 함수를 C에서 JAVA로 변환 할 때의 문제

-17514

에서

020000810000120000000002F001128100000C9462050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C94

I는 다음 얻을 CRC16를 (바이트 []로 헥스 문자열로부터 변환) 지금 자바에서 이것을 확인하려고 노력하지만, 나는 동일한 가치를 얻지 못한다.

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


static uint16_t crc16(const uint8_t *b, size_t l) 
{ 
    uint16_t crc = 0; 
    while (l-- > 0) 
    crc = crc16_update(crc, *b++); 
    return crc; 
} 

이 자바에서 내 변환 된 기능은 다음과 같습니다 :

는 C에서 원래의 함수입니다

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

public static int crc16(byte[] bytes) { 
    int crc = 0; 
    for (byte b:bytes) { 
     crc = crc16_update(crc, b); 
    } 
    return crc; 
} 

...하지만 그것은 작동하지 않습니다. 그게 뭐가 잘못 됐어?

+2

일곱 번째 줄을보십시오. 원본 : '(crc >> 1)'귀하의 코드 : '(crc << 1). 그러나 문제를 해결했는지는 모르겠지만 ... – looper

+1

부호없는 결과를 계산하는 루틴에서 음수 -17514를 얻는 것이 조금 이상한 것이 아닌가? 혹시 당신의 자바 루틴이 대신 '48022'를 반환합니까? – dasblinkenlight

+0

괜찮습니다. 나는 그것을 chagned했습니다. –

답변

0

올바른 방법을 찾았습니다. 이제 효과가 있습니다! 나는 문제가 인터와 짧은 사이의 인턴이었다고 생각한다.

public static int crc16_update(int crc, byte a) { 
    crc ^= ((a+128) & 0xff); 
    for (int i = 0; i < 8; ++i) { 
     if ((crc & 1) != 0) { 
      crc = ((crc >>> 1)^0xA001) & 0xffff; 
     } 
     else { 
      crc = (crc >>> 1) & 0xffff; 
     } 
    } 
    return crc; 
} 

public static short crc16(byte[] bytes) { 
    int crc = 0; 
    for (byte b : bytes) { 
     crc = crc16_update(crc, b); 
    } 
    return (short) crc; 
} 
0

>>> 연산자를 사용해보세요.

자바에서는 부호없는 시프트 연산자이며 부호가 그대로 유지되는 >>과 반대입니다.

또한 short과 마찬가지로 uint16_t은 16 비트 유형입니다. 비트 수준에서 작동하는 알고리즘을 다시 작성할 때 적절한 비트 길이를 사용해보십시오.

0

당신은 문제가되지 않습니다 정수가 서명 된 자바 있지만 잘못된 데이터 형식을 사용합니다. int에는 32 비트가 있으며 사용하는 알고리즘은 유형의 데이터 크기에 민감합니다. 16 비트에는 short을, 8 비트에는 byte을 사용하십시오.

@ Anony-Mousse에서 언급 한대로 필요한 경우 >>>도 사용하십시오.

+0

나는 그것을 변경했지만 작동하지 않습니다. 아니, 내가 14646을 얻는다. 02000081000000000000000002F001128100000C9462050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C9481050C94 –

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

mentioned by looper, 당신은 C 코드에서 거기 >> 1 있습니다. 다른 기능 이제

 } 
    } 
    return crc; 
} 

:

public static int crc16(byte[] bytes) { 
    int crc = 0; 
    for (byte b:bytes) { 
     crc = crc16_update(crc, b); 

crc16_update 자바에서 두 번째 인수로 int 소요 바이트 b가 가장 중요한/부호 비트가 설정되어 C.에서 uint8_t 값 는 음수이므로 으로 변환하면 crc16_update으로 부호가 확장되므로 C에없는 1 비트가 많이 생성됩니다.

모든 비트를 마스크해야하지만 최하위 비트는 8입니다.

crc16_update(crc, ((int)b) & 0xFF); 
관련 문제