MODBUS RTU 에서 FLOAT(부동소수점) 처리 방법
MODBUS-RTU 에서 FLOAT 데이터를 처리하는 예를 설명하겠습니다. – acusys 기술팀.
상기 그림에서 TX 에 의해 상대 디바이스에 TX 를 통해 요청하여 수신한 RX 데이터는 2 바이트로 수신되는 예제이고, 이때 HEX 로 수신된 데이터는 0B 95 41 CB 가 된다. 이 데이터를 FLOAT 으로 변환하는 예를 알아본다. 앞의 02 는 슬래이브 아이디이고, 03 은 기능코드, 04는 응답하는 데이터 길이, 데이터(0B 95 41 CB)뒤에 AA FC 는 Checksum 이다.
자, 이 데이터를 FLOAT 형으로 어떻게 변환하는지 알아보자.
이 데이터의 포멧은 CD AB 로 데이터가 수신되는 방식이고, 리틀 엔디안 방식이라고 부른다. 보통 숫자의 낮은 차수 바이트는 메모리의 가장 낮은 주소에 저장되고 높은 차수 바이트는 가장 높은 주소에 저장되는 형태로서,
4바이트 기준으로 아래와 같이 저장된다. 이 데이터 방식은 제조사마다 다르며 반드시 제조사에서 제공한 MODBUS 테스트 툴이나 메뉴얼을 사전에 확인하여 올바른 데이터 수신시 출력되어야 할 값을 예측하거나 미리 확인하여 비교하기 바란다.
어째뜬 현재 설명하는 예제는 CD AB 형태로 저장되는 형태, 즉 이 장치의 제조사에서 정한 데이터 순서가 그렇단 이야기다. 글을 읽는 독자의 장치의 데이터 저장 방식을 확인하고, 위에 설명한 FLOAT CD AB 형태의 장치에서 저장하여 MODBUS-RTU 로 전송되는 바이트의 순서는 리틀 엔디안이라고 설명했으며 아래와 같은 순서로 데이터가 우리에게 도착한다.
- 바이트3, 바이트 2, 바이트1, 바이트 0
이 데이터의 각 바이트는 4 비트(니블) 2개가 합쳐진, 1바이트(8비트) 데이터이다. 1 바이트에 8비트이므로 그렇다.
수신된 변수 이름을 정해보겠다. 예를 들어 ‘szRecvProtocol’ 이 변수 이름인데, 상기 그림과 같이 MODBUS RTU 로 수신(RX)된 통신 데이터가 저장되어 있다고 가정한다면,
전체 배열의 데이터 상태는 아래와 같다.
szRecvProtocol[0] = 0x02 // 슬래이브 아이디
szRecvProtocol[1] = 0x03 // 기능 코드
szRecvProtocol[2] = 0x04 // 데이터 길이. 8비트 데이터가 4개이므로 이러하다.
szRecvProtocol[3] = 0x0B // 응답 데이터 #1
szRecvProtocol[4] = 0x95 // 응답 데이터 #2
szRecvProtocol[5] = 0x41 // 응답 데이터 #3
szRecvProtocol[6] = 0xCB // 응답 데이터 #4
szRecvProtocol[7] = 0xAA // 체크섬 – 주) 체크섬에 대해서는 나중에 시간이 되면 다루도록 하겠음.
szRecvProtocol[8] = 0xFC // 체크섬
위와 같이 저장되어 있다. 이 데이터를 FLOAT 형으로 변경하기 위해서 먼저 임시 변수에 저장해 보자. 저장하면서 바이트 배열의 순서를 [CD AB] 로 변경하는 것을 유의하기 바란다.
unsigned char _temp_b[4] = { 0, };
// FLOAT [CD AB] format
_temp_b[0] = szRecvProtocol[4]; // B
_temp_b[1] = szRecvProtocol[3]; // A
_temp_b[2] = szRecvProtocol[6]; // D
_temp_b[3] = szRecvProtocol[5]; // C
위 _temp_b 변수는 4개의 바이트 배열이다.
이 바이트 배열을 32비트 단정밀도형(FLOAT) 으로 변환하기 위해서는 8비트씩 왼쪽으로 쉬프트하면서 이를 32비트 변수에 저장해야 함.
for ( int i = 0; i < 4 ; i++)
{
dwBuffer = (_temp_b[i] << (i * 8));
dwWord |= dwBuffer;
}
이후 FLOAT 형의 변수에 memcpy 를 한다.
float _temp_f = 0.0f;
memcpy(&_temp_f,(void*)&dwWord,sizeof(char) * 4);
정리하면, MODBUS RTU 로 수신한 FLOAT 변수 데이터는 HEX 형이므로 이에 대한 바이트 순서를 확인하여 변경하고,
이후 8비트씩 왼쪽으로 쉬프트 시켜서 이를 이전 비트연산된 데이터와 OR 연산하여 32비트 형으로 적재한 후 미리 준비된 FLOAT 변수에 저장하여, 변환을 완료한다.
*이와 같은 작업을 할때 MODBUS 테스트 툴을 함께 사용하면 비교 테스트 및 구현하기가 용이하다.
<기타 타 블로그 참고 자료>
출처 : https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=songyn73&logNo=150024043837