📄 serialport.cpp
字号:
{
// Write character event from port
WriteChar(port);
ClearCommError(port->m_hComm, &dwError, &comstat);
CommErrorProc(port->m_pOwner->m_hWnd, dwError, (LPARAM)port->m_nPortNr, FALSE);
break;
}
case 3: // OpenComm Event
break;
case 4: // CloseComm Event
break;
} // end switch
} // close forever loop
return 0;
}
//
// start comm watching
//
BOOL CSerialPort::StartMonitoring()
{
if (!(m_Thread = AfxBeginThread(CommThread, this)))
return FALSE;
m_bThreadRunning = TRUE;
TRACE("Thread started\n");
return TRUE;
}
//
// Restart the comm thread
//
BOOL CSerialPort::RestartMonitoring()
{
TRACE("Thread resumed\n");
m_bThreadRunning = TRUE;
if(m_Thread)
m_Thread->ResumeThread();
return TRUE;
}
//
// Suspend the comm thread
//
BOOL CSerialPort::StopMonitoring()
{
TRACE("Thread suspended\n");
m_bThreadRunning = FALSE;
if(m_Thread)
m_Thread->SuspendThread();
return TRUE;
}
//
// If there is a error, give the right message
//
void CSerialPort::ProcessErrorMessage(char* ErrorText)
{
char *Temp = new char[200];
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_CHINESE, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
sprintf(Temp, "WARNING: %s Failed with the following error: \n%s\nPort: %d\n", (char*)ErrorText, lpMsgBuf, m_nPortNr);
MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP);
LocalFree(lpMsgBuf);
delete[] Temp;
}
//
// Write a character.
//
void CSerialPort::WriteChar(CSerialPort* port)
{
BOOL bWrite = TRUE;
BOOL bResult = TRUE;
DWORD BytesSent = 0;
ResetEvent(port->m_hWriteEvent);
// 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);
#ifndef _COMSEND_HEX
bResult = WriteFile(port->m_hComm, // Handle to COMM Port
port->m_szWriteBuffer, // Pointer to message buffer in calling finction
strlen((char*)port->m_szWriteBuffer), // Length of message to send
&BytesSent, // Where to store the number of bytes sent
&port->m_ov); // Overlapped structure
#else
bResult = WriteFile(port->m_hComm, // Handle to COMM Port
port->m_comWriteBuffer.sendBuf, // Pointer to message buffer in calling finction
port->m_comWriteBuffer.nSizeBuf, // Length of message to send
&BytesSent, // Where to store the number of bytes sent
&port->m_ov); // Overlapped structure
#endif
// deal with any error codes
if (!bResult)
{
DWORD dwError = GetLastError();
switch (dwError)
{
case ERROR_IO_PENDING:
{
// continue to GetOverlappedResults()
BytesSent = 0;
bWrite = FALSE;
break;
}
default:
{
// all other error codes
port->ProcessErrorMessage("WriteFile()");
}
}
}
else
{
LeaveCriticalSection(&port->m_csCommunicationSync);
}
} // end if(bWrite)
if (!bWrite)
{
bWrite = TRUE;
bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port
&port->m_ov, // Overlapped structure
&BytesSent, // Stores number of bytes sent
TRUE); // Wait flag
LeaveCriticalSection(&port->m_csCommunicationSync);
// deal with the error code
if (!bResult)
{
port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");
}
} // end if (!bWrite)
// Verify that the data size send equals what we tried to send
#ifndef _COMSEND_HEX
if (BytesSent != strlen((char*)port->m_szWriteBuffer))
{
TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent,\
strlen((char*)port->m_szWriteBuffer));
}
#else
if (BytesSent != port->m_comWriteBuffer.nSizeBuf)
{
TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent,\
port->m_comWriteBuffer.nSizeBuf);
}
#endif
}
//
// Character received. Inform the owner
//
void CSerialPort::ReceiveChar(CSerialPort* port, COMSTAT comstat)
{
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
unsigned char RXBuff;
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_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);
} // end forever loop
}
//
// Write a string to the port
//
void CSerialPort::WriteToPort(void* string, ULONG nCount)
{
assert(m_hComm != 0);
#ifndef _COMSEND_HEX
memset(m_szWriteBuffer, 0, sizeof(BYTE) * m_nWriteBufferSize);
strcpy(m_szWriteBuffer, (BYTE*)string);
#else
#ifndef _USE_DEFAULT_BUFSIZ
if(!m_comWriteBuffer.sendBuf)
delete [] m_comWriteBuffer.sendBuf;
ULONG nSendCount = nCount > m_nWriteBufferSize ? m_nWriteBufferSize : nCount;
m_comWriteBuffer.sendBuf = new BYTE[nSendCount];
memset(m_comWriteBuffer.sendBuf, 0x00, sizeof(BYTE) * nSendCount);
memcpy(m_comWriteBuffer.sendBuf, string, sizeof(BYTE) * nSendCount);
#else
ULONG nSendCount = nCount > m_nWriteBufferSize ? m_nWriteBufferSize : nCount;
m_comWriteBuffer.nSizeBuf = nSendCount;
memset(m_comWriteBuffer.sendBuf, 0x00, sizeof(BYTE) * nSendCount);
memcpy(m_comWriteBuffer.sendBuf, string, sizeof(BYTE) * nSendCount);
#endif
#endif
// set event for write
SetEvent(m_hWriteEvent);
}
//
// Return the device control block
//
DCB CSerialPort::GetDCB()
{
return m_dcb;
}
//
// Return the communication event masks
//
DWORD CSerialPort::GetCommEvents()
{
return m_dwCommEvents;
}
//
// Return the output buffer size
//
DWORD CSerialPort::GetWriteBufferSize()
{
return m_nWriteBufferSize;
}
void CSerialPort::CommErrorProc(HWND hRcvWnd, DWORD dwErrorCode, LPARAM dwPortNum, BOOL bRead)
{
ComErrorState comerrorstate;
if(bRead)
comerrorstate.enWhile = COMERRSTATE_READ;
else
comerrorstate.enWhile = COMERRORSTATE_WRITE;
if(dwErrorCode & CE_RXOVER)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_RXOVER;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_OVERRUN)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_OVERRUN;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_RXPARITY)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_RXPARITY;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_FRAME)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_FRAME;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_BREAK)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_BREAK;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_TXFULL)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_TXFULL;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_PTO)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_PTO;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_IOE)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_IO;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_DNS)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_DNS;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_OOP)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_OOP;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & CE_MODE)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_MODE;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & IE_BADID)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_BADID;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & IE_NOPEN)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_NOPEN;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & IE_MEMORY)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_MEMORY;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & IE_DEFAULT)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_DEFAULT;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & IE_HARDWARE)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_HARDWARE;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & IE_BYTESIZE)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_ERR_BYTESIZE;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
if(dwErrorCode & IE_BAUDRATE)
{
comerrorstate.dwErrFlag = (WPARAM)COMM_BAUDRATE;
::SendMessage(hRcvWnd, WM_COMM_ERROR, (WPARAM)&comerrorstate, dwPortNum);
}
}
#ifdef _COMSEND_HEX
#undef _COMSEND_HEX
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -