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

来源:互联网 发布:南京逍遥游网络怎么样 编辑:程序博客网 时间:2024/05/01 05:24
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 destructionCSerialPort();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 watchingBOOL StartMonitoring();BOOL RestartMonitoring();BOOL StopMonitoring();DWORD GetWriteBufferSize();DWORD GetCommEvents();DCB GetDCB();void WriteToPort(char* string);protected:// protected memberfunctionsvoid ProcessErrorMessage(char* ErrorText);static UINT CommThread(LPVOID pParam);static void ReceiveChar(CSerialPort* port, COMSTAT comstat);static void WriteChar(CSerialPort* port);// threadCWinThread* m_Thread;// synchronisation objectsCRITICAL_SECTION m_csCommunicationSync;BOOL m_bThreadAlive;// handlesHANDLE 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];// structuresOVERLAPPED m_ov;COMMTIMEOUTS m_CommTimeouts;DCB m_dcb;// owner windowCWnd* m_pOwner;// miscUINT 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 zerom_ov.Offset = 0;m_ov.OffsetHigh = 0;// create eventsm_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, // baudratechar parity, // parityUINT databits, // databitsUINT stopbits, // stopbitsDWORD dwCommEvents, // EV_RXCHAR, EV_CTS etcUINT writebuffersize) // size to the writebuffer{assert(portnr > 0 && portnr < 5);assert(pPortOwner != NULL);// if the thread is alive: Killif (m_bThreadAlive){do{SetEvent(m_hShutdownEvent);}while (m_bThreadAlive);TRACE("Thread ended/n");}// create eventsif (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 objectsm_hEventArray[0] = m_hShutdownEvent; // highest prioritym_hEventArray[1] = m_ov.hEvent;m_hEventArray[2] = m_hWriteEvent;// initialize critical sectionInitializeCriticalSection(&m_csCommunicationSync);// set buffersize for writing and save the ownerm_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 itif (m_hComm != NULL){CloseHandle(m_hComm);m_hComm = NULL;}// prepare port stringssprintf(szPort, "COM%d", portnr);sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits,stopbits);// get a handle to the portm_hComm = CreateFile(szPort, // communication port string (COMX)GENERIC_READ | GENERIC_WRITE, // read/write types0, // comm devices must be opened with exclusive accessNULL, // no security attributesOPEN_EXISTING, // comm devices must use OPEN_EXISTINGFILE_FLAG_OVERLAPPED, // Async I/O0); // template must be 0 for comm devicesif (m_hComm == INVALID_HANDLE_VALUE){// port not founddelete []szPort;delete []szBaud;return FALSE;}// set the timeout valuesm_CommTimeouts.ReadIntervalTimeout = 1000;m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;m_CommTimeouts.ReadTotalTimeoutConstant = 1000;m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;m_CommTimeouts.WriteTotalTimeoutConstant = 1000;// configureif (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... continueelseProcessErrorMessage("SetCommState()");}elseProcessErrorMessage("BuildCommDCB()");}elseProcessErrorMessage("GetCommState()");}elseProcessErrorMessage("SetCommMask()");}elseProcessErrorMessage("SetCommTimeouts()");delete []szPort;delete []szBaud;// flush the portPurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);// release critical sectionLeaveCriticalSection(&m_csCommunicationSync);TRACE("Initialisation for communicationport %d completed./nUse Startmonitor to communicate./n", portnr);return TRUE;}
原创粉丝点击