CSerialPort类解析
来源:互联网 发布:淘宝小卖家如何推广 编辑:程序博客网 时间:2024/05/17 04:19
CSerialPort类的功能及成员函数介绍
CSerialPort类是免费提供的串口累,Codeguru是一个非常不错的源代码网站
CSerialPort类支持线连接(非MODEM)的串口编程操作。
CSerialPort类是基于多线程的,其工作流程如下:首先设置好串口参数,再开启串口检测工作线程,串口检测工作线程检测到串口接收到的数据、流控制事件或其他串口事件后,就以消息方式通知主程序,激发消息处理函数来进行数据处理,这是对接受数据而言的,发送数据可直接向串口发送。
CSerialPort类定义的消息如表
消息名称
消息号
功能说明
WM_COMM_BREAK_DETECTED
WM_USER+1
检测到输入中断
WM_COMM_CTS_DETECTED
WM_USER+2
检测到CTS(清除发送)信号状态改变
WM_COMM_DSR_DETECTED
WM_USER+3
检测到DSR(数据设备准备就绪)信号状态改变
WM_COMM_ERR_DETECTED
WM_USER+4
发生线状态错误(包括CE_FRAME,CE_OVERRUN,和CE_RXPARITY)
WM_COMM_RING_DETECTED
WM_USER+5
检测到响铃指示信号
WM_COMM_RLSD_DETECTED
WM_USER+6
检测到RLSD(接收线信号)状态改变
WM_COMM_RXCHAR
WM_USER+7
接收到一个字符并已放入接受缓冲区
WM_COMM_RXFLAG_DETECTED
WM_USER+8
检测到接受到字符(该字符已放入接受缓冲区)事件
WM_COMM_TXEMPTY_DETECTED
WM_USER+9
检测到发送缓冲区最后一个字符已经被发送
介绍几个经常用到的函数:1、串口初始化函数InitPort
BOOL CSerialPort::InitPort(CWnd *pPortOwner, // the owner (CWnd) of the port (receives message) UINT portnr, // portnumber (1..4) UINT baud, // baudrate char parity, // parity UINT databits, // databits UINT stopbits, // stopbits DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc UINT writebuffersize) // size to the writebuffer { assert(portnr > 0 && portnr < 5); assert(pPortOwner != NULL); // if the thread is alive: Kill if (m_bThreadAlive) { do { SetEvent(m_hShutdownEvent); } while (m_bThreadAlive); TRACE("Thread ended\n"); } // create events if (m_ov.hEvent != NULL) ResetEvent(m_ov.hEvent); m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hWriteEvent != NULL) ResetEvent(m_hWriteEvent); m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hShutdownEvent != NULL) ResetEvent(m_hShutdownEvent); m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // initialize the event objects m_hEventArray[0] = m_hShutdownEvent; // highest priority m_hEventArray[1] = m_ov.hEvent; m_hEventArray[2] = m_hWriteEvent; // initialize critical section InitializeCriticalSection(&m_csCommunicationSync); // set buffersize for writing and save the owner m_pOwner = pPortOwner; if (m_szWriteBuffer != NULL) delete [] m_szWriteBuffer; m_szWriteBuffer = new char[writebuffersize]; m_nPortNr = portnr; m_nWriteBufferSize = writebuffersize; m_dwCommEvents = dwCommEvents; BOOL bResult = FALSE; char *szPort = new char[50]; char *szBaud = new char[50]; // now it critical! EnterCriticalSection(&m_csCommunicationSync); // if the port is already opened: close it if (m_hComm != NULL) { CloseHandle(m_hComm); m_hComm = NULL; } // prepare port strings sprintf(szPort, "COM%d", portnr); sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits); // get a handle to the port m_hComm = CreateFile(szPort, // communication port string (COMX) GENERIC_READ | GENERIC_WRITE, // read/write types 0, // comm devices must be opened with exclusive access NULL, // no security attributes OPEN_EXISTING, // comm devices must use OPEN_EXISTING FILE_FLAG_OVERLAPPED, // Async I/O 0); // template must be 0 for comm devices if (m_hComm == INVALID_HANDLE_VALUE) { // port not found delete [] szPort; delete [] szBaud; return FALSE; } // set the timeout values m_CommTimeouts.ReadIntervalTimeout = 1000; m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000; m_CommTimeouts.ReadTotalTimeoutConstant = 1000; m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; m_CommTimeouts.WriteTotalTimeoutConstant = 1000; // configure if (SetCommTimeouts(m_hComm, &m_CommTimeouts)) { if (SetCommMask(m_hComm, dwCommEvents)) { if (GetCommState(m_hComm, &m_dcb)) { m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high! if (BuildCommDCB(szBaud, &m_dcb)) { if (SetCommState(m_hComm, &m_dcb)) ; // normal operation... continue else ProcessErrorMessage("SetCommState()"); } else ProcessErrorMessage("BuildCommDCB()"); } else ProcessErrorMessage("GetCommState()"); } else ProcessErrorMessage("SetCommMask()"); } else ProcessErrorMessage("SetCommTimeouts()"); delete [] szPort; delete [] szBaud; // flush the port PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // release critical section LeaveCriticalSection(&m_csCommunicationSync); TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr); return TRUE; }
这个函数是用来初始化串口的,即设置串口的通信参数:需要打开的串口号、波特率、奇偶校验方式、数据位、停止位,这里还可 以用来进行事件的设定。
如果串口初始化成功,就返回TRUE,若串口被其他设备占用、不存在或存在其他股占,就返回FALSE,编程者可以在这儿提示串口操作是否成功。
如果在当前主串口调用这个函数,那么pPortOwner可用this指针表示,串口号在函数中做了限制,只能用1,2,3和4四个串口号,而事实上在编程时可能用到更多串口号,可以通过通过注释掉本函数中的“assert(portur>0&&portnr<5)”语句取消对串口号的限制。
串口初始化成功后,就可以调用BOOL StartMonitoring()来启动串口检测线程,线程启动成功,发挥TRUE
BOOL CSerialPort::StartMonitoring()
{
if (!(m_Thread = AfxBeginThread(CommThread, this)))
return FALSE;
TRACE("Thread started\n");
return TRUE;
}
3、暂停或停止监测线程函数StopMonitoring()
该函数暂停或停止串口检测,要注意的是,调用该函数后,串口资源仍然被占用
// Suspend the comm thread
//
BOOL CSerialPort::StopMonitoring()
{
TRACE("Thread suspended\n");
m_Thread->SuspendThread();
return TRUE;
}
4、关闭串口函数ClosePort()
该函数功能是关闭串口,释放串口资源,调用该函数后,如果要继续使用串口,还需要调用InitPort()函数
5、通过串口发送字符/写串口函数WriteToPort()
该函数完成写串口功能,即向串口发送字符。
// Write a string to the port
void CSerialPort::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);
}
以上是常用的函数介绍,熟悉该类的使用后,可以仔细看看其他函数,对上面介绍的函数,在对串口资源的使用上要记住一下三点:
l 打开串口用调用InitPort()和StartMonitoring();关闭串口用StopMonitoring()和ClosePort()而且以上函数的调用顺序不能乱
l 通过串口发送字符调用函数WriteToPort()
l 接受串口收到的字符需要自己编写WM_COMM_RXCHAR消息处理函数,需要手工添加。
操作:
首先,需要操作一个串口,所以只需要定义1个类对象就可以了,如要操作多个串口,则要为每个串口均定一个类对象,这可以通过数据方式来实现,这里定义的类对象为m_SerialPort,再定义一个布尔变量m_bSerialPortOpened用来标志串口是否打开。
在CserialPort类中有多个串口事件可以响应,在一般串口编程中,只需要处理WM_COMM_RXCHAR消息就可以了,该类所有的消息均需要人工添加消息处理函数,将处理函数名定义为OnComm(),首先在SerialPortTestDlg.h(头文件)中添加串口字符接受消息WM_COMM_RXCHAR(串口接受缓冲区内有一个字符)的响应函数声明:
然后在,SerilPortTestDlg.cpp文件中进行WM_COMM_RXCHAR消息映射
说明:WPARAM、LPARAM类型是多态数据类型,在WIN32中为32位,支持多种数据类型,根据需要自动适应,这样,程序有很强的适应性,再次,我们可以分贝理解为char和integer类型数据,每当串口接受缓冲区内有一个字符时,就会产生一个WM_COMM_RXCHAR消息,除法OnComm()函数,这时就可以在函数中进行数据处理,所以,这个消息就是整个程序的源头。
虽然CSerialPort类是一个非常好的类,但毕竟只是集中了作者一个人的智慧和经验,他也有许多缺陷,
n 原类只能发送字符(ASCII文本)不能处理二进制发送(也就是不能发送0X00)
n 该类不能很好的释放串口
n 存在内存泄漏
可以进行如下改进
改进一、ASCII文本和二进制数据发送方式兼容
CSerialPort类中只有一个发送函数WriteToPort()
下面来对类做一些改进,解决这个问题,原理就是用字符数据来发送数据,并在发送时指定其长度,这样,数据没有发送完,发送过程就不会停止,CSerialPort类是用API函数编写的在,只要在WriteFile()函数中指定其实际要发送的长度,就可以将数据全部发送出去:
实现步骤如下:
1、在SerialPort.h文件中为CSerialPort类添加一个整形public成员变量,:int m_nWriteSize;用于指定发送字符数据的长度
添加三个发送函数
h文件:#ifndef __SERIALPORT_H__ #define __SERIALPORT_H__ #define WM_COMM_BREAK_DETECTED WM_USER+1 // A break was detected on input. #define WM_COMM_CTS_DETECTED WM_USER+2 // The CTS (clear-to-send) signal changed state. #define WM_COMM_DSR_DETECTED WM_USER+3 // The DSR (data-set-ready) signal changed state. #define WM_COMM_ERR_DETECTED WM_USER+4 // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. #define WM_COMM_RING_DETECTED WM_USER+5 // A ring indicator was detected. #define WM_COMM_RLSD_DETECTED WM_USER+6 // The RLSD (receive-line-signal-detect) signal changed state. #define WM_COMM_RXCHAR WM_USER+7 // A character was received and placed in the input buffer. #define WM_COMM_RXFLAG_DETECTED WM_USER+8 // The event character was received and placed in the input buffer. #define WM_COMM_TXEMPTY_DETECTED WM_USER+9 // The last character in the output buffer was sent. class CSerialPort { public: void ClosePort(); void WriteToPort(LPCTSTR string, int n); void WriteToPort(LPCTSTR string); void WriteToPort(char *string, int n); CSerialPort(); virtual ~CSerialPort(); BOOL InitPort(CWnd *pPortOwner, // the owner (CWnd) of the port (receives message) UINT portnr, // portnumber (1..4) UINT baud, // baudrate char parity, // parity UINT databits, // databits UINT stopbits, // stopbits DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc UINT writebuffersize); // size to the writebuffer BOOL StartMonitoring(); BOOL RestartMonitoring(); BOOL StopMonitoring(); DWORD GetWriteBufferSize(); DWORD GetCommEvents(); DCB GetDCB(); void WriteToPort(char *string); int m_nWriteSize; protected: // protected memberfunctions void ProcessErrorMessage(char *ErrorText); static UINT CommThread(LPVOID pParam); static void ReceiveChar(CSerialPort *port, COMSTAT comstat); static void WriteChar(CSerialPort *port); // thread CWinThread *m_Thread; // synchronisation objects CRITICAL_SECTION m_csCommunicationSync; BOOL m_bThreadAlive; // handles HANDLE m_hShutdownEvent; HANDLE m_hComm; HANDLE m_hWriteEvent; // Event array. // One element is used for each event. There are two event handles for each port. // A Write event and a receive character event which is located in the overlapped structure (m_ov.hEvent). // There is a general shutdown when the port is closed. HANDLE m_hEventArray[3]; // structures OVERLAPPED m_ov; COMMTIMEOUTS m_CommTimeouts; DCB m_dcb; // owner window CWnd *m_pOwner; // misc UINT m_nPortNr; char *m_szWriteBuffer; DWORD m_dwCommEvents; DWORD m_nWriteBufferSize; }; #endif __SERIALPORT_H__
CSerialPort.cpp /* ** FILENAME CSerialPort.cpp ** ** PURPOSE This class can read, write and watch one serial port. ** It sends messages to its owner when something happends on the port ** The class creates a thread for reading and writing so the main ** program is not blocked. ** ** CREATION DATE 15-09-1997 ** LAST MODIFICATION 12-11-1997 ** ** AUTHOR Remon Spekreijse ** ** */ #include "stdafx.h" #include "CSerialPort.h" #include <assert.h> // // Constructor // CSerialPort::CSerialPort() { m_hComm = NULL; // initialize overlapped structure members to zero m_ov.Offset = 0; m_ov.OffsetHigh = 0; // create events m_ov.hEvent = NULL; m_hWriteEvent = NULL; m_hShutdownEvent = NULL; m_szWriteBuffer = NULL; m_bThreadAlive = FALSE; m_nWriteSize = 0; } // // Delete dynamic memory // CSerialPort::~CSerialPort() { do { SetEvent(m_hShutdownEvent); } while (m_bThreadAlive); TRACE("Thread ended\n"); delete [] m_szWriteBuffer; } // // Initialize the port. This can be port 1 to 4. // BOOL CSerialPort::InitPort(CWnd *pPortOwner, // the owner (CWnd) of the port (receives message) UINT portnr, // portnumber (1..4) UINT baud, // baudrate char parity, // parity UINT databits, // databits UINT stopbits, // stopbits DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc UINT writebuffersize) // size to the writebuffer { assert(portnr > 0 && portnr < 5); assert(pPortOwner != NULL); // if the thread is alive: Kill if (m_bThreadAlive) { do { SetEvent(m_hShutdownEvent); } while (m_bThreadAlive); TRACE("Thread ended\n"); } // create events if (m_ov.hEvent != NULL) ResetEvent(m_ov.hEvent); else m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hWriteEvent != NULL) ResetEvent(m_hWriteEvent); else m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hShutdownEvent != NULL) ResetEvent(m_hShutdownEvent); else m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // initialize the event objects m_hEventArray[0] = m_hShutdownEvent; // highest priority m_hEventArray[1] = m_ov.hEvent; m_hEventArray[2] = m_hWriteEvent; // initialize critical section InitializeCriticalSection(&m_csCommunicationSync); // set buffersize for writing and save the owner m_pOwner = pPortOwner; if (m_szWriteBuffer != NULL) delete [] m_szWriteBuffer; m_szWriteBuffer = new char[writebuffersize]; m_nPortNr = portnr; m_nWriteBufferSize = writebuffersize; m_dwCommEvents = dwCommEvents; BOOL bResult = FALSE; char *szPort = new char[50]; char *szBaud = new char[50]; // now it critical! EnterCriticalSection(&m_csCommunicationSync); // if the port is already opened: close it if (m_hComm != NULL) { CloseHandle(m_hComm); m_hComm = NULL; } // prepare port strings sprintf(szPort, "COM%d", portnr); sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits); // get a handle to the port m_hComm = CreateFile(szPort, // communication port string (COMX) GENERIC_READ | GENERIC_WRITE, // read/write types 0, // comm devices must be opened with exclusive access NULL, // no security attributes OPEN_EXISTING, // comm devices must use OPEN_EXISTING FILE_FLAG_OVERLAPPED, // Async I/O 0); // template must be 0 for comm devices if (m_hComm == INVALID_HANDLE_VALUE) { // port not found delete [] szPort; delete [] szBaud; return FALSE; } // set the timeout values m_CommTimeouts.ReadIntervalTimeout = 1000; m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000; m_CommTimeouts.ReadTotalTimeoutConstant = 1000; m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; m_CommTimeouts.WriteTotalTimeoutConstant = 1000; // configure if (SetCommTimeouts(m_hComm, &m_CommTimeouts)) { if (SetCommMask(m_hComm, dwCommEvents)) { if (GetCommState(m_hComm, &m_dcb)) { m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high! if (BuildCommDCB(szBaud, &m_dcb)) { if (SetCommState(m_hComm, &m_dcb)) ; // normal operation... continue else ProcessErrorMessage("SetCommState()"); } else ProcessErrorMessage("BuildCommDCB()"); } else ProcessErrorMessage("GetCommState()"); } else ProcessErrorMessage("SetCommMask()"); } else ProcessErrorMessage("SetCommTimeouts()"); delete [] szPort; delete [] szBaud; // flush the port PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // release critical section LeaveCriticalSection(&m_csCommunicationSync); TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr); return TRUE; } // // The CommThread Function. // UINT CSerialPort::CommThread(LPVOID pParam) { // Cast the void pointer passed to the thread back to // a pointer of CSerialPort class CSerialPort *port = (CSerialPort *)pParam; // Set the status variable in the dialog class to // TRUE to indicate the thread is running. port->m_bThreadAlive = TRUE; // Misc. variables DWORD BytesTransfered = 0; DWORD Event = 0; DWORD CommEvent = 0; DWORD dwError = 0; COMSTAT comstat; BOOL bResult = TRUE; // Clear comm buffers at startup if (port->m_hComm) // check if the port is opened PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // begin forever loop. This loop will run as long as the thread is alive. for (;;) { // Make a call to WaitCommEvent(). This call will return immediatly // because our port was created as an async port (FILE_FLAG_OVERLAPPED // and an m_OverlappedStructerlapped structure specified). This call will cause the // m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to // be placed in a non-signeled state if there are no bytes available to be read, // or to a signeled state if there are bytes available. If this event handle // is set to the non-signeled state, it will be set to signeled when a // character arrives at the port. // we do this for each port! bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov); if (!bResult) { // If WaitCommEvent() returns FALSE, process the last error to determin // the reason.. switch (dwError = GetLastError()) { case ERROR_IO_PENDING: { // This is a normal return value if there are no bytes // to read at the port. // Do nothing and continue break; } case 87: { // Under Windows NT, this value is returned for some reason. // I have not investigated why, but it is also a valid reply // Also do nothing and continue. break; } default: { // All other error codes indicate a serious error has // occured. Process this error. port->ProcessErrorMessage("WaitCommEvent()"); break; } } } else { // If WaitCommEvent() returns TRUE, check to be sure there are // actually bytes in the buffer to read. // // If you are reading more than one byte at a time from the buffer // (which this program does not do) you will have the situation occur // where the first byte to arrive will cause the WaitForMultipleObjects() // function to stop waiting. The WaitForMultipleObjects() function // resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state // as it returns. // // If in the time between the reset of this event and the call to // ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again // to the signeled state. When the call to ReadFile() occurs, it will // read all of the bytes from the buffer, and the program will // loop back around to WaitCommEvent(). // // At this point you will be in the situation where m_OverlappedStruct.hEvent is set, // but there are no bytes available to read. If you proceed and call // ReadFile(), it will return immediatly due to the async port setup, but // GetOverlappedResults() will not return until the next character arrives. // // It is not desirable for the GetOverlappedResults() function to be in // this state. The thread shutdown event (event 0) and the WriteFile() // event (Event2) will not work if the thread is blocked by GetOverlappedResults(). // // The solution to this is to check the buffer with a call to ClearCommError(). // This call will reset the event handle, and if there are no bytes to read // we can loop back through WaitCommEvent() again, then proceed. // If there are really bytes to read, do nothing and proceed. bResult = ClearCommError(port->m_hComm, &dwError, &comstat); if (comstat.cbInQue == 0) continue; } // end if bResult // Main wait function. This function will normally block the thread // until one of nine events occur that require action. Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE); switch (Event) { case 0: { // Shutdown event. This is event zero so it will be // the higest priority and be serviced first. port->m_bThreadAlive = FALSE; // Kill this thread. break is not needed, but makes me feel better. AfxEndThread(100); break; } case 1: // read event { GetCommMask(port->m_hComm, &CommEvent); if (CommEvent & EV_CTS) ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr); if (CommEvent & EV_RXFLAG) ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr); if (CommEvent & EV_BREAK) ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr); if (CommEvent & EV_ERR) ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr); if (CommEvent & EV_RING) ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 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 CSerialPort::StartMonitoring() { if (!(m_Thread = AfxBeginThread(CommThread, this))) return FALSE; TRACE("Thread started\n"); return TRUE; } // // Restart the comm thread // BOOL CSerialPort::RestartMonitoring() { TRACE("Thread resumed\n"); m_Thread->ResumeThread(); return TRUE; } // // Suspend the comm thread // BOOL CSerialPort::StopMonitoring() { TRACE("Thread suspended\n"); m_Thread->SuspendThread(); return TRUE; } // // If there is a error, give the right message // void CSerialPort::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\nPort: %d\n", (char *)ErrorText, lpMsgBuf, m_nPortNr); MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP); LocalFree(lpMsgBuf); delete[] Temp; } // // Write a character. // void CSerialPort::WriteChar(CSerialPort *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_RXABORT | PURGE_TXABORT); bResult = WriteFile(port->m_hComm, // Handle to COMM Port port->m_szWriteBuffer, // Pointer to message buffer in calling finction //原句 strlen((char*)port->m_szWriteBuffer), // Length of message to send port->m_nWriteSize,//更改后,Length of message to send &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 GetOverlappedResults() BytesSent = 0; bWrite = FALSE; break; } default: { // all other error codes port->ProcessErrorMessage("WriteFile()"); } } } else { LeaveCriticalSection(&port->m_csCommunicationSync); } } // end if(bWrite) if (!bWrite) { bWrite = TRUE; bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port &port->m_ov, // Overlapped structure &BytesSent, // Stores number of bytes sent TRUE); // Wait flag LeaveCriticalSection(&port->m_csCommunicationSync); // deal with the error code if (!bResult) { port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()"); } } // end if (!bWrite) // Verify that the data size send equals what we tried to send //原句 if (BytesSent != strlen((char*)port->m_szWriteBuffer)) if(BytesSent |= port->m_nWriteSize) //修改后,Length of message to send { TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char *)port->m_szWriteBuffer)); } } // // Character received. Inform the owner // void CSerialPort::ReceiveChar(CSerialPort *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. //添加信息 防止死锁 if(WaitForSingleObject(port->m_hShutdownEvent, 0) == WAIT_OBJECT_0) return ; 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, // Handle 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 still in progress // Proceed on to GetOverlappedResults(); bRead = FALSE; break; } default: { // Another error has occured. Process this error. port->ProcessErrorMessage("ReadFile()"); break; } } } else { // ReadFile() returned complete. It is not necessary to call GetOverlappedResults() bRead = TRUE; } } // close if (bRead) if (!bRead) { bRead = TRUE; bResult = GetOverlappedResult(port->m_hComm, // Handle 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)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr); } // end forever loop } // // Write a string to the port // void CSerialPort::WriteToPort(char *string) { assert(m_hComm != 0); memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer)); strcpy(m_szWriteBuffer, string); m_nWriteSize = strlen(string); // set event for write SetEvent(m_hWriteEvent); } // // Return the device control block // DCB CSerialPort::GetDCB() { return m_dcb; } // // Return the communication event masks // DWORD CSerialPort::GetCommEvents() { return m_dwCommEvents; } // // Return the output buffer size // DWORD CSerialPort::GetWriteBufferSize() { return m_nWriteBufferSize; } void CSerialPort::WriteToPort(char *string, int n) { assert(m_hComm != 0); memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer)); memcpy(m_szWriteBuffer, string, n); m_nWriteSize = n; //set event for write SetEvent(m_hWriteEvent); } void CSerialPort::WriteToPort(LPCTSTR string) { assert(m_hComm != 0); memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer)); strcpy(m_szWriteBuffer, string); m_nWriteSize = strlen(string); //set event for write SetEvent(m_hWriteEvent); } void CSerialPort::WriteToPort(LPCTSTR string, int n) { assert(m_hComm != 0); memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer)); memcpy(m_szWriteBuffer, string, n); m_nWriteSize = n; //set event for write SetEvent(m_hWriteEvent); } void CSerialPort::ClosePort() { if (m_bThreadAlive) { MSG message; while (m_bThreadAlive) { if(::PeekMessage(&message, m_pOwner->m_hWnd, 0, 0, PM_REMOVE)) { ::TranslateMessage(&message); ::DispatchMessage(&message); } SetEvent(m_hShutdownEvent); } TRACE("Thread ended\n"); } if(m_szWriteBuffer != NULL) { delete [] m_szWriteBuffer; m_szWriteBuffer = NULL; } if(m_hComm) { CloseHandle(m_hComm); m_hComm = NULL; } }
- CSerialPort类解析
- CSerialPort类解析
- CSerialPort类解析
- CSerialPort类解析
- CSerialPort类解析
- CserialPort类解析(一)
- CSerialPort类解析(一)
- cserialport类
- CSerialPort类
- CSerialPort类
- CserialPort类函数解析及基本操作流程 基于C++
- CSerialPort类关闭函数
- CSerialPort类源代码分析
- CSerialPort串口类
- CSerialPort类错误排除
- CSerialPort类的使用
- 串口通信--CSerialport类
- CSerialPort
- rpm2cpio和cpio
- Visual Studio 2010已安装,sql server 2008 management studio安装教程
- Ubuntu的wired Networks 变灰色,无法连接网络
- 重庆OA办公系统目前推出PC端、移动终端(安卓、IOS、平板)- 上弦科技
- STL中的所有算法(70个)
- CSerialPort类解析
- 界面设计添加监听器
- int n=Integer.parseInt("".equals(j)?"0":j);
- 检测内存泄露问题
- Android Service
- 每日一小练——Armstrong数
- 富文本编辑器过滤XSS注入(JSOUP)
- ROS serial port programming
- rhel6.2下安装gcc