📄 bcb_n9.htm
字号:
rlappedStr <br>
uct.hEvent is set, <br>
// but there are no bytes available to read. If you pro <br>
eed and ca <br>
ll <br>
// ReadFile(), it will return immediatly due to the asyn <br>
port setu <br>
p, but <br>
// GetOverlappedResults() will not return until the next <br>
character <br>
arrives. <br>
// <br>
// It is not desirable for the GetOverlappedResults() fu <br>
ction to b <br>
e in <br>
// this state. The thread shutdown event (event 0) and <br>
he WriteFi <br>
le() <br>
// event (Event2) will not work if the thread is blocked <br>
by GetOver <br>
lappedResults(). <br>
// <br>
// The solution to this is to check the buffer with a ca <br>
l to Clear <br>
CommError(). <br>
// This call will reset the event handle, and if there a <br>
e no bytes <br>
to read <br>
// we can loop back through WaitCommEvent() again, then <br>
roceed. <br>
// If there are really bytes to read, do nothing and pro <br>
eed. <br>
<br>
bResult = ClearCommError(port->m_hComm, &dwError, &comst <br>
t); <br>
<br>
if (comstat.cbInQue == 0) <br>
continue; <br>
} // end if bResult <br>
<br>
// Main wait function. This function will normally block the th <br>
ead <br>
<br>
<br>
// until one of nine events occur that require action. <br>
Event = WaitForMultipleObjects(3, port->m_hEventArray, false, IN <br>
INI <br>
TE); <br>
<br>
switch (Event) <br>
{ <br>
case 0: <br>
{ <br>
// Shutdown event. This is event zero so it wil <br>
be <br>
// the higest priority and be serviced first. <br>
<br>
port->m_bThreadAlive = false; <br>
<br>
// Kill this thread. break is not needed, but m <br>
kes me feel bette <br>
r. <br>
ExitThread(100); <br>
break; <br>
} <br>
case 1: // read event <br>
{ <br>
GetCommMask(port->m_hComm, &CommEvent); <br>
if (CommEvent & EV_CTS) <br>
::SendMessage(port->m_pOwner->Handle, WM <br>
COMM_CTS_DETECTED, (WPAR <br>
AM) 0, (LPARAM) port->m_nPortNr); <br>
if (CommEvent & EV_RXFLAG) <br>
::SendMessage(port->m_pOwner->Handle, WM <br>
COMM_RXFLAG_DETECTED, (W <br>
PARAM) 0, (LPARAM) port->m_nPortNr); <br>
if (CommEvent & EV_BREAK) <br>
::SendMessage(port->m_pOwner->Handle, WM <br>
COMM_BREAK_DETECTED, (WP <br>
ARAM) 0, (LPARAM) port->m_nPortNr); <br>
if (CommEvent & EV_ERR) <br>
::SendMessage(port->m_pOwner->Handle, WM <br>
COMM_ERR_DETECTED, (WPAR <br>
AM) 0, (LPARAM) port->m_nPortNr); <br>
if (CommEvent & EV_RING) <br>
::SendMessage(port->m_pOwner->Handle, WM <br>
COMM_RING_DETECTED, (WPA <br>
RAM) 0, (LPARAM) port->m_nPortNr); <br>
<br>
if (CommEvent & EV_RXCHAR) <br>
// Receive character event from port. <br>
ReceiveChar(port, comstat); <br>
<br>
break; <br>
} <br>
case 2: // write event <br>
{ <br>
// Write character event from port <br>
WriteChar(port); <br>
break; <br>
} <br>
<br>
} // end switch <br>
<br>
} // close forever loop <br>
<br>
return 0; <br>
} <br>
<br>
// <br>
// <br>
// start comm watching <br>
// <br>
BOOL TSerialPort::StartMonitoring() <br>
{ <br>
DWORD lpThreadId; <br>
m_HThread =CreateThread(NULL, <br>
0, <br>
CommThread, <br>
this, <br>
0, <br>
&lpThreadId); <br>
if(m_HThread==NULL) <br>
{ <br>
ProcessErrorMessage("Create Thread Error"); <br>
return false; <br>
} <br>
return true; <br>
} <br>
<br>
// <br>
// Restart the comm thread <br>
// <br>
// <br>
BOOL TSerialPort::RestartMonitoring() <br>
{ <br>
ResumeThread(m_HThread); <br>
return true; <br>
} <br>
<br>
// <br>
// Suspend the comm thread <br>
// <br>
BOOL TSerialPort::StopMonitoring() <br>
{ <br>
SuspendThread(m_HThread); <br>
return true; <br>
} <br>
<br>
// <br>
// If there is a error, give the right message <br>
// <br>
void TSerialPort::ProcessErrorMessage(char* ErrorText) <br>
{ <br>
char *Temp = new char[200]; <br>
<br>
<br>
LPVOID lpMsgBuf; <br>
<br>
FormatMessage( <br>
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, <br>
NULL, <br>
GetLastError(), <br>
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language <br>
(LPTSTR) &lpMsgBuf, <br>
0, <br>
NULL <br>
); <br>
<br>
sprintf(Temp, "WARNING: %s Failed with the following error: \n%s\nPo <br>
rt: %d\n", (char*)ErrorText, lpMsgBuf, m_nPortNr); <br>
Application->MessageBox(Temp, "Application Error", MB_ICONSTOP); <br>
<br>
LocalFree(lpMsgBuf); <br>
delete[] Temp; <br>
} <br>
<br>
// <br>
// Write a character. <br>
// <br>
void TSerialPort::WriteChar(TSerialPort* port) <br>
{ <br>
BOOL bWrite = true; <br>
BOOL bResult = true; <br>
<br>
DWORD BytesSent = 0; <br>
<br>
ResetEvent(port->m_hWriteEvent); <br>
<br>
// Gain ownership of the critical section <br>
EnterCriticalSection(&port->m_csCommunicationSync); <br>
<br>
if (bWrite) <br>
{ <br>
// Initailize variables <br>
port->m_ov.Offset = 0; <br>
port->m_ov.OffsetHigh = 0; <br>
<br>
// Clear buffer <br>
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_R <br>
ABO <br>
ABO <br>
RT | PURGE_TXABORT); <br>
<br>
bResult = WriteFile(port->m_hComm, <br>
/ Handle to COMM Port <br>
port->m_szWriteBuffer, / <br>
/ Pointer to message buffer in call <br>
ing finction <br>
strlen((char*)port->m_sz <br>
riteBuffer), // Length of message to s <br>
end <br>
&BytesSent, <br>
/ Where to store the number of bytes sent <br>
&port->m_ov); <br>
/ Overlapped structure <br>
<br>
// deal with any error codes <br>
if (!bResult) <br>
{ <br>
DWORD dwError = GetLastError(); <br>
switch (dwError) <br>
{ <br>
case ERROR_IO_PENDING: <br>
{ <br>
// continue to GetOverlappedResu <br>
ts() <br>
BytesSent = 0; <br>
bWrite = false; <br>
break; <br>
} <br>
default: <br>
{ <br>
// all other error codes <br>
port->ProcessErrorMessage("Write <br>
ile()"); <br>
} <br>
} <br>
} <br>
else <br>
{ <br>
LeaveCriticalSection(&port->m_csCommunicationSync); <br>
} <br>
} // end if(bWrite) <br>
<br>
if (!bWrite) <br>
{ <br>
bWrite = true; <br>
<br>
bResult = GetOverlappedResult(port->m_hComm, // Handle to COM <br>
port <br>
<br>
&port- <br>
m_ov, // Overlapped structure <br>
&Bytes <br>
ent, // Stores number of bytes sent <br>
true); <br>
// Wait flag <br>
<br>
LeaveCriticalSection(&port->m_csCommunicationSync); <br>
<br>
// deal with the error code <br>
if (!bResult) <br>
{ <br>
port->ProcessErrorMessage("GetOverlappedResults() in Wri <br>
eFile()"); <br>
<br>
} <br>
} // end if (!bWrite) <br>
<br>
// Verify that the data size send equals what we tried to send <br>
if (BytesSent != strlen((char*)port->m_szWriteBuffer)) <br>
{ <br>
printf("WARNING: WriteFile() error.. Bytes Sent: %d; Message Len <br>
th: <br>
%d\n", BytesSent, strlen((char*)port->m_szWriteBuffer)); <br>
} <br>
} <br>
<br>
// <br>
// Character received. Inform the owner <br>
// <br>
void TSerialPort::ReceiveChar(TSerialPort* port, COMSTAT comstat) <br>
{ <br>
BOOL bRead = true; <br>
BOOL bResult = true; <br>
DWORD dwError = 0; <br>
DWORD BytesRead = 0; <br>
unsigned char RXBuff; <br>
<br>
<br>
for (;;) <br>
{ <br>
// Gain ownership of the comm port critical section. <br>
// This process guarantees no other part of this program <br>
// is using the port object. <br>
<br>
EnterCriticalSection(&port->m_csCommunicationSync); <br>
<br>
// ClearCommError() will update the COMSTAT structure and <br>
// clear any other errors. <br>
<br>
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
<br>
<br>
LeaveCriticalSection(&port->m_csCommunicationSync); <br>
<br>
// start forever loop. I use this type of loop because I <br>
// do not know at runtime how many loops this will have to <br>
// run. My solution is to start a forever loop and to <br>
// break out of it when I have processed all of the <br>
// data available. Be careful with this approach and <br>
// be sure your loop will exit. <br>
// My reasons for this are not as clear in this sample <br>
// as it is in my production code, but I have found this <br>
// solutiion to be the most efficient way to do this. <br>
<br>
if (comstat.cbInQue == 0) <br>
{ <br>
// break out when all bytes have been read <br>
break; <br>
} <br>
<br>
EnterCriticalSection(&port->m_csCommunicationSync); <br>
<br>
if (bRead) <br>
{ <br>
bResult = ReadFile(port->m_hComm, // Handl <br>
to COMM port <br>
&RXBuff, <br>
/ RX Buffer Pointer <br>
1, <br>
/ Read one byte <br>
&BytesRead, <br>
/ Stores number of bytes read <br>
&port->m_ov); <br>
/ pointer to the m_ov structure <br>
// deal with the error code <br>
if (!bResult) <br>
{ <br>
switch (dwError = GetLastError()) <br>
{ <br>
case ERROR_IO_PENDING: <br>
{ <br>
// asynchronous i/o is s <br>
ill in progress <br>
// Proceed on to GetOver <br>
appedResults(); <br>
bRead = false; <br>
break; <br>
} <br>
default: <br>
{ <br>
// Another error has occ <br>
red. Process this error. <br>
port->ProcessErrorMessag <br>
("ReadFile()"); <br>
break; <br>
} <br>
} <br>
} <br>
else <br>
{ <br>
// ReadFile() returned complete. It is not neces <br>
ary to call GetOv <br>
erlappedResults() <br>
bRead = true; <br>
} <br>
} // close if (bRead) <br>
<br>
if (!bRead) <br>
{ <br>
bRead = true; <br>
bResult = GetOverlappedResult(port->m_hComm, // Handl <br>
to COMM port <br>
<br>
<br>
&port->m_ov, // Overlapped structure <br>
<br>
&BytesRead, // Stores number of bytes read <br>
<br>
true); // Wait flag <br>
<br>
// deal with the error code <br>
if (!bResult) <br>
{ <br>
port->ProcessErrorMessage("GetOverlappedResults( <br>
in ReadFile()"); <br>
<br>
} <br>
} // close if (!bRead) <br>
<br>
LeaveCriticalSection(&port->m_csCommunicationSync); <br>
<br>
// notify parent that a byte was received <br>
::SendMessage((port->m_pOwner)->Handle, WM_COMM_RXCHAR, (WPARAM) <br>
RXB <br>
uff, (LPARAM) port->m_nPortNr); <br>
} // end forever loop <br>
<br>
} <br>
<br>
<br>
// <br>
// Write a string to the port <br>
// <br>
void TSerialPort::WriteToPort(char* string) <br>
{ <br>
assert(m_hComm != 0); <br>
<br>
memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer)); <br>
strcpy(m_szWriteBuffer, string); <br>
<br>
// set event for write <br>
SetEvent(m_hWriteEvent); <br>
} <br>
<br>
// <br>
// Return the device control block <br>
// <br>
DCB TSerialPort::GetDCB() <br>
{ <br>
return m_dcb; <br>
} <br>
<br>
<br>
// <br>
// Return the communication event masks <br>
// <br>
DWORD TSerialPort::GetCommEvents() <br>
{ <br>
return m_dwCommEvents; <br>
} <br>
<br>
// <br>
// Return the output buffer size <br>
// <br>
DWORD TSerialPort::GetWriteBufferSize() <br>
{ <br>
return m_nWriteBufferSize; <br>
} <br>
<br>
//----------------------------------------------------------------<br>
</td>
</tr>
</table>
<br>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -