#include "stdafx.h" #include "CommThread.h" extern HWND g_hCommWnd; void CQueue::Clear() { m_iHead = m_iTail =0; memset(buff,0,BUFF_SIZE); } CQueue::CQueue() { Clear(); } int CQueue::GetSize() { return (m_iHead - m_iTail + BUFF_SIZE) % BUFF_SIZE; } BOOL CQueue::PutByte(BYTE b) { if(GetSize() == (BUFF_SIZE-1)) return FALSE; buff[m_iHead++] =b; m_iHead %= BUFF_SIZE; return TRUE; } BOOL CQueue::PutBytes(BYTE *b, int nBytes) { if(GetSize() == (BUFF_SIZE-1)) return FALSE; for(int i = 0 ; i < nBytes ; i++) { buff[m_iHead++] = *(b+i); m_iHead %= BUFF_SIZE; } return TRUE; } BOOL CQueue::GetByte(BYTE *pb) { if(GetSize() == 0) return FALSE; *pb = buff[m_iTail++]; m_iTail %= BUFF_SIZE; return TRUE; } BOOL CQueue::GetBytes(BYTE *pb, int nBytes) { if(GetSize() == 0) return FALSE; for(int i = 0 ; i < nBytes ; i++) { *(pb+i) = buff[m_iTail++]; m_iTail %= BUFF_SIZE; } return TRUE; } //--- Ŭ·¡½º »ý¼ºÀÚ CCommThread::CCommThread() { //--> Ãʱâ´Â ´ç¿¬È÷..Æ÷Æ®°¡ ¿­¸®Áö ¾ÊÀº »óÅ¿©¾ß°ÚÁÒ? m_bConnected = FALSE; } CCommThread::~CCommThread() { } BOOL CCommThread::CheckPort(CString strPortName, DWORD dwBaud, BYTE byData, BYTE byStop, BYTE byParity ) { // Local º¯¼ö. COMMTIMEOUTS timeouts; DCB dcb; DWORD dwThreadID; // overlapped structure º¯¼ö ÃʱâÈ­. m_osRead.Offset = 0; m_osRead.OffsetHigh = 0; //--> Read À̺¥Æ® »ý¼º¿¡ ½ÇÆÐ.. if ( !(m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) ) { return FALSE; } m_osWrite.Offset = 0; m_osWrite.OffsetHigh = 0; //--> Write À̺¥Æ® »ý¼º¿¡ ½ÇÆÐ.. if (! (m_osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { return FALSE; } //--> Æ÷Æ®¸í ÀúÀå.. m_sPortName = strPortName; //--> ½ÇÁ¦ÀûÀÎ...RS 232 Æ÷Æ® ¿­±â.. m_hComm = CreateFile( m_sPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); //--> Æ÷Æ® ¿­±â¿¡ ½ÇÇØÇϸé.. if (m_hComm == (HANDLE) -1) { // AfxMessageBox(_T("fail Port ofen")); return FALSE; } else { ClosePort(); return TRUE; } } // Æ÷Æ® sPortNameÀ» dwBaud ¼Óµµ·Î ¿¬´Ù. // ThreadWatchComm ÇÔ¼ö¿¡¼­ Æ÷Æ®¿¡ ¹«¾ð°¡ ÀÐÇûÀ» ¶§ MainWnd¿¡ ¾Ë¸®±â // À§ÇØ WM_COMM_READ¸Þ½ÃÁö¸¦ º¸³¾¶§ °°ÀÌ º¸³¾ wPortID°ªÀ» Àü´Þ ¹Þ´Â´Ù. BOOL CCommThread::OpenPort(CString strPortName, DWORD dwBaud, BYTE byData, BYTE byStop, BYTE byParity ) { // Local º¯¼ö. COMMTIMEOUTS timeouts; DCB dcb; DWORD dwThreadID; // overlapped structure º¯¼ö ÃʱâÈ­. m_osRead.Offset = 0; m_osRead.OffsetHigh = 0; //--> Read À̺¥Æ® »ý¼º¿¡ ½ÇÆÐ.. if ( !(m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) ) { return FALSE; } m_osWrite.Offset = 0; m_osWrite.OffsetHigh = 0; //--> Write À̺¥Æ® »ý¼º¿¡ ½ÇÆÐ.. if (! (m_osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { return FALSE; } //--> Æ÷Æ®¸í ÀúÀå.. m_sPortName = strPortName; //--> ½ÇÁ¦ÀûÀÎ...RS 232 Æ÷Æ® ¿­±â.. m_hComm = CreateFile( m_sPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); //--> Æ÷Æ® ¿­±â¿¡ ½ÇÇØÇϸé.. if (m_hComm == (HANDLE) -1) { // AfxMessageBox(_T("fail Port ofen")); return FALSE; } //===== Æ÷Æ® »óÅ ¼³Á¤. ===== // EV_RXCHAR event ¼³Á¤...µ¥ÀÌÅͰ¡ µé¾î¿À¸é.. ¼ö½Å À̺¥Æ®°¡ ¹ß»ýÇϰԲû.. SetCommMask( m_hComm, EV_RXCHAR); // InQueue, OutQueue Å©±â ¼³Á¤. SetupComm( m_hComm, BUFF_SIZE, BUFF_SIZE); // Æ÷Æ® ºñ¿ì±â. PurgeComm( m_hComm, PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR); // timeout ¼³Á¤. timeouts.ReadIntervalTimeout = 0xFFFFFFFF; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = 0; timeouts.WriteTotalTimeoutMultiplier = 2*CBR_9600 / dwBaud; timeouts.WriteTotalTimeoutConstant = 0; SetCommTimeouts( m_hComm, &timeouts); // dcb ¼³Á¤.... Æ÷Æ®ÀÇ ½ÇÁ¦ÀûÀÎ..Á¦¾î¸¦ ´ã´çÇÏ´Â DCB ±¸Á¶Ã¼°ª ¼ÂÆÃ.. dcb.DCBlength = sizeof(DCB); //--> ÇöÀç ¼³Á¤µÈ °ª Áß¿¡¼­.. GetCommState( m_hComm, &dcb); //--> º¸µå·¹ÀÌÆ®¸¦ ¹Ù²Ù°í.. dcb.BaudRate = dwBaud; //--> Data 8 Bit dcb.ByteSize = byData; //--> Noparity dcb.Parity = byParity; //--> 1 Stop Bit dcb.StopBits = byStop; //--> Æ÷Æ®¸¦ Àç..¼³Á¤°ªÀ¸·Î.. ¼³Á¤Çغ¸°í.. if( !SetCommState( m_hComm, &dcb) ) { return FALSE; } // Æ÷Æ® °¨½Ã ¾²·¹µå »ý¼º. m_bConnected = TRUE; //--> Æ÷Æ® °¨½Ã ¾²·¹µå »ý¼º. m_hThreadWatchComm = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadWatchComm, this, 0, &dwThreadID); //--> ¾²·¹µå »ý¼º¿¡ ½ÇÆÐÇϸé.. if (! m_hThreadWatchComm) { //--> ¿­¸° Æ÷Æ®¸¦ ´Ý°í.. ClosePort(); return FALSE; } check = FALSE; return TRUE; } // Æ÷Æ®¸¦ ´Ý´Â´Ù. void CCommThread::ClosePort() { //--> ¿¬°áµÇÁö ¾Ê¾ÒÀ½. m_bConnected = FALSE; //--> ¸¶½ºÅ© ÇØÁ¦.. SetCommMask( m_hComm, 0); //--> Æ÷Æ® ºñ¿ì±â. PurgeComm( m_hComm, PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR); CloseHandle(m_hComm); //--> ÇÚµé ´Ý±â } // Æ÷Æ®¿¡ pBuffÀÇ ³»¿ëÀ» nToWrite¸¸Å­ ¾´´Ù. // ½ÇÁ¦·Î ¾²¿©Áø Byte¼ö¸¦ ¸®ÅÏÇÑ´Ù. DWORD CCommThread::WriteComm(BYTE *pBuff, DWORD nToWrite) { DWORD dwWritten, dwError, dwErrorFlags; COMSTAT comstat; //--> Æ÷Æ®°¡ ¿¬°áµÇÁö ¾ÊÀº »óÅÂÀ̸é.. if( !m_bConnected ) { return 0; } //--> ÀÎÀÚ·Î µé¾î¿Â ¹öÆÛÀÇ ³»¿ëÀ» nToWrite ¸¸Å­ ¾²°í.. ¾´ °¹¼ö¸¦.,dwWrite ¿¡ ³Ñ±è. if( !WriteFile( m_hComm, pBuff, nToWrite, &dwWritten, &m_osWrite)) { //--> ¾ÆÁ÷ Àü¼ÛÇÒ ¹®ÀÚ°¡ ³²¾ÒÀ» °æ¿ì.. if (GetLastError() == ERROR_IO_PENDING) { // ÀÐÀ» ¹®ÀÚ°¡ ³²¾Æ Àְųª Àü¼ÛÇÒ ¹®ÀÚ°¡ ³²¾Æ ÀÖÀ» °æ¿ì Overapped IOÀÇ // Ư¼º¿¡ µû¶ó ERROR_IO_PENDING ¿¡·¯ ¸Þ½ÃÁö°¡ Àü´ÞµÈ´Ù. //timeouts¿¡ Á¤ÇØÁØ ½Ã°£¸¸Å­ ±â´Ù·ÁÁØ´Ù. while (! GetOverlappedResult( m_hComm, &m_osWrite, &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; } // Æ÷Æ®·ÎºÎÅÍ pBuff¿¡ nToWrite¸¸Å­ Àд´Ù. // ½ÇÁ¦·Î ÀÐÇôÁø Byte¼ö¸¦ ¸®ÅÏÇÑ´Ù. DWORD CCommThread::ReadComm(BYTE *pBuff, DWORD nToRead) { DWORD dwRead,dwError, dwErrorFlags; COMSTAT comstat; //--- system queue¿¡ µµÂøÇÑ byte¼ö¸¸ ¹Ì¸® Àд´Ù. ClearCommError( m_hComm, &dwErrorFlags, &comstat); //--> ½Ã½ºÅÛ Å¥¿¡¼­ ÀÐÀ» °Å¸®°¡ ÀÖÀ¸¸é.. dwRead = comstat.cbInQue; if(dwRead > 0) { //--> ¹öÆÛ¿¡ ÀÏ´Ü ÀоîµéÀ̴µ¥.. ¸¸ÀÏ..ÀоîµéÀΰªÀÌ ¾ø´Ù¸é.. if( !ReadFile( m_hComm, pBuff, nToRead, &dwRead, &m_osRead) ) { //--> ÀÐÀ» °Å¸®°¡ ³²¾ÒÀ¸¸é.. if (GetLastError() == ERROR_IO_PENDING) { //--------- timeouts¿¡ Á¤ÇØÁØ ½Ã°£¸¸Å­ ±â´Ù·ÁÁØ´Ù. while (! GetOverlappedResult( m_hComm, &m_osRead, &dwRead, TRUE)) { dwError = GetLastError(); if (dwError != ERROR_IO_INCOMPLETE) { ClearCommError( m_hComm, &dwErrorFlags, &comstat); break; } } } else { dwRead = 0; ClearCommError( m_hComm, &dwErrorFlags, &comstat); } } } //--> ½ÇÁ¦ ÀоîµéÀÎ °¹¼ö¸¦ ¸®ÅÏ. return dwRead; } // Æ÷Æ®¸¦ °¨½ÃÇϰí, ÀÐÈù ³»¿ëÀÌ ÀÖÀ¸¸é // m_ReadData¿¡ ÀúÀåÇÑ µÚ¿¡ MainWnd¿¡ ¸Þ½ÃÁö¸¦ º¸³»¾î BufferÀÇ ³»¿ëÀ» // Àо¶ó°í ½Å°íÇÑ´Ù. DWORD ThreadWatchComm(CCommThread* pComm) { DWORD dwEvent; OVERLAPPED os; BOOL bOk = TRUE; BYTE buff[2048]; // Àб⠹öÆÛ DWORD dwRead; // ÀÐÀº ¹ÙÀÌÆ®¼ö. // Event, OS ¼³Á¤. memset( &os, 0, sizeof(OVERLAPPED)); //--> À̺¥Æ® ¼³Á¤.. if( !(os.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL)) ) { bOk = FALSE; } //--> À̺¥Æ® ¸¶½ºÅ©.. if( !SetCommMask( pComm->m_hComm, EV_RXCHAR) ) { bOk = FALSE; } //--> À̺¥Æ®³ª..¸¶½ºÅ© ¼³Á¤¿¡ ½ÇÆÐÇÔ.. if( !bOk ) { AfxMessageBox(_T("Error while creating ThreadWatchComm, ") + pComm->m_sPortName); return FALSE; } while (pComm ->m_bConnected)//Æ÷Æ®°¡ ¿¬°áµÇ¸é ¹«ÇÑ ·çÇÁ¿¡ µé¾î°¨ { dwEvent = 0; // Æ÷Æ®¿¡ ÀÐÀ» °Å¸®°¡ ¿Ã¶§±îÁö ±â´Ù¸°´Ù. WaitCommEvent( pComm->m_hComm, &dwEvent, NULL); //--> µ¥ÀÌÅͰ¡ ¼ö½ÅµÇ¾ú´Ù´Â ¸Þ¼¼Áö°¡ ¹ß»ýÇϸé.. if ((dwEvent & EV_RXCHAR) == EV_RXCHAR) { // Æ÷Æ®¿¡¼­ ÀÐÀ» ¼ö ÀÖ´Â ¸¸Å­ Àд´Ù. //--> buff ¿¡ ¹Þ¾Æ³õ°í.. do { dwRead = pComm->ReadComm( buff, 2048); //µé¾î¿Â µ¥ÀÌÅÍ ÀÐ¾î ¿À±â if(BUFF_SIZE - pComm->m_QueueRead.GetSize() > (int)dwRead) { // for( WORD i = 0; i < dwRead; i++ ) // { // pComm->m_QueueRead.PutByte(buff[i]);//Å¥ ¹öÆÛ¿¡ µé¾î¿Â µ¥ÀÌÅÍ ³Ö±â // } pComm->m_QueueRead.PutBytes(buff,dwRead); } // else // AfxMessageBox("buff full"); //Å¥¹öÆÛÀÇ Å©±â¸¦ ÃʰúÇÏ¸é °æ°í ¸Þ½ÃÁö º¸³¿ }while(dwRead); ::PostMessage(g_hCommWnd, WM_COMM_READ, 0, 0 );//CSerialComDlg·Î µ¥ÀÌÅͰ¡ µé¾î¿Ô´Ù´Â ¸Þ½ÃÁö¸¦ º¸³¿ } Sleep(0); // ¹ÞÀº µ¥ÀÌÅ͸¦ È­¸é¿¡ º¸¿©ÁÙ ½Ã°£À» ¹ú±â À§ÇØ. // µ¥ÀÌÅ͸¦ ¿¬¼ÓÀ¸·Î ¹ÞÀ¸¸é cpuÁ¡À¯À²ÀÌ 100%°¡ µÇ¾î È­¸é¿¡ »Ñ·ÁÁÖ´Â ÀÛ¾÷ÀÌ Àß ¾ÈµÇ°í. °á°úÀûÀ¸·Î // Å¥ ¹öÆÛ¿¡ µ¥ÀÌÅͰ¡ ½×ÀÌ°Ô µÊ } CloseHandle( os.hEvent); //--> ¾²·¹µå Á¾·á°¡ µÇ°ÚÁÒ? pComm->m_hThreadWatchComm = NULL; return TRUE; }