新闻  |   论坛  |   博客  |   在线研讨会
多线程串口管理代码(2)
yanqin | 2009-04-17 10:41:32    阅读:1653   发布文章

// CommPort.cpp: implementation of the XCommPort class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "XCommPort.h"
#include <stdio.h>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//#define  COM_BUGWRITE 1

#ifdef COM_BUGWRITE
static void ComWritePrintf(const BYTE *str,const int Len )
{
        char szFileName[256];
        char  buf[512];
        strcpy( szFileName, "c:\\WritePrintf.txt" );
        FILE *fpDebug = fopen( szFileName, "a" );
    memset(buf,0,Len * 3 +2);
        for( int i =0; i< Len; i++) sprintf(buf+(3*i),"%02X ",str[i]);
        fprintf( fpDebug, "%s\n", buf );
        fclose( fpDebug );
}

static void ComReadPrintf(const BYTE *str,const int Len )
{
        char szFileName[256];
        char  buf[512];
        strcpy( szFileName, "c:\\ReadPort.txt" );
        FILE *fpDebug = fopen( szFileName, "a" );
    memset(buf,0,Len * 3 +2);
        for( int i =0; i< Len; i++) sprintf(buf+(3*i),"%02X ",str[i]);
        fprintf( fpDebug, "%s\n", buf );
        fclose( fpDebug );
}

#endif //BUG


XCommPort::XCommPort(): m_bThreadAlive(0),
                        m_dwThreadID(NULL),
                                                m_hComm(NULL),
                                                m_nSizeToWrite(0)
{
        m_pWriteBuffer            = new BYTE[200];
        m_ovOverLapped.Offset     = 0;
        m_ovOverLapped.OffsetHigh = 0;
        m_ovOverLapped.hEvent     = NULL;        
}

