시리얼 통신 수신부 질문입니다.(Win <-> Win)

sjun027의 이미지

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()의 값과 다를 때가 있습니다. 즉, 읽은 데이터가 없는 것 같은데..
이렇게 될 수도 있습니까?

조언을 좀 부탁드리겠습니다.
감사합니다.

wmjj의 이미지

시리얼통신 버퍼에 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;
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.