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