⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 5.cb_com.cpp

📁 C++Builder对串行口进行读写操作的一个通讯类
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -