CSerialPort类解析

来源:互联网 发布:淘宝新店如何发布宝贝 编辑:程序博客网 时间:2024/05/19 02:21

 

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_FRAMECE_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指针表示,串口号在函数中做了限制,只能用1234四个串口号,而事实上在编程时可能用到更多串口号,可以通过通过注释掉本函数中的“assert(portur>0&&portnr<5)”语句取消对串口号的限制。

 

2、启动串口通信监测线程函数StartMonitoring()

 

串口初始化成功后,就可以调用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, 0sizeof(m_szWriteBuffer)); 

strcpy(m_szWriteBuffer, string); 
 

// set event for write 

SetEvent(m_hWriteEvent); 


以上是常用的函数介绍,熟悉该类的使用后,可以仔细看看其他函数,对上面介绍的函数,在对串口资源的使用上要记住一下三点:

打开串口用调用InitPort()和StartMonitoring();关闭串口用StopMonitoring()和ClosePort()而且以上函数的调用顺序不能乱

通过串口发送字符调用函数WriteToPort()

接受串口收到的字符需要自己编写WM_COMM_RXCHAR消息处理函数,需要手工添加。

操作:

首先,需要操作一个串口,所以只需要定义1个类对象就可以了,如要操作多个串口,则要为每个串口均定一个类对象,这可以通过数据方式来实现,这里定义的类对象为m_SerialPort,再定义一个布尔变量m_bSerialPortOpened用来标志串口是否打开。

CserialPort类中有多个串口事件可以响应,在一般串口编程中,只需要处理WM_COMM_RXCHAR消息就可以了,该类所有的消息均需要人工添加消息处理函数,将处理函数名定义为OnComm(),首先在SerialPortTestDlg.h(头文件)中添加串口字符接受消息WM_COMM_RXCHAR(串口接受缓冲区内有一个字符)的响应函数声明:

//Generated message map funnctions 
//{{AFX_MSG(CSCportTestView) 
afx_msg long OnComm(WPARAM ch, LPARAM port); 
//}}AFX_MSG 
 

然后在,SerilPortTestDlg.cpp文件中进行WM_COMM_RXCHAR消息映射

BEGIN_MESSAE_MAP(CSerialPortTestDlg, CDialog)s 
//{{AFX_MSG_MAP(CSerialPortTestDlg) 
ON_MESSAGE(WM_COMM_RXCHAR, OnComm) 
//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 接着,在SerialPortTestDlg.cpp文件中加入函数OnComm()的实现,并在其中完成对节诶受到的字符的处理,将接收到的字符显示在接受编辑框中:

long CSerialPortTestDlg::OnComm(WPARAM ch, LPARAM port) 
    m_strEditReceiveMsg += ch; 
    UpdateData(FLASE);//将接收到的字符显示在接受编辑框中 
    returne 0

说明:WPARAMLPARAM类型是多态数据类型,在WIN32中为32位,支持多种数据类型,根据需要自动适应,这样,程序有很强的适应性,再次,我们可以分贝理解为charinteger类型数据,每当串口接受缓冲区内有一个字符时,就会产生一个WM_COMM_RXCHAR消息,除法OnComm()函数,这时就可以在函数中进行数据处理,所以,这个消息就是整个程序的源头。


虽然CSerialPort类是一个非常好的类,但毕竟只是集中了作者一个人的智慧和经验,他也有许多缺陷,

