📄 serialport.cpp
字号:
);
Temp.Format(_T("WARNING: %s Failed with the following error: \n%s\nPort: %d\n"), ErrorText, lpMsgBuf, m_nPortNr);
MessageBox(NULL, Temp, _T("Application Error"), MB_ICONSTOP);
LocalFree(lpMsgBuf);
}
//
// Character received. Inform the owner
//
void CSerialPortEx::ReceiveChar(CSerialPortEx* port, COMSTAT comstat)
{
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
unsigned char RXBuff=0;
for (;;)
{
// Gain ownership of the comm port critical section.
// This process guarantees no other part of this program
// is using the port object.
EnterCriticalSection(&port->m_csCommunicationSync);
// ClearCommError() will update the COMSTAT structure and
// clear any other errors.
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
LeaveCriticalSection(&port->m_csCommunicationSync);
// start forever loop. I use this type of loop because I
// do not know at runtime how many loops this will have to
// run. My solution is to start a forever loop and to
// break out of it when I have processed all of the
// data available. Be careful with this approach and
// be sure your loop will exit.
// My reasons for this are not as clear in this sample
// as it is in my production code, but I have found this
// solutiion to be the most efficient way to do this.
if (comstat.cbInQue == 0)
{
// break out when all bytes have been read
break;
}
EnterCriticalSection(&port->m_csCommunicationSync);
if (bRead)
{
bResult = ReadFile(port->m_hComm, // Handle to COMM port
&RXBuff, // RX Buffer Pointer
1, // Read one byte
&BytesRead, // Stores number of bytes read
&port->m_ov); // pointer to the m_ov structure
// deal with the error code
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// asynchronous i/o is still in progress
// Proceed on to GetOverlappedResults();
bRead = FALSE;
break;
}
default:
{
// Another error has occured. Process this error.
port->ProcessErrorMessage("ReadFile()");
break;
}
}
}
else
{
// ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
bRead = TRUE;
}
} // close if (bRead)
if (!bRead)
{
bRead = TRUE;
bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port
&port->m_ov, // Overlapped structure
&BytesRead, // Stores number of bytes read
TRUE); // Wait flag
// deal with the error code
if (!bResult)
{
port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");
}
} // close if (!bRead)
LeaveCriticalSection(&port->m_csCommunicationSync);
// notify parent that a byte was received
::SendMessage(port->m_Owner, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);
} // end forever loop
}
//
// Return the device control block
//
DCB CSerialPortEx::GetDCB()
{
return m_dcb;
}
//
// Return the communication event masks
//
DWORD CSerialPortEx::GetCommEvents()
{
return m_dwCommEvents;
}
/*
DWORD CSerialPortEx::ReadCommBlock(unsigned char *string, int nMaxLength)
{
BOOL fReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwLength;
DWORD dwError;
// only try to read number of bytes in queue
EnterCriticalSection(&m_csCommunicationSync);
dwLength = 0;
int n = 0;
while(dwLength < nMaxLength && n < 10)
{
Sleep(10);
BOOL ok=ClearCommError( m_hComm, &dwErrorFlags, &ComStat ) ;
dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;
n++;
}
if (dwLength > 0)
{
fReadStat = ReadFile(m_hComm,string,dwLength,&dwLength,&m_ov) ;
if (!fReadStat)
{
if ((dwError=GetLastError()) == ERROR_IO_PENDING)
{
;
}
else
{
// some other error occurred
dwLength = 0 ;
ClearCommError( m_hComm, &dwErrorFlags, &ComStat ) ;
}
}
}
string[dwLength] = '\0';
LeaveCriticalSection(&m_csCommunicationSync);
return dwLength ;
}
*/
DWORD CSerialPortEx::ReadCommBlock(unsigned char *string, int nMaxLength)
{
BOOL fReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwLength;
DWORD dwError;
// only try to read number of bytes in queue
EnterCriticalSection(&m_csCommunicationSync);
dwLength = 0;
int n = 0,curr = 0;;
while(dwLength < nMaxLength && n < 20)
{
Sleep(80);
BOOL ok=ClearCommError( m_hComm, &dwErrorFlags, &ComStat ) ;
dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;
n++;
if (dwLength > 0)
{
fReadStat = ReadFile(m_hComm,&string[curr],dwLength,&dwLength,&m_ov) ;
if (!fReadStat)
{
if ((dwError=GetLastError()) == ERROR_IO_PENDING)
{
continue;
}
else
{
// some other error occurred
dwLength = 0 ;
ClearCommError( m_hComm, &dwErrorFlags, &ComStat ) ;
}
}
else
{
curr += dwLength;
if(strchr((char *)string,0x03))
break;
}
}
}
string[curr] = '\0';
LeaveCriticalSection(&m_csCommunicationSync);
return curr ;
}
//Extension: not tested
BYTE* CSerialPortEx::ReadBlock(CSerialPortEx *port, int& readLen)
{
COMSTAT comstat;
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
DWORD BytesToRead=readLen;
BYTE* pRec;
// Gain ownership of the comm port critical section.
// This process guarantees no other part of this program
// is using the port object.
// ClearCommError() will update the COMSTAT structure and
// clear any other errors.
int n = 0;
do
{
Sleep(10);
EnterCriticalSection(&port->m_csCommunicationSync);
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
LeaveCriticalSection(&port->m_csCommunicationSync);
n++;
} while(comstat.cbInQue != BytesToRead && n < 10);
// start forever loop. I use this type of loop because I
// do not know at runtime how many loops this will have to
// run. My solution is to start a forever loop and to
// break out of it when I have processed all of the
// data available. Be careful with this approach and
// be sure your loop will exit.
// My reasons for this are not as clear in this sample
// as it is in my production code, but I have found this
// solutiion to be the most efficient way to do this.
if (comstat.cbInQue < BytesToRead)
{
// break out when all bytes have been read
readLen=0;
return NULL;
}
else
{
BytesToRead= BytesToRead+2 > comstat.cbInQue ? comstat.cbInQue : BytesToRead+2;
pRec=new BYTE[BytesToRead];
}
EnterCriticalSection(&port->m_csCommunicationSync);
if (bRead)
{
bResult = ReadFile(port->m_hComm, // Handle to COMM port
pRec, // Reader Buffer Pointer
BytesToRead, // to read bytes
&BytesRead, // Stores number of bytes read
&port->m_ov); // pointer to the m_ov structure
// deal with the error code
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// asynchronous i/o is still in progress
// Proceed on to GetOverlappedResults();
bRead = FALSE;
break;
}
default:
{
// Another error has occured. Process this error.
port->ProcessErrorMessage("ReadFile()");
break;
}
}
}
else
{
// ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
bRead = TRUE;
}
} // close if (bRead)
LeaveCriticalSection(&port->m_csCommunicationSync);
readLen=BytesRead;
return pRec;
// notify parent that a byte was received
// ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM)pRec, (LPARAM) BytesRead);
}
BOOL CSerialPortEx::WriteBlock(CSerialPortEx *port, BYTE* string, int nLength)
{
BOOL bWrite = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesSent = 0;
// Gain ownership of the critical section
EnterCriticalSection(&port->m_csCommunicationSync);
if (bWrite)
{
// Initailize variables
port->m_ov.Offset = 0;
port->m_ov.OffsetHigh = 0;
// Clear buffer
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
bResult = WriteFile(port->m_hComm, // Handle to COMM Port
string, // Pointer to message buffer in calling finction
nLength, // Length of message to send
&BytesSent, // Where to store the number of bytes sent
&port->m_ov); // Overlapped structure
// deal with any error codes
if (!bResult)
{
dwError = GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:
{
// continue to GetOverlappedResults()
BytesSent = 0;
bWrite = FALSE;
break;
}
default:
{
// all other error codes
port->ProcessErrorMessage("WriteFile()");
}
}
}
} // end if(bWrite)
LeaveCriticalSection(&port->m_csCommunicationSync);
if (BytesSent != nLength) return FALSE;
return TRUE;
}
BOOL CSerialPortEx::isopen()
{
return (m_hComm != NULL && m_hComm != INVALID_HANDLE_VALUE );
}
void CSerialPortEx::Close()
{
if (m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent); //关闭线程,用一个事件SetEvent() ,然后在线程内部WaitForMultipleObjects()等待此事件的产生,在线程内部调用AfxEndThread()终止线程。
Sleep(1000); //需要等待一会,然后再重新初始化,否则出错
} while (m_bThreadAlive);
TRACE("Thread ended\n");
}
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -