[C#] 비트교환
간만에 프로그래밍 관련 포스팅입니다.
몇년전에 처음 시리얼을 통한 통신 프로그램을 만들던중 사용한 방법이 있었습니다. 이걸 얼마전에 또 쓰게 되었네요. 당시엔 MODBUS 프로토콜이었지만 지금은 LS산전이랑 MELSEC 이란거만 다를뿐 여기서도 비트교환을 써야 하더라구요.
비트교환은 2바이트의 데이터를 교환하는 것으로, 이름은 그냥 생각나는데로 지었어요. (제목은 있어야 하니깐!)
ex) 정수 4576을 전송하기 위해 교환처리를 수행.
4576 = 11 E0 -> E0 11
위와 같은 식으로 바꿔줘야 합니다. 여러 방법이 있겠지만. 저는 비트연산을 이용했어요. 4576은 이진수로 나타내면 다음과 같습니다.
1 1 E 0 E 0 1 1
---- ---- ---- ---- ---- ---- ---- ----
0001 0001 1110 0000 to 1110 0000 0001 0001
뭐... 설명은 좀 복잡한거 같지만 결국 이겁니다...
int 원본 = 4576;
byte[] 저장 = new byte[2];
저장[0] = (byte)(원본) & 0xFF);
저장[1] = (byte)((원본 >> 8) & 0xFF);
byte 자체가 1바이트(8bit)만 저장할 수 있기에 첫번째 0xFF를 사용하면
0001 0001 1110 0000 11E0
AND 0000 0000 1111 1111 00FF
---------------------------------
0000 0000 1110 000000E0
이 되어 앞에 00은 자리수가 안맞아 잘리고 E0만 저장됩니다. (사실 0xFF 연산이 없어도 입력되긴 합니다만...)
두번째 줄을 보면 >> 쉬프트 연산자가 보입니다. 꺽쇠가 우측으로 되어 있으니 오른쪽으로 밀어내는거군용. 8이라는 숫자가 있으니 우측으로 8비트 밀으라는 겁니다.
0001 0001 1110 0000 <-- 우측 끝자리가 0번째 비트
>> 8
---------------------------------------
0000 0000 0001 00011110 0000
하지만 비트 크기는 16비트로 고정되어 있으니 0번째 비트를 넘어가는 데이터는 자동으로 버려집니다. 결과적으로 다음과 같은 값이 구해지죠.
0000 0000 0001 0001 0011
이걸 다시 and 연산합니다.
0000 0000 0001 0001 0011
AND 0000 0000 1111 1111 00FF
--------------------------------
0000 0000 0001 00010011
결국....
저장[0] 에는 E0 이 들어가고, 저장[1] 에는 11 이 들어가게 되죵. 위와 마찬가지로 자리수가 안맞아서 잘립니다.
추가1) 만약 n개의 바이트를 교환하는 경우 쉬프트 값을 8비트 단위로 늘리면 됩니다. (이하생략)
3바이트 : 16
4바이트 : 24
추가) 만약 위에 비트교환이 된 상태의 값을 정수로 저장하고 싶은 경우 OR 연산을 이용하면 됩니다.
int 정수값 = (int)((저장[0] << 8) | 저장[1]);
식으로 나타내자면.......
1110 0000 E0
<< 8
-------------------------------
1110 0000 0000 0000 E000
OR 0001 0001 11
-------------------------------
1110 0000 0001 0001 E011
몇년전에 처음 시리얼을 통한 통신 프로그램을 만들던중 사용한 방법이 있었습니다. 이걸 얼마전에 또 쓰게 되었네요. 당시엔 MODBUS 프로토콜이었지만 지금은 LS산전이랑 MELSEC 이란거만 다를뿐 여기서도 비트교환을 써야 하더라구요.
비트교환은 2바이트의 데이터를 교환하는 것으로, 이름은 그냥 생각나는데로 지었어요. (제목은 있어야 하니깐!)
ex) 정수 4576을 전송하기 위해 교환처리를 수행.
4576 = 11 E0 -> E0 11
위와 같은 식으로 바꿔줘야 합니다. 여러 방법이 있겠지만. 저는 비트연산을 이용했어요. 4576은 이진수로 나타내면 다음과 같습니다.
1 1 E 0 E 0 1 1
---- ---- ---- ---- ---- ---- ---- ----
0001 0001 1110 0000 to 1110 0000 0001 0001
뭐... 설명은 좀 복잡한거 같지만 결국 이겁니다...
int 원본 = 4576;
byte[] 저장 = new byte[2];
저장[0] = (byte)(원본) & 0xFF);
저장[1] = (byte)((원본 >> 8) & 0xFF);
byte 자체가 1바이트(8bit)만 저장할 수 있기에 첫번째 0xFF를 사용하면
0001 0001 1110 0000 11E0
AND 0000 0000 1111 1111 00FF
---------------------------------
0000 0000 1110 0000
이 되어 앞에 00은 자리수가 안맞아 잘리고 E0만 저장됩니다. (사실 0xFF 연산이 없어도 입력되긴 합니다만...)
두번째 줄을 보면 >> 쉬프트 연산자가 보입니다. 꺽쇠가 우측으로 되어 있으니 오른쪽으로 밀어내는거군용. 8이라는 숫자가 있으니 우측으로 8비트 밀으라는 겁니다.
0001 0001 1110 0000 <-- 우측 끝자리가 0번째 비트
>> 8
---------------------------------------
0000 0000 0001 0001
하지만 비트 크기는 16비트로 고정되어 있으니 0번째 비트를 넘어가는 데이터는 자동으로 버려집니다. 결과적으로 다음과 같은 값이 구해지죠.
0000 0000 0001 0001 0011
이걸 다시 and 연산합니다.
0000 0000 0001 0001 0011
AND 0000 0000 1111 1111 00FF
--------------------------------
0000 0000 0001 0001
결국....
저장[0] 에는 E0 이 들어가고, 저장[1] 에는 11 이 들어가게 되죵. 위와 마찬가지로 자리수가 안맞아서 잘립니다.
[ byte = 8bit 단위 인데, 저 값은 16비트 거든요. 하지만 항상 0번째 비트부터 저장하게 됩니다. ]
추가1) 만약 n개의 바이트를 교환하는 경우 쉬프트 값을 8비트 단위로 늘리면 됩니다. (이하생략)
3바이트 : 16
4바이트 : 24
추가) 만약 위에 비트교환이 된 상태의 값을 정수로 저장하고 싶은 경우 OR 연산을 이용하면 됩니다.
int 정수값 = (int)((저장[0] << 8) | 저장[1]);
식으로 나타내자면.......
1110 0000 E0
<< 8
-------------------------------
1110 0000 0000 0000 E000
OR 0001 0001 11
-------------------------------
1110 0000 0001 0001 E011
댓글
댓글 쓰기