Yesky首页| 产品报价| 行情| 手机 | 数码 | 笔记本 | 台式机 | DIY硬件 | 外设 | 网络 | 数字家庭 | 评测 | 软件 | e时代 | 游戏 | 图片 | 壁纸 | 群乐 | 社区 | 博客 | 下载
软件频道>程序开发>JavaVBVCDelphiC/C++Web开发微软专栏移动数据库程序人生软件工程|产品中心下载什么是软件架构
您现在的位置: 天极网 > 开发频道 > 深入浅出Win32多线程程序设计之综合实例
全文

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

2005-12-23 09:52 作者: 宋宝华 出处: 天极开发 责任编辑:方舟
  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;
}

共5页。 9 1 2 3 4 5 :
网友关注
最新上市
编辑推荐
欢迎订阅天极网RSS聚合资讯:http://www.yesky.com/index.xml