深入浅出Win32多线程程序设计之综合实例-3

3.多线程串口类 使用多线程串口通信更方便的途径是编写一个多线程的串口类,例如Remon Spekreijse编写了一个CSerialPort串口类。仔细分析这个类的源代码,将十分有助于我们对先前所学多线程及同步知识的理解。 3.1类的定义
#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: // contruction and destruction CSerialPort(); virtual ~CSerialPort(); // port initialisation BOOL InitPort(CWnd* pPortOwner, UINT portnr = 1, UINT baud = 19200, char parity = 'N', UINT databits = 8, UINT stopsbits = 1, DWORD dwCommEvents = EV_RXCHAR | EV_CTS, UINT nBufferSize = 512); // start/stop comm watching BOOL StartMonitoring(); BOOL RestartMonitoring(); BOOL StopMonitoring(); DWORD GetWriteBufferSize(); DWORD GetCommEvents(); DCB GetDCB(); void WriteToPort(char* string); 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__
3.2类的实现 3.2.1构造函数与析构函数 进行相关变量的赋初值及内存恢复:
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; } // // Delete dynamic memory // CSerialPort::~CSerialPort() { do { SetEvent(m_hShutdownEvent); } while (m_bThreadAlive); TRACE("Thread ended/n"); delete []m_szWriteBuffer; }
3.2.2核心函数:初始化串口 在初始化串口函数中,将打开串口,设置相关参数,并创建串口相关的用户控制事件,初始化临界区(Critical Section),以成队的EnterCriticalSection()、LeaveCriticalSection()函数进行资源的排它性访问: 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; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值