///////////////////////////////////////////
//ComPort.h
//////////////////////////////////////////
#include "StdAfx.h"#define COM_INIT_ERROR _T("串口初始化错误!")
#define COM_CONNECT_ERROR _T("串口连接错误!")#define GWL_PGPSINFO    0
#define GPSEXTRABYTES   sizeof( LONG )#define MAXPORTS        4#define RECEIVE_DATA    WM_USER+100#define RXQUEUE         4096
#define TXQUEUE         4096// cursor states#define CS_HIDE         0x00
#define CS_SHOW         0x01// Flow control flags#define FC_DTRDSR       0x01
#define FC_RTSCTS       0x02
#define FC_XONXOFF      0x04// ascii definitions#define ASCII_BEL       0x07
#define ASCII_BS        0x08
#define ASCII_LF        0x0A
#define ASCII_CR        0x0D
#define ASCII_XON       0x11
#define ASCII_XOFF      0x13// data structurestypedef struct tagGPSINFO
{
   HANDLE idComDev;
   BYTE bPort;
   BOOL fConnected;
   BYTE bByteSize,bParity,bStopBits;
   DWORD dwBaudRate;
   
   HANDLE hPostEvent,hWatchThread,hWatchEvent;
   HWND hTermWnd;
   DWORD dwThreadID;
   OVERLAPPED osWrite,osRead;
} GPSINFO, *PGPSINFO ;#define COMDEV( x ) (x -> idComDev)
#define PORT( x )   (x -> bPort)
#define CONNECTED( x ) (x -> fConnected)
#define BYTESIZE( x ) (x -> bByteSize)
#define PARITY( x ) (x -> bParity)
#define STOPBITS( x ) (x -> bStopBits)
#define BAUDRATE( x ) (x -> dwBaudRate)#define POSTEVENT( x ) (x -> hPostEvent)
#define HTHREAD( x ) (x -> hWatchThread)
#define THREADID( x ) (x -> dwThreadID)
#define WRITE_OS( x ) (x -> osWrite)
#define READ_OS( x ) (x -> osRead)// function prototypes (private)LRESULT NEAR CreateGPSInfo(HWND,BYTE nPort=1);
BOOL NEAR DestroyGPSInfo();int NEAR ReadCommBlock(LPSTR,int);
BOOL NEAR WriteCommBlock(LPSTR,DWORD);
BOOL NEAR OpenConnection();
BOOL NEAR SetupConnection();
BOOL NEAR CloseConnection();// function prototypes (public)DWORD FAR PASCAL CommWatchProc(LPSTR);
////////////////////////////////////
/// Comport.cpp
///////////////////////////////////
#include "StdAfx.h"
#include "ComPort.h"HWND hGPSWnd=NULL;
PGPSINFO npGPSInfo=NULL;LRESULT NEAR CreateGPSInfo(HWND hWnd,BYTE nPort)
{
        if (NULL==(npGPSInfo=(PGPSINFO)LocalAlloc(LPTR,sizeof(GPSINFO))))
return ((LRESULT)-1) ;        hGPSWnd=hWnd;
        
        COMDEV(npGPSInfo)=0;
        CONNECTED(npGPSInfo)=FALSE;
        PORT(npGPSInfo)=nPort;
        BAUDRATE(npGPSInfo)=CBR_9600;
        BYTESIZE(npGPSInfo)=8;
        PARITY(npGPSInfo)=NOPARITY;
        STOPBITS(npGPSInfo)=ONESTOPBIT;        WRITE_OS(npGPSInfo).Offset=0;
        WRITE_OS(npGPSInfo).OffsetHigh=0;
        READ_OS(npGPSInfo).Offset=0;
        READ_OS(npGPSInfo).OffsetHigh=0;
   
        // create I/O event used for overlapped reads / writes        READ_OS(npGPSInfo).hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
        if (READ_OS(npGPSInfo).hEvent==NULL)
        {       
  LocalFree( npGPSInfo ) ;
          return ((LRESULT)-1) ;
        }
        WRITE_OS(npGPSInfo).hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
        if (NULL==WRITE_OS(npGPSInfo).hEvent)
        {       
  CloseHandle(READ_OS(npGPSInfo).hEvent);
          LocalFree(npGPSInfo) ;
          return ((LRESULT)-1) ;
        }   return ( (LRESULT) TRUE ) ;
} BOOL NEAR DestroyGPSInfo()
{
        if (!npGPSInfo) return (FALSE);        if (CONNECTED(npGPSInfo)) CloseConnection();        CloseHandle(READ_OS(npGPSInfo).hEvent);
        CloseHandle(WRITE_OS(npGPSInfo).hEvent);
        CloseHandle(POSTEVENT(npGPSInfo));
        
        LocalFree(npGPSInfo);
        return (TRUE);
}BOOL NEAR OpenConnection()
{            
        char szPort[15];
        BOOL fRetVal;
        HCURSOR hOldCursor,hWaitCursor;
   
        HANDLE hCommWatchThread;
        DWORD dwThreadID;
        COMMTIMEOUTS CommTimeOuts;        if (!npGPSInfo) return (FALSE);
        
        hWaitCursor=LoadCursor(NULL,IDC_WAIT) ;
        hOldCursor=SetCursor(hWaitCursor) ;        wsprintf(szPort,"COM%d",PORT(npGPSInfo));        if ((COMDEV(npGPSInfo)=CreateFile(szPort,GENERIC_READ and GENERIC_WRITE,
                  0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL and FILE_FLAG_OVERLAPPED,
                  NULL))==(HANDLE)-1)
                return ( FALSE ) ;
        else
        {       
  SetCommMask(COMDEV(npGPSInfo),EV_RXCHAR);
                SetupComm(COMDEV(npGPSInfo),4096,4096);
                PurgeComm(COMDEV(npGPSInfo),PURGE_TXABORT and PURGE_RXABORT and PURGE_TXCLEAR and PURGE_RXCLEAR);
                CommTimeOuts.ReadIntervalTimeout=0xFFFFFFFF;
                CommTimeOuts.ReadTotalTimeoutMultiplier=0;
                CommTimeOuts.ReadTotalTimeoutConstant=1000;
                CommTimeOuts.WriteTotalTimeoutMultiplier=0;
                CommTimeOuts.WriteTotalTimeoutConstant=1000;
                SetCommTimeouts(COMDEV(npGPSInfo),&CommTimeOuts);
        }        fRetVal=SetupConnection();        if (fRetVal)
        {       CONNECTED(npGPSInfo)=TRUE;
                if (NULL==(hCommWatchThread=CreateThread((LPSECURITY_ATTRIBUTES)NULL,
                                    0,(LPTHREAD_START_ROUTINE)CommWatchProc,
                                    (LPVOID)NULL,0,&dwThreadID)))
                {       CONNECTED(npGPSInfo)=FALSE;
                        CloseHandle(COMDEV(npGPSInfo));
                        fRetVal=FALSE;
                }
                else
                {       THREADID(npGPSInfo)=dwThreadID;
                        HTHREAD(npGPSInfo)=hCommWatchThread;
                        EscapeCommFunction(COMDEV(npGPSInfo),SETDTR);
                }
        }
        else
        {       CONNECTED(npGPSInfo)=FALSE;
                CloseHandle(COMDEV(npGPSInfo));
        }        SetCursor(hOldCursor);
        return (fRetVal);
} BOOL NEAR SetupConnection()
{       BOOL fRetVal;
        DCB dcb;
        
        if (!npGPSInfo) return(FALSE);        dcb.DCBlength=sizeof(DCB);        GetCommState(COMDEV(npGPSInfo),&dcb);        dcb.BaudRate=BAUDRATE(npGPSInfo);
        dcb.ByteSize=BYTESIZE(npGPSInfo);
        dcb.Parity=PARITY(npGPSInfo);
        dcb.StopBits=STOPBITS(npGPSInfo);        dcb.fOutxDsrFlow=FALSE;
        dcb.fDtrControl=DTR_CONTROL_ENABLE;        dcb.fOutxCtsFlow=FALSE;
        dcb.fRtsControl=RTS_CONTROL_ENABLE;
        dcb.fInX=dcb.fOutX=FALSE;
        dcb.fBinary=TRUE;
        dcb.fParity=TRUE;        fRetVal=SetCommState(COMDEV(npGPSInfo),&dcb);
        return (fRetVal);
} BOOL NEAR CloseConnection()
{
        if (!npGPSInfo) return(FALSE);
        
        CONNECTED(npGPSInfo)=FALSE;
        
        SetCommMask(COMDEV(npGPSInfo),0);
        while(THREADID(npGPSInfo)!=0);        EscapeCommFunction(COMDEV(npGPSInfo),CLRDTR);
        PurgeComm(COMDEV(npGPSInfo),PURGE_TXABORT and PURGE_RXABORT and 
                                   PURGE_TXCLEAR and PURGE_RXCLEAR);
        CloseHandle(COMDEV(npGPSInfo));        return (TRUE);
} int NEAR ReadCommBlock(LPSTR lpszBlock,int nMaxLength)
{       
        BOOL       fReadStat ;
        COMSTAT    ComStat ;
        DWORD      dwErrorFlags;
        DWORD      dwLength;
        DWORD      dwError;
        
        if (!npGPSInfo) return(FALSE);        ClearCommError(COMDEV(npGPSInfo),&dwErrorFlags,&ComStat);
        dwLength=min((DWORD)nMaxLength,ComStat.cbInQue);        if (dwLength>0)
        {       fReadStat=ReadFile(COMDEV(npGPSInfo),lpszBlock,
                                    dwLength,&dwLength,&READ_OS(npGPSInfo));
                if (!fReadStat)
                {       if (GetLastError()==ERROR_IO_PENDING)
                        {       OutputDebugString("\n\rIO Pending");
                                while(!GetOverlappedResult(COMDEV(npGPSInfo),&READ_OS(npGPSInfo),&dwLength,TRUE))
                                {       dwError=GetLastError();
                                        if(dwError == ERROR_IO_INCOMPLETE) continue;
                                }
                                        
                        }
                        else
                        {       dwLength=0;
                                ClearCommError(COMDEV(npGPSInfo),&dwErrorFlags,&ComStat);
                        }
                }
        }
   return ( dwLength ) ;
}BOOL NEAR WriteCommBlock(LPSTR lpByte,DWORD dwBytesToWrite)
{       BOOL fWriteStat;
        DWORD dwBytesWritten;
        DWORD dwErrorFlags;
        DWORD dwError;
        COMSTAT ComStat;        if (!npGPSInfo) return(FALSE);        fWriteStat=WriteFile(COMDEV(npGPSInfo),lpByte,dwBytesToWrite,
                               &dwBytesWritten,&WRITE_OS(npGPSInfo));        if (!fWriteStat) 
        {       if(GetLastError()==ERROR_IO_PENDING)
                {       while(!GetOverlappedResult(COMDEV(npGPSInfo),
                                &WRITE_OS(npGPSInfo),&dwBytesWritten,TRUE))
                        {       dwError=GetLastError();
                                if(dwError == ERROR_IO_INCOMPLETE) continue;
                                else
                                {       ClearCommError(COMDEV(npGPSInfo),&dwErrorFlags,&ComStat);
                                        break;
                                }
                        }
                }
                else
                {       ClearCommError(COMDEV(npGPSInfo),&dwErrorFlags,&ComStat);
                        return ( FALSE );
                }
        }
        return ( TRUE ) ;} DWORD FAR PASCAL CommWatchProc(LPSTR)
{       DWORD dwEvtMask;
        OVERLAPPED os;
        int nLength;
        BYTE abIn[1024];        memset(&os,0,sizeof(OVERLAPPED));        // create I/O event used for overlapped read        os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
        if (os.hEvent==NULL)
        {       MessageBox(NULL,"Failed to create event for thread!","GPS Error!",MB_ICONEXCLAMATION and MB_OK);
                return ( FALSE ) ;
        }        if (!SetCommMask(COMDEV(npGPSInfo),EV_RXCHAR)) return (FALSE);
        
        while (CONNECTED( npGPSInfo))
        {       dwEvtMask=0 ;
                WaitCommEvent(COMDEV(npGPSInfo),&dwEvtMask,NULL);
                
                if ((dwEvtMask&EV_RXCHAR)==EV_RXCHAR)
                {       do
                        {       if (nLength=ReadCommBlock((LPSTR)abIn,1024))
                                {       //WriteCommBlock((LPSTR)abIn,nLength );
                                        *(abIn+nLength)=0;
                                        ::SendMessage(hGPSWnd,RECEIVE_DATA,nLength,(LONG)(LPSTR)abIn);
                        }
                        }
                        while ((nLength>0)&&(CONNECTED( npGPSInfo)));
                }
        }        CloseHandle(os.hEvent);
        THREADID(npGPSInfo)=0;
        HTHREAD(npGPSInfo)=NULL;
        return(TRUE);
}

解决方案 »

  1.   

    我不知道你所要处理的串口数据是不是要求非常及时,为什么不用CSerial类来完成这个工作呢?你只需把初始化函数稍微改动一下即可,然后用一个线程来处理串口数据即可,这样处理既方便又省时间,自己去写串口代码,调试就得花去好你几天时间,CSerial类在CodeGuru上有。
      

  2.   

    telan老兄,在你的线程函数CommWatchProc中曾定义了一个变量os,且串口
    是以异步方式打开的,为什幺在WaitCommEvent调用中没有用变量os?定义
    os又是用来干什幺的?
    能详细作答吗?多谢了,阿弥托福!
      

  3.   

    1.不好意思,其实CommWatchProc函数中的以下几句是无用的,忘了删掉。
         OVERLAPPED os; 
         memset(&os,0,sizeof(OVERLAPPED));        // create I/O event used for overlapped read        os.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
            if (os.hEvent==NULL)
            {       MessageBox(NULL,"Failed to create event for thread!","GPS Error!",MB_ICONEXCLAMATION and MB_OK);
                    return ( FALSE ) ;
            }
    2.//建立监视串口的线程
    //一般使用的顺序是:
    //CreateGPSInfo(被通知的窗口句柄,串口端口号1或2);
    //OpenConnection();建立联结它会调用SetupConnection
    //DestroyGPSInfo(); 解除联结它会调用CloseConnection
    //可以用ReadCommBlock/WriteCommBlock来读/写串口
    //CommWatchProc是监视串口的线程,由OpenConnection建立
    //当串口有数据来的时侯,它会通知'被通知的窗口句柄'的窗口数据传到的消息(自定义的)
    //::SendMessage(hGPSWnd,RECEIVE_DATA,nLength,(LONG)(LPSTR)abIn); LRESULT lReturn=CreateGPSInfo(m_hWnd,2);
    ASSERT(lReturn!=(LRESULT)(-1));
    if(lReturn==(LRESULT)(-1))
    {
    MessageBox(COM_INIT_ERROR,ERROR_TITLE);
    return FALSE;
    }
    BOOL bReturn=OpenConnection();
    ASSERT(bReturn);
    if(!bReturn)
    {
    MessageBox(COM_CONNECT_ERROR,ERROR_TITLE);
    return FALSE;
    }//自定义接收消息的处理函数
    ON_MESSAGE(RECEIVE_DATA,OnReceiveData) 
    LONG CXXX::OnReceiveData(UINT nLength,LONG lpData)
    {
    CString strReceiveData((LPSTR)lpData);
    m_strReceiveData+=strReceiveData;
             ....................
             ......................
             return 1;
    }
      

  4.   

    如果你的串口接的是数据采线的话,WaitCommEvent很少会阻塞该线程,
    但我接的是Keypad,他会等着用户输入,用户不输入,WaitCommEvent就
    阻塞该线程,于是问题就出来了:在结束该线程的时候,用户必须敲一
    下Keypad,否则,就一直等待!该怎样解决?
      

  5.   

    调用CloseConnection()应该可以结束线程啊!
    你可以根据需要修改该函数。
      

  6.   

    关于串口监视线程的WaitCommEvent(port->m_hComm, &Event, &port->m_ov);函数,重叠调用时,是不是返回后,还在一直监视着串口,直到由字符传来,再把m_OverlappedStruct.hEvent置为有信号? 
      

  7.   

    bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);
     
      if (!bResult)  
      { 
       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 */
        这一处不太明白,请解释一下好吗?立刻跳到了WaitForMultipleObjects()处吗?
         break;
        }
       }
      }
     else{... ...}
     
      /*谁来使read event 发生呢?*/
     Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);
     
     ... ...