사용자 도구

사이트 도구

English

cublocapp:an61007:index

AN61007 - 모아콘 실수 처리방법

모아콘의 실수형 (float)를 HMI에 표시하는 방법에 대해서 알아보겠습니다.

#include "moacon500.h"
void cmain(void)
{
 static u8 MDcoil[100];
 static float MDregister[100];           // <----------- u16 대신 float 로 바꿈
 openCom(0,115200, C8N1);                // RS232C 채널0을 115200으로 오픈
 startModbusRtu(0,1,MDregister, MDcoil); // MODBUS RTU의 시작, 슬레이브 어드레스는 1
 
 delay(100);
 for(;;) {
 MDregister[0]= MDregister[0] + 0.1;     // <------------- 이제 배열은 실수배열이다.
 delay(100);
                   // 무한루프
  }
}

방법은 의외로 간단합니다. 모아콘에서 선언하는 중계영역을 float형으로 바꾸면 됩니다. 그러면 배열은 float 변수처럼 사용가능합니다.

숫자 위젯을 화면에 올린뒤, 위젯을 더블클릭하시면, 아래와 같은 박스가 나옵니다.

여기에서 주소입력 아이콘을 클릭하세요.

원격 데이터 형식을 <float (32비트 실수)>로 바꾸세요.

소수 자리수도 표시하는걸로 하세요. 실행시키면 아래처럼 실수가 화면에 표시됩니다.


조금 다른 상황을 생각해 보겠습니다. 위의 예는 MDregister 전부를 실수로 사용하는 경우입니다.

그런데, MDregister를 그냥 16비트 정수로 사용하고, 그중 일부분만 실수를 옮겨서 전달하는 상황이 필요할 수도 있다는 생각이 들었습니다.

즉, 대부분의 데이터는 정수로 주고 받는데, 특정값 몇개만 실수데이터를 주고 받을 필요가 있을 경우입니다.

#include "moacon500.h"
static u8 MDcoil[100];
static u16 MDregister[100];
 
void cmain(void)
{
 float a1;
 openCom(0,115200, C8N1);                // RS232C 채널0을 115200으로 오픈
 startModbusRtu(0,1,MDregister, MDcoil); // MODBUS RTU의 시작, 슬레이브 어드레스는 1
 
 delay(100);
 for(;;) {
 a1 = a1 + 0.1;
 MDregister[0] = MDregister[0] + 1;
 MDregister[1] = *((u16 *)(&a1));      // <-- a1 의 하위16비트를 MDregister[1] 에 저장
 MDregister[2] = *((u32 *)(&a1))>>16;  // <-- a1 의 상위16비트를 MDregister[2] 에 저장
 delay(100);
                   // 무한루프
  }
}

이 경우에는 그냥 u16 으로 MDregister를 선언하세요. 그리고 실수형으로 선언한 a1 변수를 가지고 필요한 연산을 하십시오.

a1 변수는 32비트 정보를 가지고 있습니다. 물론 실수형 포맷으로 저장하고 있습니다. 이것을 MDregister 배열 안에 집어넣으면, HMI가 알아서 가져갈 것입니다.

실수형과 정수형은 type이 일치하지 않아서

MDregister[1] = a1; 

이런식으로 바로 넣을 수 없습니다.

그래서

MDregister[1] = *((u16 *)(&a1));      // <-- a1 의 하위16비트를 MDregister[1] 에 저장
MDregister[2] = *((u32 *)(&a1))>>16;  // <-- a1 의 상위16비트를 MDregister[2] 에 저장

이런식으로 포인터를 사용해서 넣었습니다.

a1의 하위 16비트는 MDregister[1]에 들어가고, a1의 상위 16비트는 MDregister[2]에 들어갑니다.

그러면 HMI에서는 30002번지에서 32비트 실수형으로 데이터를 읽어와서 표시하면 됩니다.

moacon_simple.zip


거꾸로 MDregister에 들어있는 값을 float형 변수로 가져오는 방법도 생각해 보았습니다.

#include "moacon500.h"
static u8 MDcoil[100];
static u16 MDregister[100];
 
void cmain(void)
{
 float a1,b1;
 u32 bf1;
 openCom(0,115200, C8N1);                // RS232C 채널0을 115200으로 오픈
 startModbusRtu(0,1,MDregister, MDcoil); // MODBUS RTU의 시작, 슬레이브 어드레스는 1
 
 delay(100);
 for(;;) {
 a1 = a1 + 0.1;
 MDregister[0] = MDregister[0] + 1;
 MDregister[1] = *((u16 *)(&a1));      // <-- a1 의 하위16비트를 MDregister[1] 에 저장
 MDregister[2] = *((u32 *)(&a1))>>16;  // <-- a1 의 상위16비트를 MDregister[2] 에 저장
 
 // MDregister에 있는 실수값을 float변수로 가져가기
 bf1 = MDregister[2] * 65536 + MDregister[1];
 b1 = *((float *)(&bf1));
 printf ("%x %f\r\n",bf1, b1);
 delay(500);
                   // 무한루프
  }
}

bf1 이라는 32비트 형 변수를 매개체로 해서, MDregister의 값을 이동시킨뒤, 실수형으로 변환한 것입니다.

bf1 = MDregister[2] * 65536 + MDregister[1];

일단 이 문장은 MDregister 2군데에 나누어져 있는 32비트형 데이터를 하나의 수로 만들어 변수 bf1에 저장합니다.

이제 변수 bf1에 있는 값은 정수처럼 보이는 실수형 포맷의 숫자입니다. 이것을 원형 그대로 float형 변수에 전달해주어야 실수형으로 인식됩니다.

 b1 = *((float *)(&bf1));

이렇게 하면, bf1에 들어있는 값이 원형 그대로 b1 이라는 float변수로 전달됩니다.

한단계 뒤로

cublocapp/an61007/index.txt · 마지막으로 수정됨: 2023/10/25 04:06 저자 Comfile Technology