📄 bcb_n9.htm
字号:
<html>
<head>
<title>用BuilderC++如何对串行口COM1或COM2进行读写操作</title>
<meta http-equiv="目录类型" content="文本/html; 字符集=gb2312">
</head>
<body bgcolor="#FFFFFF">
<table width="100%" border="0" height="285">
<tr>
<td height="35">
<div align="center" class="p14"><font color="#000000">用Builder C++如何对串行口COM1或COM2进行读写操作</font></div>
</td>
</tr>
<tr valign="top">
<td>一个通讯类(对串口的读写),可以不用做修改就用在程序中 <br>
<br>
TSerialPort.h <br>
<br>
#ifndef __SERIALPORT_H__ <br>
#define __SERIALPORT_H__ <br>
<br>
#define WM_COMM_BREAK_DETECTED WM_USER+1 // A break was detected on input.
<br>
#define WM_COMM_CTS_DETECTED WM_USER+2 // The CTS (clear-to-sennd) sig <br>
nal changed state. <br>
#define WM_COMM_DSR_DETECTED WM_USER+3 // The DSR (data-set-reaady) si <br>
gnal changed state. <br>
#define WM_COMM_ERR_DETECTED WM_USER+4 // A line-status error ooccurre <br>
d. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. <br>
<br>
#define WM_COMM_RING_DETECTED WM_USER+5 // A ring indicator was etec ted.
<br>
#define WM_COMM_RLSD_DETECTED WM_USER+6 // The RLSD (receive-lin <br>
-sig <br>
nal-detect) signal changed state. <br>
#define WM_COMM_RXCHAR WM_USER+7 // A character w <br>
s received and pl <br>
aced in the input buffer. <br>
#define WM_COMM_RXFLAG_DETECTED WM_USER+8 // The event character w <br>
s <br>
received and placed in the input buffer. <br>
#define WM_COMM_TXEMPTY_DETECTED WM_USER+9 // The last character in <br>
th <br>
e output buffer was sent. <br>
<br>
class TSerialPort <br>
{ <br>
public: <br>
// contruction and destruction <br>
TSerialPort(); <br>
virtual ~TSerialPort(); <br>
<br>
// port initialisation <br>
BOOL InitPort(TForm* pPortOwner, UINT portnr = 1, UINT baud = <br>
19200, <br>
char parity = 'N', UINT databits = 8, UINT stopsbits = 1, DWORD dwCom <br>
mEvents = EV_RXCHAR | EV_CTS, UINT nBufferSize = 512); <br>
<br>
// start/stop comm watching <br>
BOOL StartMonitoring(); <br>
BOOL RestartMonitoring(); <br>
BOOL StopMonitoring(); <br>
<br>
DWORD GetWriteBufferSize(); <br>
DWORD GetCommEvents(); <br>
DCB GetDCB(); <br>
<br>
void WriteToPort(char* string); <br>
<br>
protected: <br>
// protected memberfunctions <br>
void ProcessErrorMessage(char* ErrorText); <br>
static DWORD _stdcall CommThread(LPVOID pParam); <br>
static void ReceiveChar(TSerialPort* port, COMSTAT comstat); <br>
static void WriteChar(TSerialPort* port); <br>
<br>
// thread <br>
HANDLE m_HThread; <br>
<br>
// synchronisation objects <br>
CRITICAL_SECTION m_csCommunicationSync; <br>
BOOL m_bThreadAlive; <br>
<br>
// handles <br>
HANDLE m_hShutdownEvent; <br>
HANDLE m_hComm; <br>
HANDLE m_hWriteEvent; <br>
<br>
// Event array. <br>
// One element is used for each event. There are two event handles fo <br>
r each port. <br>
// A Write event and a receive character event which is located in th <br>
e overlapped structure (m_ov.hEvent). <br>
// There is a general shutdown when the port is closed. <br>
HANDLE m_hEventArray[3]; <br>
<br>
// structures <br>
OVERLAPPED m_ov; <br>
COMMTIMEOUTS m_CommTimeouts; <br>
DCB m_dcb; <br>
<br>
// owner window <br>
TForm* m_pOwner; <br>
<br>
// misc <br>
UINT m_nPortNr; <br>
char* m_szWriteBuffer; <br>
DWORD m_dwCommEvents; <br>
DWORD m_nWriteBufferSize; <br>
}; <br>
<br>
#endif __SERIALPORT_H__ <br>
<br>
<br>
TSerialPort.cpp <br>
<br>
#include <br>
#pragma hdrstop <br>
#include "SerialPort.h" <br>
#include <br>
#include <br>
#pragma package(smart_init) <br>
// <br>
// Constructor <br>
// <br>
TSerialPort::TSerialPort() <br>
{ <br>
m_hComm = NULL; <br>
<br>
// initialize overlapped structure members to zero <br>
m_ov.Offset = 0; <br>
m_ov.OffsetHigh = 0; <br>
<br>
// create events <br>
m_ov.hEvent = NULL; <br>
m_hWriteEvent = NULL; <br>
m_hShutdownEvent = NULL; <br>
<br>
m_szWriteBuffer = NULL; <br>
<br>
m_bThreadAlive = false; <br>
} <br>
<br>
// <br>
// Delete dynamic memory <br>
// <br>
TSerialPort::~TSerialPort() <br>
{ <br>
do <br>
{ <br>
SetEvent(m_hShutdownEvent); <br>
} while (m_bThreadAlive); <br>
<br>
delete [] m_szWriteBuffer; <br>
} <br>
<br>
// <br>
// Initialize the port. This can be port 1 to 4. <br>
// <br>
BOOL TSerialPort::InitPort(TForm* pPortOwner, // the owner (CWnd) of t <br>
he port (receives message) <br>
UINT portnr, <br>
/ portnumber (1..4) <br>
UINT baud, <br>
/ baudrate <br>
char parity, <br>
/ parity <br>
UINT databits, <br>
/ databits <br>
UINT stopbits, <br>
/ stopbits <br>
DWORD dwCommEvents, // EV_RX <br>
HAR, EV_CTS etc <br>
UINT writebuffersize) <br>
/ size to the writebuffer <br>
{ <br>
assert(portnr > 0 && portnr < 5); <br>
assert(pPortOwner != NULL); <br>
<br>
// if the thread is alive: Kill <br>
if (m_bThreadAlive) <br>
{ <br>
do <br>
{ <br>
SetEvent(m_hShutdownEvent); <br>
} while (m_bThreadAlive); <br>
} <br>
<br>
// create events <br>
if (m_ov.hEvent != NULL) <br>
ResetEvent(m_ov.hEvent); <br>
m_ov.hEvent = CreateEvent(NULL, true, false, NULL); <br>
<br>
if (m_hWriteEvent != NULL) <br>
ResetEvent(m_hWriteEvent); <br>
m_hWriteEvent = CreateEvent(NULL, true, false, NULL); <br>
<br>
if (m_hShutdownEvent != NULL) <br>
ResetEvent(m_hShutdownEvent); <br>
m_hShutdownEvent = CreateEvent(NULL, true, false, NULL); <br>
<br>
// initialize the event objects <br>
m_hEventArray[0] = m_hShutdownEvent; // highest priority <br>
m_hEventArray[1] = m_ov.hEvent; <br>
m_hEventArray[2] = m_hWriteEvent; <br>
<br>
// initialize critical section <br>
InitializeCriticalSection(&m_csCommunicationSync); <br>
<br>
// set buffersize for writing and save the owner <br>
m_pOwner = pPortOwner; <br>
<br>
if (m_szWriteBuffer != NULL) <br>
delete [] m_szWriteBuffer; <br>
m_szWriteBuffer = new char[writebuffersize]; <br>
<br>
m_nPortNr = portnr; <br>
<br>
m_nWriteBufferSize = writebuffersize; <br>
m_dwCommEvents = dwCommEvents; <br>
<br>
BOOL bResult = false; <br>
char *szPort = new char[50]; <br>
char *szBaud = new char[50]; <br>
<br>
// now it critical! <br>
EnterCriticalSection(&m_csCommunicationSync); <br>
<br>
// if the port is already opened: close it <br>
if (m_hComm != NULL) <br>
{ <br>
CloseHandle(m_hComm); <br>
m_hComm = NULL; <br>
} <br>
<br>
// prepare port strings <br>
sprintf(szPort, "COM%d", portnr); <br>
sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, da <br>
tabits, stopbits); <br>
<br>
// get a handle to the port <br>
m_hComm = CreateFile(szPort, <br>
/ communication port string (COMX) <br>
<br>
GENERIC_READ | GENERIC_WRITE, <br>
/ read/write types <br>
0, <br>
/ comm devices must be opened with exclusive acce <br>
ss <br>
ss <br>
NULL, <br>
/ no security attributes <br>
OPEN_EXISTING, <br>
/ comm devices must use OPEN_EXISTING <br>
FILE_FLAG_OVERLAPPED, <br>
/ Async I/O <br>
0); <br>
/ template must be 0 for comm devices <br>
<br>
if (m_hComm == INVALID_HANDLE_VALUE) <br>
{ <br>
// port not found <br>
delete [] szPort; <br>
delete [] szBaud; <br>
<br>
return false; <br>
} <br>
<br>
// set the timeout values <br>
m_CommTimeouts.ReadIntervalTimeout = 1000; <br>
m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000; <br>
m_CommTimeouts.ReadTotalTimeoutConstant = 1000; <br>
m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; <br>
m_CommTimeouts.WriteTotalTimeoutConstant = 1000; <br>
<br>
// configure <br>
if (SetCommTimeouts(m_hComm, &m_CommTimeouts)) <br>
{ <br>
if (SetCommMask(m_hComm, dwCommEvents)) <br>
{ <br>
if (GetCommState(m_hComm, &m_dcb)) <br>
{ <br>
m_dcb.fRtsControl = RTS_CONTROL_ENABLE; <br>
/ set RTS bit high! <br>
if (BuildCommDCB(szBaud, &m_dcb)) <br>
{ <br>
if (SetCommState(m_hComm, &m_dcb)) <br>
; // normal operation... continu <br>
<br>
else <br>
ProcessErrorMessage("SetCommStat <br>
()"); <br>
} <br>
else <br>
ProcessErrorMessage("BuildCommDCB()"); <br>
} <br>
else <br>
ProcessErrorMessage("GetCommState()"); <br>
} <br>
else <br>
ProcessErrorMessage("SetCommMask()"); <br>
} <br>
else <br>
ProcessErrorMessage("SetCommTimeouts()"); <br>
<br>
delete [] szPort; <br>
delete [] szBaud; <br>
<br>
// flush the port <br>
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PU <br>
RGE_TXABORT); <br>
<br>
// release critical section <br>
LeaveCriticalSection(&m_csCommunicationSync); <br>
<br>
return true; <br>
} <br>
<br>
// <br>
// The CommThread Function. <br>
// <br>
DWORD _stdcall TSerialPort::CommThread(LPVOID pParam) <br>
{ <br>
// Cast the void pointer passed to the thread back to <br>
// a pointer of TSerialPort class <br>
TSerialPort *port = (TSerialPort*)pParam; <br>
<br>
// Set the status variable in the dialog class to <br>
// TRUE to indicate the thread is running. <br>
port->m_bThreadAlive = true; <br>
<br>
// Misc. variables <br>
DWORD BytesTransfered = 0; <br>
DWORD Event = 0; <br>
DWORD CommEvent = 0; <br>
DWORD dwError = 0; <br>
COMSTAT comstat; <br>
BOOL bResult = true; <br>
<br>
// Clear comm buffers at startup <br>
if (port->m_hComm) // check if the port is opened <br>
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_R <br>
ABO <br>
RT | PURGE_TXABORT); <br>
<br>
// begin forever loop. This loop will run as long as the thread is a <br>
live. <br>
for (;;) <br>
{ <br>
<br>
// Make a call to WaitCommEvent(). This call will return immedi <br>
tly <br>
<br>
// because our port was created as an async port (FILE_FLAG_OVER <br>
APP <br>
ED <br>
// and an m_OverlappedStructerlapped structure specified). This <br>
cal <br>
l will cause the <br>
// m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, <br>
whi <br>
ch is part of the m_hEventArray to <br>
// be placed in a non-signeled state if there are no bytes avail <br>
ble <br>
to be read, <br>
// or to a signeled state if there are bytes available. If this <br>
eve <br>
nt handle <br>
// is set to the non-signeled state, it will be set to signeled <br>
hen <br>
a <br>
// character arrives at the port. <br>
<br>
// we do this for each port! <br>
<br>
bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);
<br>
<br>
if (!bResult) <br>
{ <br>
// If WaitCommEvent() returns FALSE, process the last er <br>
or to dete <br>
rmin <br>
rmin <br>
// the reason.. <br>
switch (dwError = GetLastError()) <br>
{ <br>
case ERROR_IO_PENDING: <br>
{ <br>
// This is a normal return value if ther <br>
are no bytes <br>
// to read at the port. <br>
// Do nothing and continue <br>
break; <br>
} <br>
case 87: <br>
{ <br>
// Under Windows NT, this value is retur <br>
ed for some reason. <br>
// I have not investigated why, but it i <br>
also a valid reply <br>
// Also do nothing and continue. <br>
break; <br>
} <br>
default: <br>
{ <br>
// All other error codes indicate a seri <br>
us error has <br>
// occured. Process this error. <br>
port->ProcessErrorMessage("WaitCommEvent <br>
)"); <br>
break; <br>
} <br>
} <br>
} <br>
else <br>
{ <br>
// If WaitCommEvent() returns TRUE, check to be sure the <br>
e are <br>
// actually bytes in the buffer to read. <br>
// <br>
// If you are reading more than one byte at a time from <br>
he buffer <br>
<br>
// (which this program does not do) you will have the si <br>
uation occ <br>
ur <br>
// where the first byte to arrive will cause the WaitFor <br>
ultipleObj <br>
ects() <br>
// function to stop waiting. The WaitForMultipleObjects <br>
) function <br>
<br>
// resets the event handle in m_OverlappedStruct.hEvent <br>
o the non- <br>
signelead state <br>
// as it returns. <br>
// <br>
// If in the time between the reset of this event and th <br>
call to <br>
// ReadFile() more bytes arrive, the m_OverlappedStruct. <br>
Event hand <br>
le will be set again <br>
// to the signeled state. When the call to ReadFile() oc <br>
urs, it wi <br>
ll <br>
// read all of the bytes from the buffer, and the progra <br>
will <br>
// loop back around to WaitCommEvent(). <br>
// <br>
// At this point you will be in the situation where m_Ov <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -