📄 21.htm
字号:
<table border="0" width="640">
<tr><td align="center"><b>用Builder C++如何对串行口COM1或COM2进行读写操作</b></td></tr>
<tr><td align="center"><font color="#CC9933"></font></td></tr>
<tr><td> 一个通讯类(对串口的读写),可以不用做修改就用在程序中<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>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>//----------------------------------------------------------------</td></tr>
</table></center></div>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -