시리얼 통신 수신부 질문입니다.(Win <-> Win)
글쓴이: sjun027 / 작성시간: 수, 2014/04/02 - 4:11오후
UINT CommThread(LPVOID lpData) { extern short g_nRemoteStatus; DWORD ErrorFlags; COMSTAT ComStat; DWORD EvtMask ; memset(ucRxBuffer, NULL, sizeof(ucRxBuffer)); DWORD Length, dwRead; int size; int insize = 0; CMycomm* Comm = (CMycomm*)lpData; while (Comm->m_bIsOpenned) { EvtMask = 0; Length = 0; insize = 0; memset(ucRxBuffer, NULL, sizeof(ucRxBuffer)); WaitCommEvent(Comm->m_hComDev,&EvtMask, NULL); ClearCommError(Comm->m_hComDev, &ErrorFlags, &ComStat); if ((EvtMask & EV_RXCHAR) && ComStat.cbInQue) //////★(1) { if (ComStat.cbInQue > MAXBUF) size = MAXBUF; else size = ComStat.cbInQue; do { ClearCommError(Comm->m_hComDev, &ErrorFlags, &ComStat); if (!ReadFile(Comm->m_hComDev, ucRxBuffer+insize, size, &Length, &(Comm->m_OLR))) //////★(2) { // 에러 TRACE("Error in ReadFile\n"); if (GetLastError() == ERROR_IO_PENDING) { if (WaitForSingleObject(Comm->m_OLR.hEvent, 1000) != WAIT_OBJECT_0) Length = 0; else GetOverlappedResult(Comm->m_hComDev, &(Comm->m_OLR), &Length, FALSE); } else Length = 0; } insize += Length; } while ((Length!=0) && (insize</*size*/aSize)); ClearCommError(Comm->m_hComDev, &ErrorFlags, &ComStat); if (Comm->m_nLength + insize > MAXBUF*2) insize = (Comm->m_nLength + insize) - MAXBUF*2; Comm->m_pEvent->ResetEvent(); Comm->m_nLength += insize; memcpy(Comm->m_sInBuf, ucRxBuffer, insize); Comm->m_pEvent->SetEvent(); LPARAM temp=(LPARAM)Comm; TRACE("\nSEND MESSAGE: \n"); SendMessage(Comm->m_hWnd, WM_MYRECEIVE, Comm->m_nLength, temp); //// } PurgeComm(Comm->m_hComDev, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); LPARAM temp=(LPARAM)Comm; SendMessage(Comm->m_hWnd, WM_MYCLOSE, 0, temp); return 0; }
질문입니다..
WriteFile()을 통해서 송신을 합니다. 인자로 보낼 데이터 사이즈(예를 들어 100 바이트)를 넣어서 보내기에 문제가 없다고 생각합니다.
- 하지만 (1)의 ComStat.cbInQue()에서 늘 100이 나오는게 아니고 90이라든지 21이라든지 가끔 적게 들어오기도 합니다.
- (2)에서 ComStat.cbInQueue()만큼 읽습니다. 읽은 바이트 = Length (1)의 오류를 보정하기 위해
insize를 만들어 ucRxBuffer의 insize 위치부터 다시 더해줌으로써 100바이트의 ucRxBuffer을 완성합니다.
- 하지만 더 신기한 것은 (2)의 Length, 즉 읽은 데이터가 cbInQueue()의 값과 다를 때가 있습니다. 즉, 읽은 데이터가 없는 것 같은데..
이렇게 될 수도 있습니까?
조언을 좀 부탁드리겠습니다.
감사합니다.
Forums:
제가 예전에 시리얼 통신 하면서 만들어놓은 함수가 있습니다.
시리얼통신 버퍼에 cbInQue 만큼 데이터가 들어간다고 알린 후 실제 데이터가 들어오는데
데이터가 들어오는 와중에 ReadFile 파일을 하면 ReadFile이 FALSE를 리턴 합니다.
이때 GetLastError() 호출하면 ERROR_IO_PENDING 가 나오는데 이건 에러가 아니고 정상적인 동작입니다.
ERROR_IO_PENDING 에러일때는 데이터가 전부 들어올때까지 기다려야 합니다.
그런데 언제까지 기다려야 할까요
GetOverlappedResult 함수가 TRUE를 리턴할때까지 기다리면 됩니다.
아래는 제가 예전에 만들어 놓은 함수인데 참고 하시기 바랍니다.
/*
설명: 시리얼 포트에서 데이터를 읽어 온다.
@ hCommPort : 시리얼 포트 핸들.
@ buff : 데이터 저장 버퍼.
@ nLength : 준비된 데이터 길이.
@ return : 읽은 데이터 길이. ( -1 이면 읽기 오류 발생 )
*/
DWORD ReadSerial(HANDLE hCommPort, char* buff, DWORD nLength)
{
DWORD dwReturn;
if (!ReadFile(hCommPort, buff, nLength, &dwReturn, &g_osRead))
{
// 수신이 완료되지 않았음.
if (GetLastError() == ERROR_IO_PENDING)
{
TRACE( _T("ERROR_IO_PENDING 발생!!!\r\n") );
// 수신이 완료 될때까지 기다림.
while( !GetOverlappedResult( hCommPort, &g_osRead, &dwReturn, TRUE ) )
{
// 정상 대기중...
if( GetLastError() == ERROR_IO_INCOMPLETE )
{
TRACE( _T("ERROR_IO_INCOMPLETE 정상 대기\r\n") );
continue;
}
// 읽기 오류 발생.
else
{
dwReturn = -1;
break;
}
}
}
// 읽기 오류 발생!
else dwReturn = -1;
}
return dwReturn;
}
댓글 달기