XCommPort::~XCommPort()
{    
        CloseCommPort();
    SafeDeleteArray( m_pWriteBuffer );
}
//---------------------------------------------------------------------------
BOOL XCommPort::CloseCommPort()
{
        while (m_bThreadAlive)
        {
            SetEvent( m_hShutdownEvent );
        }
        ::CloseHandle(m_hComm);

    m_hComm = NULL;        
    return TRUE;
}
//---------------------------------------------------------------------------
DWORD XCommPort::CommThread(LPVOID pParame)
{
   XCommPort *Port       = (XCommPort*)pParame;  
   Port->m_bThreadAlive  = true;  
   DWORD BytesTransfered = 0;
   DWORD Event           = 0;    
   DWORD CommEvent       = 0;    
   DWORD dwError         = 0;    
   BOOL  bResult         = TRUE;  
   //.................................................
   if (Port->m_hComm)
   {
           ::PurgeComm( Port->m_hComm,
                           PURGE_RXCLEAR|
                                   PURGE_TXCLEAR|
                                   PURGE_RXABORT|
                                   PURGE_TXABORT);
   }
   for(;;)
   {
           bResult = WaitCommEvent(Port->m_hComm,
                                       &Event,
                                                           &Port->m_ovOverLapped);

           Event =  WaitForMultipleObjects(3,
                                              Port->m_hEventArray,
                                                                          false,
                                                                          INFINITE);
          
           switch( Event )
           {
           case 0:
                   {
               Port->m_bThreadAlive = false;
                           ExitThread( 100 );
                           break;
                   }
           case 1:
                   {
                           GetCommMask(Port->m_hComm,&CommEvent);
               if (CommEvent & EV_RXCHAR)
                                   Port->ReadData();
                           break;
                   }
           case 2:
                   {
                           Port->WriteData();
                           break;
                   }
           case WAIT_FAILED:
                   {
                           char *msg= new char[20];
                           sprintf(msg,"%8X\n",::GetLastError());
                           ATLTRACE(msg);
                           ::Sleep(1);
                           break;
                   }          
           }

   }

   return 0;
}
//---------------------------------------------------------------------------
int XCommPort::Create(const DWORD dwThreadID,
                                          const char *szPath,
                                          const BYTE bComID,const BYTE bSerialNo,
                                          const DWORD dwBaudRate,const BYTE bByteSize,
                                          const BYTE  bParity,const BYTE  bStopBits,
                                          const int nWaitTime,const short bHaveMID)
{
    if( !(InitCommPort(dwThreadID, bComID,bSerialNo,dwBaudRate,
                                           bByteSize,bParity,bStopBits)) )
                                          
        {
                CloseCommPort();
                return SERIAL_ERROR;
        }
        InitSerial(dwThreadID,bComID,bSerialNo,szPath,nWaitTime,bHaveMID); //(0)
        DetectComm();
        //SafeDelete(pInfo);
    return SERIAL_OK;
}
//---------------------------------------------------------------------------
BOOL XCommPort::DetectComm()
{
        DWORD ThreadID;
        m_hThread = CreateThread(NULL,0,CommThread,this,0,&ThreadID);
    if ( m_hThread == NULL )
    {
                return FALSE;
        }

    SetThreadPriority( m_hThread,THREAD_PRIORITY_TIME_CRITICAL );
    return TRUE;
}
//---------------------------------------------------------------------------
BOOL XCommPort::InitCommPort(DWORD dwThreadID,
                                                          BYTE bComID,
                                                          BYTE bSerialNo,
                                                          DWORD dwBaudRate,
                                                          BYTE bByteSize,
                                                          BYTE bParity,
                                                          BYTE bStopBits )
{
        char szSerialPortName[20];
        if( m_hShutdownEvent != NULL )
                ResetEvent( m_hShutdownEvent );
        m_hShutdownEvent = CreateEvent( NULL, true, false, NULL );
        while( m_bThreadAlive )
        {
                SetEvent( m_hShutdownEvent );
        }

        sprintf( szSerialPortName, "\\\\.\\COM%d", bComID );
        m_dwThreadID = dwThreadID;
        if( m_ovOverLapped.hEvent != NULL )
                ResetEvent( m_ovOverLapped.hEvent );
        m_ovOverLapped.hEvent = CreateEvent( NULL, true, false, NULL );

        if( m_hWriteEvent != NULL )
                ResetEvent( m_hWriteEvent );
        m_hWriteEvent = CreateEvent( NULL, true, false, NULL );

        m_hEventArray[0] = m_hShutdownEvent;
        m_hEventArray[1] = m_ovOverLapped.hEvent;
        m_hEventArray[2] = m_hWriteEvent;

        InitializeCriticalSection( &m_csCommunicationSync );
        EnterCriticalSection( &m_csCommunicationSync );

        m_hComm = CreateFile( szSerialPortName,
                GENERIC_READ|GENERIC_WRITE,
                0,
                NULL,
                OPEN_EXISTING,
                FILE_FLAG_OVERLAPPED,
                NULL );
        if( m_hComm == INVALID_HANDLE_VALUE )
        {
                LeaveCriticalSection( &m_csCommunicationSync );
                return FALSE;
        }
        COMMTIMEOUTS CommTimeouts;
        CommTimeouts.ReadIntervalTimeout = MAXDWORD;
        CommTimeouts.ReadTotalTimeoutConstant =0;
        CommTimeouts.ReadTotalTimeoutMultiplier = 0;
        CommTimeouts.WriteTotalTimeoutConstant =0;
        CommTimeouts.WriteTotalTimeoutMultiplier =0;
        if( !SetCommTimeouts( m_hComm, &CommTimeouts ) )
        {
                LeaveCriticalSection( &m_csCommunicationSync );
                return FALSE;
        }
        //if( !SetCommMask( m_hComm,
        //        EV_BREAK | EV_ERR | EV_RING
        //        | EV_RXCHAR | EV_RXFLAG | EV_CTS ) )
    if( !SetCommMask( m_hComm, EV_RXCHAR ) )
        {
                LeaveCriticalSection( &m_csCommunicationSync );
                return FALSE;
        }
        if( !SetupComm( m_hComm, 4096, 2048 ) )
        {
                LeaveCriticalSection( &m_csCommunicationSync );
                return FALSE;
        }
        if( !GetCommState( m_hComm, &m_dcb ) )
        {
                LeaveCriticalSection( &m_csCommunicationSync );
                return FALSE;
        }
        m_dcb.BaudRate =dwBaudRate;
        m_dcb.ByteSize =bByteSize;
        m_dcb.Parity = bParity;
        m_dcb.StopBits = bStopBits;
        m_dcb.fBinary = true;
        m_dcb.fParity = false;
        m_dcb.fInX = false;
        m_dcb.fOutX = false;
        m_dcb.fRtsControl = RTS_CONTROL_DISABLE; //ENABLE;
    m_dcb.fDtrControl = DTR_CONTROL_DISABLE;
        m_dcb.fOutxCtsFlow = FALSE;
    m_dcb.fOutxDsrFlow = FALSE;

        if( !SetCommState( m_hComm, &m_dcb ) )
        {
                LeaveCriticalSection( &m_csCommunicationSync );
                return FALSE;
        }
        m_bSerialNo = bSerialNo;
        PurgeComm( m_hComm, PURGE_RXCLEAR|PURGE_TXCLEAR
                |PURGE_RXABORT|PURGE_TXABORT );
        LeaveCriticalSection( &m_csCommunicationSync );
        return TRUE;
}
//---------------------------------------------------------------------------
BOOL XCommPort::ReadData()
{
        BOOL     bResult      = TRUE;
        DWORD    dwError      = 0;
        DWORD    dwBytesRead  = 0;
        DWORD    dwByteToRead = 0;
    COMSTAT  comstat;

        EnterCriticalSection( &m_csCommunicationSync );
    bResult = ClearCommError( m_hComm,&dwError,&comstat );
        LeaveCriticalSection( &m_csCommunicationSync );

    Sleep(27); //(0)
        dwByteToRead = comstat.cbInQue;


        BYTE *pBuf = new BYTE[dwByteToRead];

        if ( comstat.cbInQue > 0 )
        {
                EnterCriticalSection( &m_csCommunicationSync );
                m_ovOverLapped.Offset     = 0;
                m_ovOverLapped.OffsetHigh = 0;
                bResult = ::ReadFile( m_hComm,pBuf, comstat.cbInQue,
                                          &dwBytesRead, &m_ovOverLapped );
                if ( !bResult)
                {
                        if ( ERROR_IO_PENDING == GetLastError() )
                        {
                                ::GetOverlappedResult( m_hComm, &m_ovOverLapped,&dwBytesRead,TRUE );
                        }
                }
                LeaveCriticalSection(&m_csCommunicationSync);
        }
#ifdef COM_BUGWRITE
                ComReadPrintf(pBuf,dwBytesRead);
#endif
        ReceiveBuf(dwBytesRead,pBuf);
        delete[] pBuf;
        return TRUE;
}
//---------------------------------------------------------------------------
BOOL XCommPort::WriteData()
{        
        BOOL   bResult     = TRUE;
        DWORD  dwBytesSent = 0;
        ResetEvent( m_hWriteEvent );
    EnterCriticalSection( &m_csCommunicationSync );
        m_ovOverLapped.Offset     = 0;
        m_ovOverLapped.OffsetHigh = 0;

#ifdef COM_BUGWRITE
ComWritePrintf(m_pWriteBuffer,m_nSizeToWrite);
#endif

    ::PurgeComm( m_hComm,
                         PURGE_RXCLEAR|
                                 PURGE_TXCLEAR|
                                 PURGE_RXABORT|
                                 PURGE_TXABORT );

        bResult = ::WriteFile( m_hComm,
                                   m_pWriteBuffer,
                                   m_nSizeToWrite,
                                                   &dwBytesSent,
                                                   &m_ovOverLapped );

        if ( !bResult )
        {
                DWORD dwError = GetLastError();
                if (dwError == ERROR_IO_PENDING)                
                        ::GetOverlappedResult( m_hComm,
                                                   &m_ovOverLapped,
                                                   &dwBytesSent,
                                                                   TRUE );
        }
    WriteCompleted( false );
        LeaveCriticalSection( &m_csCommunicationSync );
    return TRUE;

}
//---------------------------------------------------------------------------
int XCommPort::WriteToPort(BYTE *Buf,int Length)
{
        if ( !m_bThreadAlive) return -1;

        EnterCriticalSection( &m_csCommunicationSync );

        m_nSizeToWrite = Length;

        ATLASSERT(Length < 200 );

        if ( Length>= 200 )
        {
                MessageBox(NULL,"write length >200","提示",MB_ICONWARNING);
                return 1;
        }

        memcpy( m_pWriteBuffer, Buf,Length );
        LeaveCriticalSection( &m_csCommunicationSync );

        SetEvent( m_hWriteEvent );

    return 0;
}

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客