serial´ÔÀÇ ±Û
------------------------------------
// SerialPort.cpp : implementation file
//
#include "stdafx.h"
#include "CraneControl.h"
#include "SerialPort.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CSerialPort
CSerialPort::CSerialPort()
{
m_hComm = NULL;
m_bThreadAlive = FALSE;
m_Thread = NULL;
m_ovrWrite.Offset = 0;
m_ovrWrite.OffsetHigh = 0;
m_osRead.Offset = 0;
m_ovrWrite.OffsetHigh = 0;
m_strComErrMsg =_T(""); //¿¡·¯ ¸®Æ÷Æ® ..Ãʱ⠽ÇÇà½Ã ºñ¿ì°í
}
CSerialPort::~CSerialPort()
{
ClosePort();
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CSerialPort, CObject)
//{{AFX_MSG_MAP(CSerialPort)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/////////////////////////////////////////////////////////////////////////////
// CSerialPort member functions
BOOL CSerialPort::OpenPort(CWnd* pPortOwner, LPTTYSTRUCT lpTTY)
{
BOOL bResult = FALSE;
char szPort[8]; //
DCB dcb; //ÀåÄ¡ Á¦¾î ºí·Ï ±¸Á¶Ã¼ (Device-Control Block, DCB)
COMMTIMEOUTS cto; //ŸÀӾƿô°ª ¼³Á¤
CString sMessage; //¿¡·¯ ¸Þ½ÃÁö
m_pOwner = pPortOwner;
m_nPortNr = lpTTY->byCommPort; //Á¢¼Ó port ¼³Á¤
//½Ã¸®¾ó Æ÷Æ®ÀÇ »óŸ¦ ¹Þ±âÀ§ÇØ À̺¥Æ® °³Ã¼¸¦ ÀÌ¿ëÇÑ ½º·¹µå°£ÀÇ µ¿±âÈ
//Æ÷Å並 ¿±âÀ§ÇÑ Àüó¸®
m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(m_osRead.hEvent == NULL)
{
AfxMessageBox("m_osRead.hEvent Error");
return FALSE;
}
m_ovrWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if(m_ovrWrite.hEvent == NULL)
{
AfxMessageBox("m_ovrWrite.hEvent Error");
return FALSE;
}
sprintf(szPort, "COM%d", m_nPortNr); //¹öÆÛ ¿À¹öÇÃ·Î¿ì º¸È£¸¦ À§ÇÑ ÇÔ¼öÀε¥ ¿©±â¿¡¼´Â
//commport°¡ ÁöÁ¤µÈ´Ù
//Æ÷Æ® µð¹ÙÀ̽º¸¦ ¿¬´Ù
m_hComm = CreateFile(szPort, // £§COM1 or COM2...£§communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // ÀÏ°í¾²±âÁöÁ¤...¾ï¼¼½º ¸ðµå
0, // ´Ù¸¥ÇÁ·Î±×·¥°úÀÇ °øÀ¯¸ðµå
NULL, // º¸¾ÈÁ¤º¸ (º¸¾È¾ÈÇÔ)
OPEN_EXISTING, // ±âÁ¸ÀÇ ÆÄÀÏÀ» ¿¬´Ù..comm devices »ý¼º¹æ¹ý
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //ÆÄÀÏ Ç÷¡±×¿Í ¼Ó¼º
NULL); // ÅÛÇ÷¹ÀÌÆ® ÆÄÀÏ ÇÊ¿ä¾øÀ½..template must be 0 for comm devices
if (m_hComm == INVALID_HANDLE_VALUE)
{
m_strComErrMsg = "Can£§t Create Device port ";
m_hComm = NULL;
return FALSE;
}
ZERO_MEMORY(dcb); //RS-232cÀåÄ¡ Á¦¾î ºí·Ï ±¸Á¶Ã¼¸¦ ÃʱâÈ
dcb.DCBlength = sizeof(DCB); //DCB Å©±â ºñ±³
if (!GetCommState(m_hComm, &dcb)) //DCBÃʱâÈ
return FALSE;
dcb.BaudRate = lpTTY->dwBaudRate; // DCB±¸Á¶Ã¼ÀÇ Å©±â
dcb.Parity = lpTTY->byParity; //CTS ÁöÁ¤ Ç÷¯±× 1À̸é CTS°¡ 1ÀÌ µÉ ¶§±îÁö ±â´Ù¸°´Ù.
dcb.ByteSize = lpTTY->byByteSize; //number of bits/byte, 4-8 Æ÷Æ®¿¡ ÀÇÇØ ÇöÀç »ç¿ëµÇ´Â µ¥ÀÌÅÍ ºñÆ®¼ö
dcb.StopBits = lpTTY->byStopBits; //Á¤Áö ºñÆ®:Æ÷Æ®¿¡ ÀÇÇØ ÇöÀç »ç¿ëµÇ´Â µ¥ÀÌÅÍ ºñÆ®¼ö
dcb.fOutxCtsFlow = 0; //CTS ÁöÁ¤ Ç÷¯±× 1À̸é CTS°¡ 1ÀÌ µÉ ¶§±îÁö ±â´Ù¸°´Ù.
dcb.fOutxDsrFlow = 0; //DSR ÁöÁ¤ Ç÷¯±× 1À̸é DSRÀÌ 1ÀÌ µÉ ¶§ ±îÁö ±â´Ù¸°´Ù.
//if(m_nPortNr == 7)
//{
// dcb.fDtrControl = DTR_CONTROL_DISABLE; //DTR ÁöÁ¤ Ç÷¯±× DTR_CONTROL_DISBLE·Î ¼³Á¤½Ã DTRÀÌ OFFµÇ°í
//DTR_CONTROL_ENABLE ¸¦ ¼³Á¤Çϸé DTRÀº ONÀ̵ȴÙ.
// dcb.fRtsControl = RTS_CONTROL_DISABLE; //RTS´Â ÀÌ°ªÀÌ RTS_CONTROL_DISABLE·Î ¼³Á¤½Ã 0À̵ǰí
// RTS_CONTROL_ENABLE·Î ¼³Á¤µÉ ¶§ ONÀÌ µÈ´Ù.
//}
dcb.fOutX = 0; // ÀÌ°ªÀÌ 1À̸é XoffChar¹®ÀÚ ¼ö½Å½Ã Áß´Ü
// XON/XOFF out flow control
dcb.fInX = 0; // ÀÌ°ªÀÌ 1À̸é XoffChar¹®ÀÚ´Â ¼ö½Å ¹öÆÛ°¡ XoffLim¹ÙÀÌÆ®
// ¾È¿¡ ÀÖÀ» °æ¿ì º¸³»Áö°í XonChar ¹«ÀÚ´Â XonLim¾È¿¡ ÀÖÀ» ¶§
// º¸³»Áø´Ù.
dcb.fBinary = TRUE; // binary mode¼³Á¤ 1·Î ¼³Á¤Çϸé binary mode°¡´É
dcb.fParity = TRUE; // Æи®Æ¼ °Ë»ç ±â´É À¯¹« .. enable parity check
dcb.XonChar = ASCII_XON;
dcb.XoffChar = ASCII_XOFF;
dcb.XonLim = 100;
dcb.XoffLim = 100;
if (!SetCommState(m_hComm, &dcb)) //DCB¸¦ Æ÷Åä¿¡ ¿¬°á
{
CloseHandle(m_hComm);
return FALSE;
}
//ŸÀÓ ¾Æ¿ô°ª ¼³Á¤
cto.ReadIntervalTimeout = 100;
cto.ReadTotalTimeoutConstant = 100;
cto.ReadTotalTimeoutMultiplier = 100;
if (!SetCommTimeouts(m_hComm, &cto)) //¼ö½Å°ú ¼Û½ÅÀÇ ½Ã°£À» ¼³Á¤
return FALSE;
//Åë½ÅÆ÷Åä·Î ÅëÇØ ¹®ÀÚ°¡ ¼ö½ÅµÇ¾ú´Ù´Â °ÍÀ» ¸¶½ºÅ©·Î ¼³Á¤
if (!SetCommMask(m_hComm, EV_RXCHAR))
return FALSE;
//¹öÆÛ¸¦ ¸ðµÎ ±ú²ýÇÏ°Ô Ã»¼ÒÇØ ³õ°í ¶ÇÇÑ Æ÷Æ® µð¹ÙÀ̽º¸¦ ÃʱâÈ
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
m_bThreadAlive = FALSE;
return TRUE;
}
void CSerialPort::ClosePort()
{
if (m_Thread != NULL)
{
DWORD dwSuspendCount;
do
{
dwSuspendCount = m_Thread->ResumeThread();
}
while((dwSuspendCount != 0) && (dwSuspendCount != 0xffffffff));
}
m_bThreadAlive = FALSE; //½º·¹µå ÇØÁ¦
//ÄÄÆ÷Æ® ´Ý±â
if (m_hComm != NULL)
CloseHandle(m_hComm);
//µ¥ÀÌÅÍ ±¸Á¶Ã¼ ÇØÁ¦
if(m_ovrWrite.hEvent!= NULL )
{
CloseHandle(m_ovrWrite.hEvent);
CloseHandle(m_osRead.hEvent);
}
m_hComm = NULL;
m_ovrWrite.hEvent = NULL;
m_osRead.hEvent = NULL;
}
//¾²·¹µå »ý¼º
BOOL CSerialPort::StartMonitoring()
{
if (!(m_Thread = AfxBeginThread(CommThread, this)))
{
m_strComErrMsg += "Thread Start Error";
//MessageBox(NULL,"Thread Start Error",NULL,MB_OK);
return FALSE;
}
m_bThreadAlive = TRUE;
return TRUE;
}
//threadÀÇ Àç½ÃÀÛ
BOOL CSerialPort::RestartMonitoring()
{
if (m_Thread)
m_Thread->ResumeThread();
return TRUE;
}
// threadÀÇ ´ë±â
BOOL CSerialPort::StopMonitoring()
{
if (m_Thread)
m_Thread->SuspendThread();
return TRUE;
}
UINT CSerialPort::CommThread(LPVOID pParam)
{
DWORD dwEvent = 0;
DWORD dwError = 0;
BOOL bResult = TRUE;
CSerialPort *port = NULL;
BYTE buff[256]; //---- Àб⠹öÆÛ
DWORD dwRead; //
//½º·¹µå¸¦ offÇϱâÀ§ÇØ 0À¸·Î ¼ÂÆÃ
//ReadComm()ÇÔ¼ö¿¡¼ ¹öÆÛÀÇ µ¥ÀÌÅ͸¦ ´Ù ÀÐÁö ¸øÇϸé 0ÀÌ ¾Æ´Ñ ´Ù¸¥°ªÀÌ ÀÖ´Ù.
port = (CSerialPort*)pParam;
//port->m_bThreadAlive = TRUE;
//½Ã¸®¾óÆ÷Æ®ÀÇ Æ÷Æ® µð¹ÙÀ̽º°¡ ¿¬°áµÇ¾îÀÖ´Ù¸é
//¹öÆÛ¸¦ ¸ðµÎ ±ú²ýÇÏ°Ô Ã»¼ÒÇØ ³õ°í ¶ÇÇÑ Æ÷Æ® µð¹ÙÀ̽º¸¦ ÃʱâÈ
if (port->m_hComm)
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
while(port->m_bThreadAlive) //¾²·¹µå°¡ È°¼ºÈµÇ¾î ÀÖÀ»µ¿¾È
{
dwEvent = 0;
//ÇÔ¼öÀÇ 2¹ø° ÀÎÀÚ´Â OVERLAPPED±¸Á¶Ã¼ ÀÌ´Ù. º¸Åë Åë½ÅÀ» ÇÒ °æ¿ì µ¿±âȸ¦ Çϱâ
//¶§¹®¿¡ À̱¸Á¶Ã¼¸¦ »ç¿ëÇÏÁö ¾Ê°í NULL·Î ¼³Á¤
//WaitCommEvent(port->m_hComm, &dwEvent,NULL); //¹®ÀÚ°¡ µé¾î¿À±â¸¦ ±â´Ù¸²
//WaitCommEvent( port->m_hComm, &dwEvent,&port->m_ovrWrite);
//if ((dwEvent & EV_RXCHAR) == EV_RXCHAR) //¹®ÀÚ¿ÀÌ µé¾î¿ÔÀ» ¶§ ¼öÇàÇÏ´Â ³»¿ë
//{
do
{
dwRead = port->ReadComm(buff, 256);
if (dwRead > 0)
port->ProcessRcvData(port, buff, (BYTE)dwRead );
else
Sleep(90); //100ÀÌ µÇ¸é ½ÇÇà Áß ¿¡·¯³²
} while (dwRead);
//}
}
return 0;
}
DWORD CSerialPort::ReadComm(BYTE *pBuff, DWORD nToRead)
{
DWORD dwRead, dwError, dwErrorFlags;
COMSTAT comstat; //Åë½Å ÀåÄ¡ÀÇ Á¤º¸¸¦ ´ã°íÀÖ´Â ±¸Á¶Ã¼
//¹öÆÛ¿¡ ³²¾ÆÀÖ´Â ¹ÙÀÌÆ®ÀÇ ¼ö¸¦ ÆľÇÇÏ¿© Çѹø¿¡ ÀоîµéÀÌ´Â ÀÛ¾÷À» ÇÑ´Ù.
//ÀÌ ¹æ¹ýÀº ¸Å¿ì º¹ÀâÇÑ ¹öÆÛ °ü¸®¸¦ ¿ä±¸ÇÏÁö¸¸
//¾öû³ª°Ô ¸¹Àº µ¥ÀÌÅÍ°¡ ¼ö½ÅµÈ °ÍÀ» ÀоîµéÀ̴ Ƚ¼ö¸¦ ÇѹøÀ¸·Î ÁÙ¿©ÁØ´Ù.
ClearCommError( m_hComm, &dwErrorFlags, &comstat);
dwRead = comstat.cbInQue; // bytes in input buffer
//¹öÆÛ¿¡ µ¥ÀÌÅÍ°¡ ÀÖ´Ù¸é
if(dwRead > 0)
{
//µ¥ÀÌÅÍ Àбâ
//µ¥ÀÌÅ͸¦ Àд °ÍÀº À§ÀÇ µ¥ÀÌÅ͸¦ ¾²´Â ÇÔ¼ö¿Í ºñ½Á´Ù. ÇÔ¼ö¸íÀº ReadFileÀÔ´Ï´Ù.
//ù¹ø° ÀÎÀÚ´Â ÆÄÀÏ Çڵ鷯ÀÌ°í,
//µÎ ¹ø° ÀÎÀÚ´Â ½á¾ß ÇÒ µ¥ÀÌÅÍ,
//¼¼ ¹ø° ÀÎÀÚ´Â ½á¾ß ÇÒ ¹ÙÀÌÆ®ÀÇ ¼ö,
//³× ¹ø° ÀÎÀÚ´Â ½á¾ß ÇÒ ¹ÙÀÌÆ®¼ö°¡ µé¾î ÀÖ´Â ¹øÁö,
//´Ù¼¸ ¹ø° ÀÎÀÚ´Â À§¿¡¼ ¸¸µç overWriteÀÔ´Ï´Ù.
if( !ReadFile( m_hComm, pBuff, nToRead, &dwRead, &m_osRead) )//¿À¹ö·¦´ë½Å NULL·Î Çϸé Åë½Å ¾ÈµÊ
{
//µ¥ÀÌÅÍ°¡ ³²¾ÆÀÖ´Ù¸é
if (GetLastError() == ERROR_IO_PENDING)
{
/*timeouts¿¡ Á¤ÇØÁØ ½Ã°£¸¸Å ±â´Ù·ÁÁØ´Ù.
GetOverlappedResult°¡ ÀÛ¾÷ÀÇ °á°ú¸¦ ·¹Æ÷Æ® ÇØÁØ´Ù.
¸¸¾à¿À·ù°¡ ¹ß»ýÇÏ¿´´Ù¸é GetOverlappedResult´Â FALSE¸¦ µ¹·ÁÁÖ°í
GetLastError°¡ ¿À·ù Äڵ带 µÇµ¹·Á ÁØ´Ù.
¸¸¾à ÀÛ¾÷ÀÌ ¼º°øÀûÀ¸·Î ³¡³µ´Ù¸é GetOverlappedResult´Â TRUE¸¦ µ¹·ÁÁØ´Ù.
ÁÖÀÇ : GetOverlappedResult´Â ÀÛ¾÷ÀÌ Á¾·áµÇ¾ú´ÂÁö ½ÇÆÐµÈ »óÅÂÀÎÁö¸¦ ¾Ë¼ö ÀÖ´Ù.
GetOverlappedResult°¡ FALSE¸¦ µ¹·ÁÁÖ°í
GetLastError°¡ ERROR_IO_INCOMPLETEÀÌ¸é ±× ÀÛ¾÷Àº Á¾·áµÈ °ÍÀÌ ¾Æ´Ï´Ù.
¶ÇÇÑ GetOverlappedResult´Â ÀÛ¾÷ÀÌ Á¾·áµÉ ¶§±îÁö ºÙÀâÀ» ¼ö ÀÖ´Ù.
bWaitÆĶó¹ÌÅÍ¿Í °°Àº °Í¿¡ TRUE¸¦ ³Ñ°Ü ÁÜÀ¸·Î½á ¿À¹ö·¾°ú ³í¿À¹ö·¾À» ÀüȯÇÒ ¼ö ÀÖ´Ù. */
while (! GetOverlappedResult( m_hComm, &m_osRead, &dwRead, TRUE))
{
dwError = GetLastError();
if (dwError != ERROR_IO_INCOMPLETE) //ÀÛ¾÷ÀÌ Á¾·áµÇ¸é
{
ClearCommError( m_hComm, &dwErrorFlags, &comstat); //µ¥ÀÌŸ Àаí
break;
} //End of four if
} //End of first while
}//End of third if
else //µ¥ÀÌÅÍ°¡ ¾ø´Ù¸é
{
dwRead = 0;
ClearCommError( m_hComm, &dwErrorFlags, &comstat);
}//third if for end of else
} //end of second if
} //End of firat if
//--> ½ÇÁ¦ ÀоîµéÀÎ °¹¼ö¸¦ ¸®ÅÏ.
return dwRead;
}
void CSerialPort::ProcessRcvData(CSerialPort* port, BYTE *byBuf, int nSize)
{
if( !nSize ){return;} //µ¥ÀÌŸ°¡ ¾øÀ¸¸é
memset(m_strData, NULL, 32);
for( int i=0; i<nSize; i++ ) //Æ÷Æ®·Î¹ÞÀº µ¥ÀÌÅ͸¦ Àü¿ª¹è¿¿¡ ÀúÀå
m_strData[i] = byBuf[i];
if(m_pOwner)
m_pOwner->SendMessage(WM_RECEIVE_COM, (LPARAM)port->m_nPortNr, (WPARAM) nSize);
}
//µ¥ÀÌÅÍ SEND
DWORD CSerialPort::WriteComm(BYTE *pBuff, DWORD nToWrite)
{
DWORD dwWritten, dwError, dwErrorFlags;
COMSTAT comstat;
int n;
//µ¥ÀÌÅÍ ¾²±â
/***********************************************************************
*ù¹ø° ÀÎÀÚ´Â ÆÄÀÏ Çڵ鷯(Æ÷Æ® µð¹ÙÀ̽º), µÎ ¹ø° ÀÎÀڴ½á¾ß ÇÒ µ¥ÀÌÅÍ*
*¼¼ ¹ø° ÀÎÀÚ´Â ½á¾ß ÇÒ ¹ÙÀÌÆ®ÀÇ ¼ö, ³× ¹ø° ÀÎÀÚ´Â ½á¾ß ÇÒ ¹ÙÀÌÆ®¼ö°¡ *
*µé¾î ÀÖ´Â ¹øÁö, ´Ù¼¸ ¹ø° ÀÎÀÚ´Â À§¿¡¼ ¸¸µçosWrite *
************************************************************************/
n = WriteFile(m_hComm, pBuff, nToWrite, &dwWritten,&m_ovrWrite);
if(!n)//Æ÷Æ®¿¡ Á¦´ë·Î ½áÁöÁö ¾Ê¾ÒÀ¸¸é
{
if(GetLastError() == ERROR_IO_PENDING ) // ¾ÆÁ÷ Àü¼ÛÇÒ ¹®ÀÚ°¡ ³²¾ÆÀÖ´Ù¸é
{
//---- Åë½Å°á°ú°¡ ½ÇÆÐÇÏ¸é ¾î¶² ¿¡·¯°¡ ³µ´ÂÁö ¾Ë±âÀ§ÇØ GetLastError¸¦ È£ÃâÇÑ´Ù.
while( !GetOverlappedResult(m_hComm,&m_ovrWrite,&dwWritten,TRUE) )
{
dwError = GetLastError();
if(dwError != ERROR_IO_INCOMPLETE) //ÀÛ¾÷Àº Á¾·áµÈ °ÍÀÌ ¾Æ´Ï¸é
{
ClearCommError(m_hComm,&dwErrorFlags,&comstat);
break;
}
}
}
else
{
dwWritten = 0;
ClearCommError(m_hComm,&dwErrorFlags,&comstat);
}
}
return dwWritten;
}
------------------------------------
|