原类只能发送字符(ASCII文本)不能处理二进制发送(也就是不能发送0X00

该类不能很好的释放串口

存在内存泄漏

可以进行如下改进

改进一、ASCII文本和二进制数据发送方式兼容

CSerialPort类中只有一个发送函数WriteToPort()

// 
// Write a string to the port 
// 
void CSerialPort::WriteToPort(char *string) 
    assert(m_hComm != 0); 
 
    memset(m_szWriteBuffer, 0sizeof(m_szWriteBuffer)); 
    strcpy(m_szWriteBuffer, string); 
 
    // set event for write 
    SetEvent(m_hWriteEvent); 
调用上面的函数就只能用字符串方式,而c语言中,空字符(NULL,其中ASCII码值为0,即通常所说的十六禁止0x00字符),是串结束符,当检测到NULL字符后,就认为该字符串结束了,所以0x00字符以ASCII文本方式是不能从串口发送出去的,那么解决这一问题的方法就是用二进制发送,其实这里说的二进制,只不过是不以我们通常所说的“可见”或“能显示的字符”发送,比如,要发如下的一组值:
char chSend[5]={0x33,0x96,0x00,0x31,0xf1};

下面来对类做一些改进,解决这个问题,原理就是用字符数据来发送数据,并在发送时指定其长度,这样,数据没有发送完,发送过程就不会停止,CSerialPort类是用API函数编写的在,只要在WriteFile()函数中指定其实际要发送的长度,就可以将数据全部发送出去:

实现步骤如下:

1、SerialPort.h文件中为CSerialPort类添加一个整形public成员变量,:int m_nWriteSize;用于指定发送字符数据的长度

添加三个发送函数

h文件:
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #ifndef __SERIALPORT_H__   
  2. #define __SERIALPORT_H__   
  3.    
  4. #define WM_COMM_BREAK_DETECTED        WM_USER+1    // A break was detected on input.   
  5. #define WM_COMM_CTS_DETECTED        WM_USER+2    // The CTS (clear-to-send) signal changed state.    
  6. #define WM_COMM_DSR_DETECTED        WM_USER+3    // The DSR (data-set-ready) signal changed state.    
  7. #define WM_COMM_ERR_DETECTED        WM_USER+4    // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY.    
  8. #define WM_COMM_RING_DETECTED        WM_USER+5    // A ring indicator was detected.    
  9. #define WM_COMM_RLSD_DETECTED        WM_USER+6    // The RLSD (receive-line-signal-detect) signal changed state.    
  10. #define WM_COMM_RXCHAR                WM_USER+7    // A character was received and placed in the input buffer.    
  11. #define WM_COMM_RXFLAG_DETECTED        WM_USER+8    // The event character was received and placed in the input buffer.     
  12. #define WM_COMM_TXEMPTY_DETECTED    WM_USER+9    // The last character in the output buffer was sent.     
  13.    
  14.    
  15. class CSerialPort   
  16. {   
  17. public:   
  18.     void ClosePort();   
  19.     void WriteToPort(LPCTSTR string, int n);   
  20.     void WriteToPort(LPCTSTR string);   
  21.     void WriteToPort(char *string, int n);   
  22.     CSerialPort();   
  23.     virtual        ~CSerialPort();   
  24.     BOOL        InitPort(CWnd *pPortOwner,    // the owner (CWnd) of the port (receives message)   
  25.                          UINT  portnr,        // portnumber (1..4)   
  26.                          UINT  baud,            // baudrate   
  27.                          char  parity,        // parity   
  28.                          UINT  databits,        // databits   
  29.                          UINT  stopbits,        // stopbits   
  30.                          DWORD dwCommEvents,    // EV_RXCHAR, EV_CTS etc   
  31.                          UINT  writebuffersize);    // size to the writebuffer   
  32.    
  33.     BOOL        StartMonitoring();   
  34.     BOOL        RestartMonitoring();   
  35.     BOOL        StopMonitoring();   
  36.     DWORD        GetWriteBufferSize();   
  37.     DWORD        GetCommEvents();   
  38.     DCB            GetDCB();   
  39.    
  40.     void        WriteToPort(char *string);   
  41.     int m_nWriteSize;   
  42.    
  43. protected:   
  44.     // protected memberfunctions   
  45.     void        ProcessErrorMessage(char *ErrorText);   
  46.     static UINT    CommThread(LPVOID pParam);   
  47.     static void    ReceiveChar(CSerialPort *port, COMSTAT comstat);   
  48.     static void    WriteChar(CSerialPort *port);   
  49.    
  50.     // thread   
  51.     CWinThread            *m_Thread;   
  52.    
  53.     // synchronisation objects   
  54.     CRITICAL_SECTION    m_csCommunicationSync;   
  55.     BOOL                m_bThreadAlive;   
  56.    
  57.     // handles   
  58.     HANDLE                m_hShutdownEvent;   
  59.     HANDLE                m_hComm;   
  60.     HANDLE                m_hWriteEvent;   
  61.    
  62.     // Event array.   
  63.     // One element is used for each event. There are two event handles for each port.   
  64.     // A Write event and a receive character event which is located in the overlapped structure (m_ov.hEvent).   
  65.     // There is a general shutdown when the port is closed.   
  66.     HANDLE                m_hEventArray[3];   
  67.    
  68.     // structures   
  69.     OVERLAPPED            m_ov;   
  70.     COMMTIMEOUTS        m_CommTimeouts;   
  71.     DCB                    m_dcb;   
  72.    
  73.     // owner window   
  74.     CWnd                *m_pOwner;   
  75.    
  76.     // misc   
  77.     UINT                m_nPortNr;   
  78.     char                *m_szWriteBuffer;   
  79.     DWORD                m_dwCommEvents;   
  80.     DWORD                m_nWriteBufferSize;   
  81. };   
  82.    
  83. #endif __SERIALPORT_H__   

 

cpp文件:
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. CSerialPort.cpp   
  2. /*  
  3.   
  4. ** FILENAME CSerialPort.cpp  
  5.   
  6. **  
  7.   
  8. ** PURPOSE This class can read, write and watch one serial port.  
  9.   
  10. ** It sends messages to its owner when something happends on the port  
  11.   
  12. ** The class creates a thread for reading and writing so the main  
  13.   
  14. ** program is not blocked.  
  15.   
  16. **  
  17.   
  18. ** CREATION DATE 15-09-1997  
  19.   
  20. ** LAST MODIFICATION 12-11-1997  
  21.   
  22. **  
  23.   
  24. ** AUTHOR Remon Spekreijse  
  25.   
  26. **  
  27.   
  28. **  
  29.   
  30. */   
  31.    
  32.    
  33. #include "stdafx.h"   
  34.    
  35. #include "CSerialPort.h"   
  36.    
  37. #include <assert.h>   
  38.    
  39.    
  40. //   
  41.    
  42. // Constructor   
  43.    
  44. //   
  45.    
  46. CSerialPort::CSerialPort()   
  47.    
  48. {   
  49.    
  50.     m_hComm = NULL;   
  51.    
  52.    
  53.     // initialize overlapped structure members to zero   
  54.    
  55.     m_ov.Offset = 0;   
  56.    
  57.     m_ov.OffsetHigh = 0;   
  58.    
  59.    
  60.     // create events   
  61.    
  62.     m_ov.hEvent = NULL;   
  63.    
  64.     m_hWriteEvent = NULL;   
  65.    
  66.     m_hShutdownEvent = NULL;   
  67.    
  68.    
  69.     m_szWriteBuffer = NULL;   
  70.    
  71.    
  72.     m_bThreadAlive = FALSE;   
  73.    
  74.    
  75.     m_nWriteSize = 0;   
  76.    
  77. }   
  78.    
  79.    
  80. //   
  81.    
  82. // Delete dynamic memory   
  83.    
  84. //   
  85.    
  86. CSerialPort::~CSerialPort()   
  87.    
  88. {   
  89.    
  90.     do   
  91.    
  92.     {   
  93.    
  94.         SetEvent(m_hShutdownEvent);   
  95.    
  96.     }   
  97.     while (m_bThreadAlive);   
  98.    
  99.    
  100.     TRACE("Thread ended\n");   
  101.    
  102.    
  103.     delete [] m_szWriteBuffer;   
  104.    
  105. }   
  106.    
  107.    
  108. //   
  109.    
  110. // Initialize the port. This can be port 1 to 4.   
  111.    
  112. //   
  113.    
  114. BOOL CSerialPort::InitPort(CWnd *pPortOwner, // the owner (CWnd) of the port (receives message)   
  115.    
  116.                            UINT  portnr, // portnumber (1..4)   
  117.    
  118.                            UINT  baud, // baudrate   
  119.    
  120.                            char  parity, // parity   
  121.    
  122.                            UINT  databits, // databits   
  123.    
  124.                            UINT  stopbits, // stopbits   
  125.    
  126.                            DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc   
  127.    
  128.                            UINT  writebuffersize) // size to the writebuffer   
  129.    
  130. {   
  131.    
  132.     assert(portnr > 0 && portnr < 5);   
  133.    
  134.     assert(pPortOwner != NULL);   
  135.    
  136.    
  137.     // if the thread is alive: Kill   
  138.    
  139.     if (m_bThreadAlive)   
  140.    
  141.     {   
  142.    
  143.         do   
  144.    
  145.         {   
  146.    
  147.             SetEvent(m_hShutdownEvent);   
  148.    
  149.         }   
  150.         while (m_bThreadAlive);   
  151.    
  152.         TRACE("Thread ended\n");   
  153.    
  154.     }   
  155.    
  156.    
  157.     // create events   
  158.    
  159.     if (m_ov.hEvent != NULL)   
  160.    
  161.         ResetEvent(m_ov.hEvent);   
  162.    
  163.     else   
  164.    
  165.         m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);   
  166.    
  167.    
  168.     if (m_hWriteEvent != NULL)   
  169.    
  170.         ResetEvent(m_hWriteEvent);   
  171.    
  172.     else   
  173.    
  174.         m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);   
  175.    
  176.    
  177.     if (m_hShutdownEvent != NULL)   
  178.    
  179.         ResetEvent(m_hShutdownEvent);   
  180.    
  181.     else   
  182.    
  183.         m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);   
  184.    
  185.    
  186.     // initialize the event objects   
  187.    
  188.     m_hEventArray[0] = m_hShutdownEvent; // highest priority   
  189.    
  190.     m_hEventArray[1] = m_ov.hEvent;   
  191.    
  192.     m_hEventArray[2] = m_hWriteEvent;   
  193.    
  194.    
  195.     // initialize critical section   
  196.    
  197.     InitializeCriticalSection(&m_csCommunicationSync);   
  198.    
  199.    
  200.     // set buffersize for writing and save the owner   
  201.    
  202.     m_pOwner = pPortOwner;   
  203.    
  204.    
  205.     if (m_szWriteBuffer != NULL)   
  206.    
  207.         delete [] m_szWriteBuffer;   
  208.    
  209.     m_szWriteBuffer = new char[writebuffersize];   
  210.    
  211.    
  212.     m_nPortNr = portnr;   
  213.    
  214.    
  215.     m_nWriteBufferSize = writebuffersize;   
  216.    
  217.     m_dwCommEvents = dwCommEvents;   
  218.    
  219.    
  220.     BOOL bResult = FALSE;   
  221.    
  222.     char *szPort = new char[50];   
  223.    
  224.     char *szBaud = new char[50];   
  225.    
  226.    
  227.     // now it critical!   
  228.    
  229.     EnterCriticalSection(&m_csCommunicationSync);   
  230.    
  231.    
  232.     // if the port is already opened: close it   
  233.    
  234.     if (m_hComm != NULL)   
  235.    
  236.     {   
  237.    
  238.         CloseHandle(m_hComm);   
  239.    
  240.         m_hComm = NULL;   
  241.    
  242.     }   
  243.    
  244.    
  245.     // prepare port strings   
  246.    
  247.     sprintf(szPort, "COM%d", portnr);   
  248.    
  249.     sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);   
  250.    
  251.    
  252.     // get a handle to the port   
  253.    
  254.     m_hComm = CreateFile(szPort, // communication port string (COMX)   
  255.    
  256.                          GENERIC_READ | GENERIC_WRITE, // read/write types   
  257.    
  258.                          0, // comm devices must be opened with exclusive access   
  259.    
  260.                          NULL, // no security attributes   
  261.    
  262.                          OPEN_EXISTING, // comm devices must use OPEN_EXISTING   
  263.    
  264.                          FILE_FLAG_OVERLAPPED, // Async I/O   
  265.    
  266.                          0); // template must be 0 for comm devices   
  267.    
  268.    
  269.     if (m_hComm == INVALID_HANDLE_VALUE)   
  270.    
  271.     {   
  272.    
  273.         // port not found   
  274.    
  275.         delete [] szPort;   
  276.    
  277.         delete [] szBaud;   
  278.    
  279.    
  280.         return FALSE;   
  281.    
  282.     }   
  283.    
  284.    
  285.     // set the timeout values   
  286.    
  287.     m_CommTimeouts.ReadIntervalTimeout = 1000;   
  288.    
  289.     m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;   
  290.    
  291.     m_CommTimeouts.ReadTotalTimeoutConstant = 1000;   
  292.    
  293.     m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;   
  294.    
  295.     m_CommTimeouts.WriteTotalTimeoutConstant = 1000;   
  296.    
  297.    
  298.     // configure   
  299.    
  300.     if (SetCommTimeouts(m_hComm, &m_CommTimeouts))   
  301.    
  302.     {   
  303.    
  304.         if (SetCommMask(m_hComm, dwCommEvents))   
  305.    
  306.         {   
  307.    
  308.             if (GetCommState(m_hComm, &m_dcb))   
  309.    
  310.             {   
  311.    
  312.                 m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!   
  313.    
  314.                 if (BuildCommDCB(szBaud, &m_dcb))   
  315.    
  316.                 {   
  317.    
  318.                     if (SetCommState(m_hComm, &m_dcb))   
  319.    
  320.                         ; // normal operation... continue   
  321.    
  322.                     else   
  323.    
  324.                         ProcessErrorMessage("SetCommState()");   
  325.    
  326.                 }   
  327.    
  328.                 else   
  329.    
  330.                     ProcessErrorMessage("BuildCommDCB()");   
  331.    
  332.             }   
  333.    
  334.             else   
  335.    
  336.                 ProcessErrorMessage("GetCommState()");   
  337.    
  338.         }   
  339.    
  340.         else   
  341.    
  342.             ProcessErrorMessage("SetCommMask()");   
  343.    
  344.     }   
  345.    
  346.     else   
  347.    
  348.         ProcessErrorMessage("SetCommTimeouts()");   
  349.    
  350.    
  351.     delete [] szPort;   
  352.    
  353.     delete [] szBaud;   
  354.    
  355.    
  356.     // flush the port   
  357.    
  358.     PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);   
  359.    
  360.    
  361.     // release critical section   
  362.    
  363.     LeaveCriticalSection(&m_csCommunicationSync);   
  364.    
  365.    
  366.     TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr);   
  367.    
  368.    
  369.     return TRUE;   
  370.    
  371. }   
  372.    
  373.    
  374. //   
  375.    
  376. //  The CommThread Function.   
  377.    
  378. //   
  379.    
  380. UINT CSerialPort::CommThread(LPVOID pParam)   
  381.    
  382. {   
  383.    
  384.     // Cast the void pointer passed to the thread back to   
  385.    
  386.     // a pointer of CSerialPort class   
  387.    
  388.     CSerialPort *port = (CSerialPort *)pParam;   
  389.    
  390.    
  391.     // Set the status variable in the dialog class to   
  392.    
  393.     // TRUE to indicate the thread is running.   
  394.    
  395.     port->m_bThreadAlive = TRUE;   
  396.    
  397.    
  398.     // Misc. variables   
  399.    
  400.     DWORD BytesTransfered = 0;   
  401.    
  402.     DWORD Event = 0;   
  403.    
  404.     DWORD CommEvent = 0;   
  405.    
  406.     DWORD dwError = 0;   
  407.    
  408.     COMSTAT comstat;   
  409.    
  410.     BOOL  bResult = TRUE;   
  411.    
  412.    
  413.     // Clear comm buffers at startup   
  414.    
  415.     if (port->m_hComm) // check if the port is opened   
  416.    
  417.         PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);   
  418.    
  419.    
  420.     // begin forever loop.  This loop will run as long as the thread is alive.   
  421.    
  422.     for (;;)   
  423.    
  424.     {   
  425.    
  426.    
  427.         // Make a call to WaitCommEvent().  This call will return immediatly   
  428.    
  429.         // because our port was created as an async port (FILE_FLAG_OVERLAPPED   
  430.    
  431.         // and an m_OverlappedStructerlapped structure specified).  This call will cause the   
  432.    
  433.         // m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to   
  434.    
  435.         // be placed in a non-signeled state if there are no bytes available to be read,   
  436.    
  437.         // or to a signeled state if there are bytes available.  If this event handle   
  438.    
  439.         // is set to the non-signeled state, it will be set to signeled when a   
  440.    
  441.         // character arrives at the port.   
  442.    
  443.    
  444.         // we do this for each port!   
  445.    
  446.    
  447.         bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);   
  448.    
  449.    
  450.         if (!bResult)   
  451.    
  452.         {   
  453.    
  454.             // If WaitCommEvent() returns FALSE, process the last error to determin   
  455.    
  456.             // the reason..   
  457.    
  458.             switch (dwError = GetLastError())   
  459.    
  460.             {   
  461.    
  462.             case ERROR_IO_PENDING:   
  463.    
  464.             {   
  465.    
  466.                 // This is a normal return value if there are no bytes   
  467.    
  468.                 // to read at the port.   
  469.    
  470.                 // Do nothing and continue   
  471.    
  472.                 break;   
  473.    
  474.             }   
  475.    
  476.             case 87:   
  477.    
  478.             {   
  479.    
  480.                 // Under Windows NT, this value is returned for some reason.   
  481.    
  482.                 // I have not investigated why, but it is also a valid reply   
  483.    
  484.                 // Also do nothing and continue.   
  485.    
  486.                 break;   
  487.    
  488.             }   
  489.    
  490.             default:   
  491.    
  492.             {   
  493.    
  494.                 // All other error codes indicate a serious error has   
  495.    
  496.                 // occured.  Process this error.   
  497.    
  498.                 port->ProcessErrorMessage("WaitCommEvent()");   
  499.    
  500.                 break;   
  501.    
  502.             }   
  503.    
  504.             }   
  505.    
  506.         }   
  507.    
  508.         else   
  509.    
  510.         {   
  511.    
  512.             // If WaitCommEvent() returns TRUE, check to be sure there are   
  513.    
  514.             // actually bytes in the buffer to read.   
  515.    
  516.             //   
  517.    
  518.             // If you are reading more than one byte at a time from the buffer   
  519.    
  520.             // (which this program does not do) you will have the situation occur   
  521.    
  522.             // where the first byte to arrive will cause the WaitForMultipleObjects()   
  523.    
  524.             // function to stop waiting.  The WaitForMultipleObjects() function   
  525.    
  526.             // resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state   
  527.    
  528.             // as it returns.   
  529.    
  530.             //   
  531.    
  532.             // If in the time between the reset of this event and the call to   
  533.    
  534.             // ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again   
  535.    
  536.             // to the signeled state. When the call to ReadFile() occurs, it will   
  537.    
  538.             // read all of the bytes from the buffer, and the program will   
  539.    
  540.             // loop back around to WaitCommEvent().   
  541.    
  542.             //   
  543.    
  544.             // At this point you will be in the situation where m_OverlappedStruct.hEvent is set,   
  545.    
  546.             // but there are no bytes available to read.  If you proceed and call   
  547.    
  548.             // ReadFile(), it will return immediatly due to the async port setup, but   
  549.    
  550.             // GetOverlappedResults() will not return until the next character arrives.   
  551.    
  552.             //   
  553.    
  554.             // It is not desirable for the GetOverlappedResults() function to be in   
  555.    
  556.             // this state.  The thread shutdown event (event 0) and the WriteFile()   
  557.    
  558.             // event (Event2) will not work if the thread is blocked by GetOverlappedResults().   
  559.    
  560.             //   
  561.    
  562.             // The solution to this is to check the buffer with a call to ClearCommError().   
  563.    
  564.             // This call will reset the event handle, and if there are no bytes to read   
  565.    
  566.             // we can loop back through WaitCommEvent() again, then proceed.   
  567.    
  568.             // If there are really bytes to read, do nothing and proceed.   
  569.    
  570.    
  571.             bResult = ClearCommError(port->m_hComm, &dwError, &comstat);   
  572.    
  573.    
  574.             if (comstat.cbInQue == 0)   
  575.    
  576.                 continue;   
  577.    
  578.         } // end if bResult   
  579.    
  580.    
  581.         // Main wait function.  This function will normally block the thread   
  582.    
  583.         // until one of nine events occur that require action.   
  584.    
  585.         Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);   
  586.    
  587.    
  588.         switch (Event)   
  589.    
  590.         {   
  591.    
  592.         case 0:   
  593.    
  594.         {   
  595.    
  596.             // Shutdown event.  This is event zero so it will be   
  597.    
  598.             // the higest priority and be serviced first.   
  599.    
  600.    
  601.             port->m_bThreadAlive = FALSE;   
  602.    
  603.    
  604.             // Kill this thread.  break is not needed, but makes me feel better.   
  605.    
  606.             AfxEndThread(100);   
  607.    
  608.             break;   
  609.    
  610.         }   
  611.    
  612.         case 1: // read event   
  613.    
  614.         {   
  615.    
  616.             GetCommMask(port->m_hComm, &CommEvent);   
  617.    
  618.             if (CommEvent & EV_CTS)   
  619.    
  620.                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);   
  621.    
  622.             if (CommEvent & EV_RXFLAG)   
  623.    
  624.                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);   
  625.    
  626.             if (CommEvent & EV_BREAK)   
  627.    
  628.                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);   
  629.    
  630.             if (CommEvent & EV_ERR)   
  631.    
  632.                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);   
  633.    
  634.             if (CommEvent & EV_RING)   
  635.    
  636.                 ::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);   
  637.    
  638.    
  639.             if (CommEvent & EV_RXCHAR)   
  640.    
  641.                 // Receive character event from port.   
  642.    
  643.                 ReceiveChar(port, comstat);   
  644.    
  645.    
  646.             break;   
  647.    
  648.         }   
  649.    
  650.         case 2: // write event   
  651.    
  652.         {   
  653.    
  654.             // Write character event from port   
  655.    
  656.             WriteChar(port);   
  657.    
  658.             break;   
  659.    
  660.         }   
  661.    
  662.    
  663.         } // end switch   
  664.    
  665.    
  666.     } // close forever loop   
  667.    
  668.    
  669.     return 0;   
  670.    
  671. }   
  672.    
  673.    
  674. //   
  675.    
  676. // start comm watching   
  677.    
  678. //   
  679.    
  680. BOOL CSerialPort::StartMonitoring()   
  681.    
  682. {   
  683.    
  684.     if (!(m_Thread = AfxBeginThread(CommThread, this)))   
  685.    
  686.         return FALSE;   
  687.    
  688.     TRACE("Thread started\n");   
  689.    
  690.     return TRUE;   
  691.    
  692. }   
  693.    
  694.    
  695. //   
  696.    
  697. // Restart the comm thread   
  698.    
  699. //   
  700.    
  701. BOOL CSerialPort::RestartMonitoring()   
  702.    
  703. {   
  704.    
  705.     TRACE("Thread resumed\n");   
  706.    
  707.     m_Thread->ResumeThread();   
  708.    
  709.     return TRUE;   
  710.    
  711. }   
  712.    
  713.    
  714.    
  715. //   
  716.    
  717. // Suspend the comm thread   
  718.    
  719. //   
  720.    
  721. BOOL CSerialPort::StopMonitoring()   
  722.    
  723. {   
  724.    
  725.     TRACE("Thread suspended\n");   
  726.    
  727.     m_Thread->SuspendThread();   
  728.    
  729.     return TRUE;   
  730.    
  731. }   
  732.    
  733.    
  734.    
  735. //   
  736.    
  737. // If there is a error, give the right message   
  738.    
  739. //   
  740.    
  741. void CSerialPort::ProcessErrorMessage(char *ErrorText)   
  742.    
  743. {   
  744.    
  745.     char *Temp = new char[200];   
  746.    
  747.    
  748.     LPVOID lpMsgBuf;   
  749.    
  750.    
  751.     FormatMessage(   
  752.    
  753.         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,   
  754.    
  755.         NULL,   
  756.    
  757.         GetLastError(),   
  758.    
  759.         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language   
  760.    
  761.         (LPTSTR) &lpMsgBuf,   
  762.    
  763.         0,   
  764.    
  765.         NULL   
  766.    
  767.     );   
  768.    
  769.    
  770.     sprintf(Temp, "WARNING:  %s Failed with the following error: \n%s\nPort: %d\n", (char *)ErrorText, lpMsgBuf, m_nPortNr);   
  771.    
  772.     MessageBox(NULL, Temp, "Application Error", MB_ICONSTOP);   
  773.    
  774.    
  775.     LocalFree(lpMsgBuf);   
  776.    
  777.     delete[] Temp;   
  778.    
  779. }   
  780.    
  781.    
  782. //   
  783.    
  784. // Write a character.   
  785.    
  786. //   
  787.    
  788. void CSerialPort::WriteChar(CSerialPort *port)   
  789.    
  790. {   
  791.    
  792.     BOOL bWrite = TRUE;   
  793.    
  794.     BOOL bResult = TRUE;   
  795.    
  796.    
  797.     DWORD BytesSent = 0;   
  798.    
  799.    
  800.     ResetEvent(port->m_hWriteEvent);   
  801.    
  802.    
  803.     // Gain ownership of the critical section   
  804.    
  805.     EnterCriticalSection(&port->m_csCommunicationSync);   
  806.    
  807.    
  808.     if (bWrite)   
  809.    
  810.     {   
  811.    
  812.         // Initailize variables   
  813.    
  814.         port->m_ov.Offset = 0;   
  815.    
  816.         port->m_ov.OffsetHigh = 0;   
  817.    
  818.    
  819.         // Clear buffer   
  820.    
  821.         PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);   
  822.    
  823.    
  824.         bResult = WriteFile(port->m_hComm, // Handle to COMM Port   
  825.    
  826.                             port->m_szWriteBuffer, // Pointer to message buffer in calling finction   
  827.    
  828.                             //原句 strlen((char*)port->m_szWriteBuffer), // Length of message to send   
  829.    
  830.                             port->m_nWriteSize,//更改后,Length of message to send   
  831.    
  832.                             &BytesSent, // Where to store the number of bytes sent   
  833.    
  834.                             &port->m_ov); // Overlapped structure   
  835.    
  836.    
  837.         // deal with any error codes   
  838.    
  839.         if (!bResult)   
  840.    
  841.         {   
  842.    
  843.             DWORD dwError = GetLastError();   
  844.    
  845.             switch (dwError)   
  846.    
  847.             {   
  848.    
  849.             case ERROR_IO_PENDING:   
  850.    
  851.             {   
  852.    
  853.                 // continue to GetOverlappedResults()   
  854.    
  855.                 BytesSent = 0;   
  856.    
  857.                 bWrite = FALSE;   
  858.    
  859.                 break;   
  860.    
  861.             }   
  862.    
  863.             default:   
  864.    
  865.             {   
  866.    
  867.                 // all other error codes   
  868.    
  869.                 port->ProcessErrorMessage("WriteFile()");   
  870.    
  871.             }   
  872.    
  873.             }   
  874.    
  875.         }   
  876.    
  877.         else   
  878.    
  879.         {   
  880.    
  881.             LeaveCriticalSection(&port->m_csCommunicationSync);   
  882.    
  883.         }   
  884.    
  885.     } // end if(bWrite)   
  886.    
  887.    
  888.     if (!bWrite)   
  889.    
  890.     {   
  891.    
  892.         bWrite = TRUE;   
  893.    
  894.    
  895.         bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port   
  896.    
  897.                                       &port->m_ov, // Overlapped structure   
  898.    
  899.                                       &BytesSent, // Stores number of bytes sent   
  900.    
  901.                                       TRUE);  // Wait flag   
  902.    
  903.    
  904.         LeaveCriticalSection(&port->m_csCommunicationSync);   
  905.    
  906.    
  907.         // deal with the error code   
  908.    
  909.         if (!bResult)   
  910.    
  911.         {   
  912.    
  913.             port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");   
  914.    
  915.         }   
  916.    
  917.     } // end if (!bWrite)   
  918.    
  919.    
  920.     // Verify that the data size send equals what we tried to send   
  921.    
  922.     //原句 if (BytesSent != strlen((char*)port->m_szWriteBuffer))   
  923.    
  924.     if(BytesSent |= port->m_nWriteSize) //修改后,Length of message to send   
  925.    
  926.     {   
  927.    
  928.         TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char *)port->m_szWriteBuffer));   
  929.    
  930.     }   
  931.    
  932. }   
  933.    
  934.    
  935. //   
  936.    
  937. // Character received. Inform the owner   
  938.    
  939. //   
  940.    
  941. void CSerialPort::ReceiveChar(CSerialPort *port, COMSTAT comstat)   
  942.    
  943. {   
  944.    
  945.     BOOL  bRead = TRUE;   
  946.    
  947.     BOOL  bResult = TRUE;   
  948.    
  949.     DWORD dwError = 0;   
  950.    
  951.     DWORD BytesRead = 0;   
  952.    
  953.     unsigned char RXBuff;   
  954.    
  955.    
  956.     for (;;)   
  957.    
  958.     {   
  959.    
  960.         // Gain ownership of the comm port critical section.   
  961.    
  962.         // This process guarantees no other part of this program   
  963.    
  964.         // is using the port object.   
  965.    
  966.    
  967.    
  968.         //添加信息 防止死锁   
  969.    
  970.         if(WaitForSingleObject(port->m_hShutdownEvent, 0) == WAIT_OBJECT_0)   
  971.    
  972.             return ;   
  973.    
  974.    
  975.    
  976.         EnterCriticalSection(&port->m_csCommunicationSync);   
  977.    
  978.    
  979.         // ClearCommError() will update the COMSTAT structure and   
  980.    
  981.         // clear any other errors.   
  982.    
  983.    
  984.         bResult = ClearCommError(port->m_hComm, &dwError, &comstat);   
  985.    
  986.    
  987.         LeaveCriticalSection(&port->m_csCommunicationSync);   
  988.    
  989.    
  990.         // start forever loop.  I use this type of loop because I   
  991.    
  992.         // do not know at runtime how many loops this will have to   
  993.    
  994.         // run. My solution is to start a forever loop and to   
  995.    
  996.         // break out of it when I have processed all of the   
  997.    
  998.         // data available.  Be careful with this approach and   
  999.    
  1000.         // be sure your loop will exit.   
  1001.    
  1002.         // My reasons for this are not as clear in this sample   
  1003.    
  1004.         // as it is in my production code, but I have found this   
  1005.    
  1006.         // solutiion to be the most efficient way to do this.   
  1007.    
  1008.    
  1009.         if (comstat.cbInQue == 0)   
  1010.    
  1011.         {   
  1012.    
  1013.             // break out when all bytes have been read   
  1014.    
  1015.             break;   
  1016.    
  1017.         }   
  1018.    
  1019.    
  1020.         EnterCriticalSection(&port->m_csCommunicationSync);   
  1021.    
  1022.    
  1023.         if (bRead)   
  1024.    
  1025.         {   
  1026.    
  1027.             bResult = ReadFile(port->m_hComm, // Handle to COMM port   
  1028.    
  1029.                                &RXBuff, // RX Buffer Pointer   
  1030.    
  1031.                                1, // Read one byte   
  1032.    
  1033.                                &BytesRead, // Stores number of bytes read   
  1034.    
  1035.                                &port->m_ov); // pointer to the m_ov structure   
  1036.    
  1037.             // deal with the error code   
  1038.    
  1039.             if (!bResult)   
  1040.    
  1041.             {   
  1042.    
  1043.                 switch (dwError = GetLastError())   
  1044.    
  1045.                 {   
  1046.    
  1047.                 case ERROR_IO_PENDING:   
  1048.    
  1049.                 {   
  1050.    
  1051.                     // asynchronous i/o is still in progress   
  1052.    
  1053.                     // Proceed on to GetOverlappedResults();   
  1054.    
  1055.                     bRead = FALSE;   
  1056.    
  1057.                     break;   
  1058.    
  1059.                 }   
  1060.    
  1061.                 default:   
  1062.    
  1063.                 {   
  1064.    
  1065.                     // Another error has occured.  Process this error.   
  1066.    
  1067.                     port->ProcessErrorMessage("ReadFile()");   
  1068.    
  1069.                     break;   
  1070.    
  1071.                 }   
  1072.    
  1073.                 }   
  1074.    
  1075.             }   
  1076.    
  1077.             else   
  1078.    
  1079.             {   
  1080.    
  1081.                 // ReadFile() returned complete. It is not necessary to call GetOverlappedResults()   
  1082.    
  1083.                 bRead = TRUE;   
  1084.    
  1085.             }   
  1086.    
  1087.         }  // close if (bRead)   
  1088.    
  1089.    
  1090.         if (!bRead)   
  1091.    
  1092.         {   
  1093.    
  1094.             bRead = TRUE;   
  1095.    
  1096.             bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port   
  1097.    
  1098.                                           &port->m_ov, // Overlapped structure   
  1099.    
  1100.                                           &BytesRead, // Stores number of bytes read   
  1101.    
  1102.                                           TRUE);  // Wait flag   
  1103.    
  1104.    
  1105.             // deal with the error code   
  1106.    
  1107.             if (!bResult)   
  1108.    
  1109.             {   
  1110.    
  1111.                 port->ProcessErrorMessage("GetOverlappedResults() in ReadFile()");   
  1112.    
  1113.             }   
  1114.    
  1115.         }  // close if (!bRead)   
  1116.    
  1117.    
  1118.         LeaveCriticalSection(&port->m_csCommunicationSync);   
  1119.    
  1120.    
  1121.         // notify parent that a byte was received   
  1122.    
  1123.         ::SendMessage((port->m_pOwner)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);   
  1124.    
  1125.     } // end forever loop   
  1126.    
  1127.    
  1128. }   
  1129.    
  1130.    
  1131. //   
  1132.    
  1133. // Write a string to the port   
  1134.    
  1135. //   
  1136.    
  1137. void CSerialPort::WriteToPort(char *string)   
  1138.    
  1139. {   
  1140.    
  1141.     assert(m_hComm != 0);   
  1142.    
  1143.    
  1144.     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));   
  1145.    
  1146.     strcpy(m_szWriteBuffer, string);   
  1147.    
  1148.     m_nWriteSize = strlen(string);   
  1149.    
  1150.    
  1151.     // set event for write   
  1152.    
  1153.     SetEvent(m_hWriteEvent);   
  1154.    
  1155. }   
  1156.    
  1157.    
  1158. //   
  1159.    
  1160. // Return the device control block   
  1161.    
  1162. //   
  1163.    
  1164. DCB CSerialPort::GetDCB()   
  1165.    
  1166. {   
  1167.    
  1168.     return m_dcb;   
  1169.    
  1170. }   
  1171.    
  1172.    
  1173. //   
  1174.    
  1175. // Return the communication event masks   
  1176.    
  1177. //   
  1178.    
  1179. DWORD CSerialPort::GetCommEvents()   
  1180.    
  1181. {   
  1182.    
  1183.     return m_dwCommEvents;   
  1184.    
  1185. }   
  1186.    
  1187.    
  1188. //   
  1189.    
  1190. // Return the output buffer size   
  1191.    
  1192. //   
  1193.    
  1194. DWORD CSerialPort::GetWriteBufferSize()   
  1195.    
  1196. {   
  1197.    
  1198.     return m_nWriteBufferSize;   
  1199.    
  1200. }   
  1201.    
  1202.    
  1203.    
  1204. void CSerialPort::WriteToPort(char *string, int n)   
  1205.    
  1206. {   
  1207.    
  1208.     assert(m_hComm != 0);   
  1209.    
  1210.     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));   
  1211.    
  1212.     memcpy(m_szWriteBuffer, string, n);   
  1213.    
  1214.     m_nWriteSize = n;   
  1215.    
  1216.     //set event for write   
  1217.    
  1218.     SetEvent(m_hWriteEvent);   
  1219.    
  1220. }   
  1221.    
  1222.    
  1223. void CSerialPort::WriteToPort(LPCTSTR string)   
  1224.    
  1225. {   
  1226.    
  1227.     assert(m_hComm != 0);   
  1228.    
  1229.     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));   
  1230.    
  1231.     strcpy(m_szWriteBuffer, string);   
  1232.    
  1233.     m_nWriteSize = strlen(string);   
  1234.    
  1235.     //set event for write   
  1236.    
  1237.     SetEvent(m_hWriteEvent);   
  1238.    
  1239. }   
  1240.    
  1241.    
  1242. void CSerialPort::WriteToPort(LPCTSTR string, int n)   
  1243.    
  1244. {   
  1245.    
  1246.     assert(m_hComm != 0);   
  1247.    
  1248.     memset(m_szWriteBuffer, 0, sizeof(m_szWriteBuffer));   
  1249.    
  1250.     memcpy(m_szWriteBuffer, string, n);   
  1251.    
  1252.     m_nWriteSize = n;   
  1253.    
  1254.     //set event for write   
  1255.    
  1256.     SetEvent(m_hWriteEvent);   
  1257.    
  1258. }   
  1259.    
  1260.    
  1261. void CSerialPort::ClosePort()   
  1262.    
  1263. {   
  1264.    
  1265.     if (m_bThreadAlive)   
  1266.    
  1267.     {   
  1268.    
  1269.         MSG message;   
  1270.    
  1271.         while (m_bThreadAlive)   
  1272.    
  1273.         {   
  1274.    
  1275.             if(::PeekMessage(&message, m_pOwner->m_hWnd, 0, 0, PM_REMOVE))   
  1276.    
  1277.             {   
  1278.    
  1279.                 ::TranslateMessage(&message);   
  1280.    
  1281.                 ::DispatchMessage(&message);   
  1282.    
  1283.             }   
  1284.    
  1285.             SetEvent(m_hShutdownEvent);   
  1286.    
  1287.         }   
  1288.    
  1289.         TRACE("Thread ended\n");   
  1290.    
  1291.    
  1292.     }   
  1293.    
  1294.     if(m_szWriteBuffer != NULL)   
  1295.    
  1296.     {   
  1297.    
  1298.         delete [] m_szWriteBuffer;   
  1299.    
  1300.         m_szWriteBuffer = NULL;   
  1301.    
  1302.     }   
  1303.    
  1304.    
  1305.     if(m_hComm)   
  1306.    
  1307.     {   
  1308.    
  1309.         CloseHandle(m_hComm);   
  1310.    
  1311.         m_hComm = NULL;   
  1312.     }   
  1313. }   

 

0 0
原创粉丝点击