|
저도 이게 오래된 프로그램이고 처음으로 제어했던 PLC라 소스가 좀 지저분 합니다.
지금보면 정말 한심한 소스인데 전체 소스는 회사 규정상 보내 드릴 수 없고
전송 부분과 수신 부분의 일부만 소스를 올렸습니다.
#define ENQ 0x05
#define ACK 0x06
#define NAK 0x15
#define EOT 0x04
#define ETX 0x03
void TMain::Input_Send(void) // I/O 포트에 대한 값을 읽어들이기 위한 함수
{
byte ch[25] ;
ch[0]=ENQ; ch[1]=0x30; ch[2]=0x30; ch[3]='R'; ch[4]='S';
ch[5]='S'; ch[6]=0x30; ch[7]=0x32; ch[8]=0x30; ch[9]=0x35;
ch[10]='%';ch[11]='P'; ch[12]='W'; ch[13]=0x30; ch[14]=0x31 ;
ch[15]=0x30; ch[16]=0x35;
ch[17]='%';ch[18]='P'; ch[19]='W'; ch[20]=0x30; ch[21]=0x33 ;
ch[22]=EOT ;
CommPort->SendData(ch,sizeof(ch)) ;
}
//---------------------------------------------------------------------------
void TMain::Analog_Send(void) // 아날로그 값을 읽기 위한 함수
{
byte ch[41] ;
ch[0]=ENQ; ch[1]=0x30; ch[2]=0x30; ch[3]='R'; ch[4]='S';
ch[5]='S'; ch[6]=0x30; ch[7]=0x34;
ch[8]=0x30; ch[9]=0x36;
ch[10]='%';ch[11]='D'; ch[12]='W'; ch[13]=0x31; ch[14]=0x31 ; ch[15]=0x32 ;
ch[16]=0x30; ch[17]=0x36;
ch[18]='%';ch[19]='D'; ch[20]='W'; ch[21]=0x31; ch[22]=0x31 ; ch[23]=0x33 ;
ch[24]=0x30; ch[25]=0x36;
ch[26]='%';ch[27]='D'; ch[28]='W'; ch[29]=0x31; ch[30]=0x31 ; ch[31]=0x34 ;
ch[32]=0x30; ch[33]=0x36;
ch[34]='%';ch[35]='D'; ch[36]='W'; ch[37]=0x31; ch[38]=0x31 ; ch[39]=0x35 ;
ch[40]=EOT ;
CommPort->SendData(ch,sizeof(ch)) ;
}
// 위의 두 함수에서 배열값을 제가 함수에서 지정했는데 고정된 값이기 때문에
헤더에 정의 하던가 아니면 별도의 모듈에서 static 전역으로 설정해서 사용하는 것이
좋을 것입니다.
예) static byte analog[41] = {--------} ; 아날로그값 Read 포맷
static byte IO_Read[25] = {----------} ; I/O Read 포맷
byte IO_Write[20] = {--------} ; I/O Write 포맷(값이 변경됨으로 static를 선언하지 않음)
이런 것인데 이상하게 빌더에서는 이런
형태로 초기화가 안되더군요.. 그래서 부득이 위의 함수와 같이 무식한 방법을
사용했습니다.
void TMain::Out_send(int temp) // I/O 포트를 제어하기 위한 함수
{
byte ch[20] ;
byte tempA,tempB ;
ch[0]=ENQ ; ch[1]=0x30; ch[2]=0x30; ch[3]=0x57; ch[4]=0x53;
ch[5]=0x53; ch[6]=0x30; ch[7]=0x31; ch[8]=0x30; ch[9]=0x35;
ch[10]=0x25; ch[11]=0x50; ch[12]=0x57; ch[13]=0x30; ch[14]=0x34 ;
switch(temp)
{
case 0 : output = output | 0x80 ; // Analog Active
break ;
:
:
:
break ;
case 13: output = output | 0x01 ; // 진공주입기 ON
break ;
case 14: output = output & 0xfe ; // 진공주입기 OFF
break ;
}
tempA = output >> 4 ;
tempB = output & 0x0f ;
ch[15] = 0x30 ;
ch[16] = 0x30 ;
ch[17] = HexToAsc(tempA) ;
ch[18] = HexToAsc(tempB) ;
ch[19] = EOT ;
CommPort->SendData(ch,sizeof(ch)) ;
}
위의 3 함수는 PLC 의 프로토콜과 관련된 함수 입니다.
저도 오래된데가 메뉴얼이 없어 위의 데이타 포맷의 각 값들의 의미를
모르겠습니다.
아마 메뉴얼에서 위와 비슷한 포맷의 프로토콜의 찾아 분석해 보시면
아실 것입니다.
void __fastcall TMain::Timer1Timer(TObject *Sender)
{
if(send==true)
{
Input_Send() ;
send = false ;
}
else
{
Analog_Send() ;
send = true ;
}
}
위의 함수는 타이머에서 아날로그 값과 I/O 를 번갈아 가며 읽어들이기 위한 것입니다.
void __fastcall TMain::CommPortReceiveData(TObject *Sender,
Pointer DataPtr, int DataSize)
{
char* data = new char[DataSize+1] ;
strncpy(data,(char*)DataPtr,DataSize) ; // Data Copy to work buffer
if(send==false) // I/O 포트값을 전송했을 경우 들어오는 데이타
{
if(data[0] == ACK && data[20] == ETX ) // ACK 에서 시작해서 ETX 로 끝나는 데이타 페키지
{
byte *temp = new byte[8] ;
temp[0] = AscToHex(data[10]) ;
temp[1] = AscToHex(data[11]) ;
temp[2] = AscToHex(data[12]) ;
temp[3] = AscToHex(data[13]) ;
temp[4] = AscToHex(data[16]) ;
temp[5] = AscToHex(data[17]) ;
temp[6] = AscToHex(data[18]) ;
temp[7] = AscToHex(data[19]) ;
Display(temp) ;
delete[] temp ;
}
}
else // 아날로그값을 읽기위해 전송한 후 들어오는 데이타
{
if(data[0] == ACK && data[32] == ETX)
{
short *value = new short[4] ;
value[0] = 0xfff0 | AscToHex(data[10]) ;
value[0] <<= 4 ;
value[0] = value[0] | AscToHex(data[11]) ;
value[0] <<= 4 ;
value[0] = value[0] | AscToHex(data[12]) ;
value[0] <<= 4 ;
value[0] = value[0] | AscToHex(data[13]) ;
위의 내용은 아날로그 값은 4바이트 되어있음을 나타냄
:
:
:
value[3] = 0xfff0 | AscToHex(data[28]) ;
value[3] <<= 4 ;
value[3] = value[3] | AscToHex(data[29]) ;
value[3] <<= 4 ;
value[3] = value[3] | AscToHex(data[30]) ;
value[3] <<= 4 ;
value[3] = value[3] | AscToHex(data[31]) ;
Display_Analog(value) ;
delete[] value ;
}
}
CommPort->FlushBuffers(true,true) ;
delete[] data ;
}
|