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

// Serial.cpp: implementation of the XSerial class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "XSerial.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//#define  COM_BUGSERIAL  1

#ifdef COM_BUGSERIAL
static void ComSerialPrintf(const BYTE *str,const int Len )
{
        char szFileName[256];
        char  buf[512];
        strcpy( szFileName, "c:\\CombugSerial.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 ComSerialBccPrintf(const BYTE *str,const int Len )
{
        char szFileName[256];
        char  buf[512];
        strcpy( szFileName, "c:\\CombugBccSerial.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 ComSerialErrorBccPrintf(const BYTE *str,const int Len )
{
        char szFileName[256];
        char  buf[512];
        strcpy( szFileName, "c:\\CombugErrorSerialCode.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


XSerial::XSerial()
{
        m_dwThreadID = 0;
        m_nSerialNo  = 0;
        memset( m_pRecvBufferForComm, 0, MAX_BYTE_FROM_COMM );
        memset( m_pEventCmd,0,SIZE_OF_CMD_TO_GET_HIS);
        m_nPosInReadBuffer = 0;
        m_nMaxWaitingTime  = 0;        
        m_bWriting = false;
        m_bReading = false;
        m_bWaiting = false;
        m_dwDelay = GetTickCount();
        m_szPath  =NULL;
        m_pDownloadCmd    = NULL;
        m_pRecvMessage    = NULL;
        m_pHistoryMessage = NULL;
        //m_nHistoryCmd     = 0xF0;
}

XSerial::~XSerial()
{
        SafeDelete( m_pDownloadCmd );
        SafeDelete( m_pHistoryMessage );
        SafeDelete( m_pRecvMessage );
}
//---------------------------------------------------------------------------
int XSerial::AddCmd( BYTE *pBuf,int nLen )
{  
  
   m_pDownloadCmd->AddContent( nLen,pBuf );
   return SERIAL_OK;
}

//--------------------------------------------------------------------------
int XSerial::InitSerial( const DWORD dwThreadID,
                                                 int   CommPortNo,
                                                 int   SerialNo,
                                                 const char *szPath,
                                                 const int nWaitTime,
                                                 const short bHaveMID )
{
    m_pHistoryMessage = new XArrays( MAX_SIZE_CMD_BUF );
        m_pRecvMessage    = new XArrays( MAX_SIZE_CMD_BUF );
        m_pDownloadCmd    = new XArrays( MAX_SIZE_CMD_BUF );    
        m_dwThreadID      = dwThreadID;
    m_nSerialNo       = SerialNo;
        m_nCommPortID     = CommPortNo;
        m_szPath          = (LPSTR)szPath;
        m_nMaxWaitingTime = nWaitTime;
        m_bHaveMID        = bHaveMID;

        if ( m_bHaveMID == 1 ) { m_bMark = 0xFF; } else { m_bMark = 0xA5; }

        //m_nHistoryCmd     = 0xF0;
    return SERIAL_OK;   //..sucessed init
}

//--------------------------------------------------------------------------
int XSerial::ReceiveBuf( int len,const BYTE *pBuff )
{    
        //m_dwDelay = GetTickCount();
    AtlTrace("Begin Read:%d\n", m_dwDelay);

    if ( m_bRecvAll || 0 == len )        return SERIAL_OK;
        if ( !m_bWaiting ) m_bWaiting = true;
        if ( !m_bReading ) m_bReading = true;

    BOOL bValid = TRUE;
        BYTE *pData = (BYTE*)pBuff;
        ATLASSERT(pData);
        if ( !pData ) return SERIAL_ERROR;
        if ( m_nPosInReadBuffer == 0 )
        {
                bValid = FALSE;
                for ( int i = 0 ; i < len; i++)
                {
                        if ( pData[i] ==  PUB_CMD_SOH )
                        {
                            bValid   = TRUE;
                                break;
                        }
                }
                pData += i;
                len   -= i;
        AtlTrace("InputLen:%d,丢弃%dByte\n",len,i);
        }

        if ( !bValid ) len = 0;
    int iTemp = len < MAX_BYTE_FROM_COMM ? len:MAX_BYTE_FROM_COMM;
        for ( int i = 0 ; i < len && m_nPosInReadBuffer < MAX_BYTE_FROM_COMM;i++)
        {
                m_pRecvBufferForComm[m_nPosInReadBuffer++] = pData[i];      
        }

    return ReceiveCompleted();
}
//--------------------------------------------------------------------------
int XSerial::ReceiveCompleted()
{
        int nSize = m_nPosInReadBuffer;
        if ( nSize < 11 )
        {
                //m_dwDelay  = GetTickCount();
                m_bReading = false;
                AtlTrace("End Delay: %d,ReadSize: %d \n",m_dwDelay,nSize);
                return SERIAL_OK;
        }        
        ATLASSERT( nSize < MAX_BYTE_FROM_COMM );
    if ( nSize >= MAX_BYTE_FROM_COMM ) return SERIAL_ERROR;
        RecvMessage( m_pRecvBufferForComm,nSize );

        m_bReading = false;
        m_bRecvAll = true;
        m_bWaiting = false;


        m_dwDelay  = GetTickCount();
    AtlTrace("End all Delay: %d,ReadSize: %d \n",m_dwDelay,nSize);
    return SERIAL_OK;
}
//--------------------------------------------------------------------------
int XSerial::SendCmd()
{           
        if ( m_bWaiting )
        {
                DWORD dwTemp = GetTickCount();
                if ( m_bWriting )
                {
                        if ( dwTemp < RECOVER_TIME + m_dwDelay )  return SERIAL_WRITING;
                }
                else if ( m_bReading )
                {
                        if ( dwTemp < m_nMaxWaitingTime + m_dwDelay ) //RECOVER_TIME
                        {
                                AtlTrace("正在等待读数据返回\n");
                                return SERIAL_READING;
                        }
                }
                else if ( dwTemp < m_nMaxWaitingTime + m_dwDelay )
                {
                        AtlTrace(" 正在等待指令发送\n");
                        return SERIAL_WRITING;
                }

                OffLineDetected();

            m_bWaiting = false;
        //m_dwDelay  = GetTickCount();
        if ( m_bRepeat )
                {
                    m_bRepeat = false;
                }
            else if (m_nWhichCmdSent == 1 ) //..temp
                {
                    m_pDownloadCmd->NextContent();
                }
            else
                {
            return SERIAL_READY_TO_ASK_NEW_HISTORY;
                }
        }

        if (GetTickCount() < m_dwDelay + 50 )
       return SERIAL_CMD_SEND_OK;
        
    int nLen = 0;
        while ( 1 )
        {
                CBufferArray BufferArray;
        m_pDownloadCmd->GetNewContent( &BufferArray );
                BYTE *pBuf = BufferArray.Data();
        nLen = BufferArray.Size();
        if ( pBuf != NULL)
                {
                        if ( pBuf[0] != 0x01 )
                        {
                                m_pDownloadCmd->NextContent();
                                continue;  
                        }
                        if (pBuf[4] == 0x99 && pBuf[5] == 0x99 )
                        {
                                m_pDownloadCmd->NextContent();
                                m_bIsBroadCast = true;  
                                m_bWaiting     = false;
                        }
                        else
                        {
                                m_bIsBroadCast = false;
                                m_bWaiting     = true;  
                        }
                        m_bWriting         = true;

                        m_nPosInReadBuffer = 0;
                        m_bRecvAll         = false;
                        m_dwDelay          = GetTickCount();

                        m_nWhichCmdSent  = 1;

                        WriteToPort( pBuf , nLen );

                        //m_dwDelay          = GetTickCount();

                        return SERIAL_CMD_SEND_OK;
                }
                else
                {
                        return SERIAL_READY_TO_ASK_NEW_HISTORY;
                }                
        }    
}
//--------------------------------------------------------------------------
int XSerial::WriteCompleted(bool bRpt)
{
    m_bWriting = false;

        if ( m_bIsBroadCast )
        {
                m_bWaiting     = true;
                m_bIsBroadCast = false;
                m_bReading     = false;
        }
        else
        {
                m_bWaiting = true;
                m_bReading = true;
                m_dwDelay  = GetTickCount();
                AtlTrace("End write: %d \n",m_dwDelay);
        }
        m_bRepeat = bRpt;
    return SERIAL_OK;
}
//--------------------------------------------------------------------------
int XSerial::RecvMessage( BYTE *buf,int nLen )
{
    ATLASSERT( buf );

    if ( !buf )        return SERIAL_ERROR;
        if( buf[4] ==0x99 || buf[5] == 0x99 ) return SERIAL_OK;

    if( buf[1] != PUB_CMD_w) return SERIAL_ERROR;

        BYTE nBCC = buf[nLen-1];

#ifdef COM_BUGSERIAL
    ComSerialPrintf(buf,nLen); //..no check
#endif

        if ( nBCC != MarkBCC(buf,nLen-1) )
        {
#ifdef COM_BUGSERIAL
                ComSerialErrorBccPrintf(buf,nLen); // check error
#endif
                m_bWaiting = false;
                return SERIAL_OK;
        }

#ifdef COM_BUGSERIAL
    ComSerialBccPrintf(buf,nLen); //..output BCC code
#endif

        WORD wParame =0 ;
        if (DECToBCD(buf[3]) >0 || DECToBCD(buf[3]) <=32)
        {
                wParame = (DECToBCD(buf[3]) << 8)+DECToBCD(buf[5]);
        }
        else { wParame = (WORD)DECToBCD(buf[5]); }
        //....
        if ( buf[0] == 0x01 &&  buf[1] == 0x77 && buf[7] ==0x02 &&
           ( DECToBCD(buf[5]) > 0 || DECToBCD(buf[5]) <=32) )
        {
                PostThreadMessage( m_dwThreadID,WM_ON_LINE_DETECTED,wParame,m_nSerialNo );
        }
        
    AtlTrace("接收操作指令: %d,地址: %d\n",buf[6],2,wParame);

        int nHisLen = 23;

        if ( m_bMark == 0xFF ) nHisLen = 25;

        if ( buf[6] == 0xF0 || buf[6] == 0xF5 )
        {
                BYTE *bHisBuf = new BYTE[nHisLen];
                memcpy(&bHisBuf[0],&buf[0],nHisLen);
        if ( buf[9] == m_bMark )
                {
                        AtlTrace("没有事件的控制器地址: %d\n",wParame);
                        PostThreadMessage( m_dwThreadID,WM_NO_RECORD,wParame ,m_nSerialNo );
                        //m_bWaiting = false;        
                        delete[] bHisBuf;
                        return SERIAL_OK;
                }
                else
                {
                        AtlTrace("正在收取事件的控制器地址: %d\n",wParame);
                        m_pHistoryMessage->AddContent( nHisLen, bHisBuf );
                        PostThreadMessage( m_dwThreadID,WM_HAS_RECORD,wParame ,m_nSerialNo );
                        //m_bWaiting = false;
                        delete[] bHisBuf;
                        return SERIAL_OK;
                }        
        }

        if (DECToBCD(buf[5]) !=  0x99 && DECToBCD(buf[4]) != 0x99 )
        {
                m_pRecvMessage->AddContent( nLen,buf );
                m_pDownloadCmd->NextContent();
        }

//    m_bWaiting = false;
    return SERIAL_OK;
}
//--------------------------------------------------------------------------
int XSerial::SetAskEventCmd( const BYTE *buf )
{
        if( NULL == buf )
                return SERIAL_ERROR;
        memcpy( m_pEventCmd, buf, SIZE_OF_CMD_TO_GET_HIS );
        return SERIAL_OK;
}
//--------------------------------------------------------------------------
int XSerial::AskForEvent()//( BYTE *pBuf, int nLen )
{
    if ( GetTickCount() < m_dwDelay + 40 )
                return SERIAL_OK;
    
        m_nWhichCmdSent = 0;
        m_nPosInReadBuffer = 0;
        m_bRecvAll = false;

        //m_dwDelay  = GetTickCount();

        AtlTrace("开始读历吏事件延时: %d\n",m_dwDelay);
        m_bWriting = true;
        m_bWaiting = true;
        
        DWORD dwTemp = GetTickCount();

        if ( m_bReading && ( dwTemp < m_nMaxWaitingTime + m_dwDelay ) ) return SERIAL_READING;
        
        WriteToPort( m_pEventCmd, SIZE_OF_CMD_TO_GET_HIS );

        return SERIAL_OK;
}
//--------------------------------------------------------------------------
void XSerial::GetRecenHistory( CBufferArray *pVal )
{
        if ( pVal == NULL ) return;
        m_pHistoryMessage->GetNewContent( pVal );
        m_pHistoryMessage->NextContent();
}
//--------------------------------------------------------------------------
void XSerial::GetRecenMessage( CBufferArray *pVal )
{
        if ( pVal == NULL ) return;
        m_pRecvMessage->GetNewContent( pVal );
        m_pRecvMessage->NextContent();
}
//--------------------------------------------------------------------------
int XSerial::OffLineDetected()
{
        BYTE *buf = NULL;
        int nLen = 0;
        CBufferArray ba;
        if( 1 == m_nWhichCmdSent )
        {
                m_pDownloadCmd->GetNewContent(&ba);                
                buf =ba.Data();
                nLen=ba.Size();
        }
        else
                buf = m_pEventCmd;

        if( NULL == buf )        return SERIAL_OK;

        WORD wParam = buf[5];
        if( 0x99 == wParam ) return SERIAL_OK;

        //.....
        wParam = 0;
        if ( DECToBCD(buf[3]) >= 1  && DECToBCD(buf[3]) <=32
                && DECToBCD(buf[5])>=1 && DECToBCD(buf[5])<=32 )
        {
                wParam = (DECToBCD(buf[3]) << 8)+DECToBCD(buf[5]);
        } else
        {
                if (DECToBCD(buf[5])>=1 && DECToBCD(buf[5])<=32)
                wParam = (WORD)DECToBCD(buf[5]);
                else  SERIAL_OK;

        }

        //.....
        if( buf[6] == 0xB3 )
        {
                wParam = 0x8000;
        }
        PostThreadMessage( m_dwThreadID, WM_OFF_LINE_DETECTED, wParam, m_nSerialNo );
        return SERIAL_OK;
}

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

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