본문 바로가기
안드로이드

[Android] 자바에서 Unsigned 타입 적용하기

by 코딩히어로 2022. 10. 13.
728x90

title


대부분 비트단위로 정보를 주고받는 임베디드 시스템과 안드로이드를 연계할 때

unsigned형으로 인한 문제가 많이 발생하게 됩니다

예를 들어 비트단위에서는 바이너리 형태로 데이터를 구성하게 되는데

만약 1byte의 마지막번째를 사용하는 데이터라고 한다면

1000 0000 와같이 구성이 되는데 바로 자바에서는 이 부분이 문제가 됩니다

 

1000 0000은 dec값으로 128이지만 1byte의 부호 있는 타입에서는

해당 자리는 -를 표현하는 부호비트가 됩니다

즉 임베디드 시스템에서 넘어온 해당 값은 128을 넘기려 했겠지만 자바에서는

부호 없는 타입인 unsigned를 지원하지 않기 때문에 128이라는 값으로 인식할 수 없습니다

 

이럴 경우 몇 바이트의 데이터를 수신해서 CRC체크 등의 계산을 할 때

보낸 쪽(임베디드 unsigned형)과 받는 쪽(자바 signed형)의 CRC가 틀어지게 되어

결국 받은 데이터를 오류라고 판단합니다

하지만 실제로는 보낸데이터와 받는 데이터는 동일하다는 게 팩트이므로

오류 검출에서 틀렸을 뿐 정상 데이터를 버리는 꼴이 됩니다

 

제 경우에도 다음과 같은 CRC 함수를 동일하게 사용했습니다

public int GetCRC(String Check_data){
    byte[] data = new byte[Check_data.length()/2];
    data = hexStringToByteArray(Check_data);

    int crc = 0, crc_idx;
    for(int i=0;i<data.length;i++){
        crc_idx = ((crc >> 8) & 0x00ff) ^data[i];
        crc = ((crc<<8)&0xff00)^crc_table[crc_idx];
        Log.i("디버깅","CRC = "+crc);
    }
    return crc;
}

임베디드 쪽과 자바 쪽 동일하게 사용했는데 항상 CRC결괏값이 다르게 판단되어

데이터를 버리게 되다보니 정상적인 통신 자체가 불가능했습니다

여러 가지 방면으로 찾아본 결과 자바에서는 아주 간단하게 unsigned타입으로 볼 수 있는 방법이 있었습니다

 

바로 제가받은 byte에 0x00 값을 and bit 처리해주기만 하면 부호 없는 타입으로 변환이 가능합니다

즉 위 코드에서 crc_idx = ((crc >> 8) & 0x00ff) ^ data[i]; 부분을

crc_idx = ((crc >> 8) & 0x00ff) ^ (data [i]&0xff);

해서 처리해주기만 하면 부호 없는 타입으로 계산이 되어 정상적으로 처리가 되는것을 확인 할 수 있습니다

public int GetCRC(String Check_data){
    byte[] data = new byte[Check_data.length()/2];
    data = hexStringToByteArray(Check_data);

    int crc = 0, crc_idx;
    for(int i=0;i<data.length;i++){
        crc_idx = ((crc >> 8) & 0x00ff) ^ (data[i] & 0xff);
        crc = ((crc<<8)&0xff00)^crc_table[crc_idx];
        Log.i("디버깅","CRC = "+crc);
    }
    return crc;
}

자바에서는 해당 문제가 예전부터 많이 거론되고 있는데

부호없는 타입을 대처할 수 있는 방법은 여러 가지가 있겠지만 제가 사용해본 것 중에

0xff를 and 시키기만 하면 되기 때문에 해당 방식이 너무나도 간편한 것 같습니다

728x90
반응형

댓글