天天看點

MFC序列槽操作(異步方式)源碼

這是我在一個背景系統摘抄出來的,在此基礎上完成了一個獨立的PPI讀寫程式(非DLL或控件方式)

//*************************************************************************

//**模 塊 名:YFCOM.cpp

//**說    明:YFSoft 版權所有2005 - 2006(C)

//**創 建 人:葉帆

//**日    期:2006年4月4日

//**修 改 人:

//**日    期:

//**描    述:序列槽操作

//**版    本:V1.0

#include "stdafx.h"

#include "yfcom.h"

//序列槽句柄

HANDLE m_COM_Handle;

//兩個信号全局變量(序列槽操作用)

OVERLAPPED m_OverlappedRead, m_OverlappedWrite;

//函 數 名:OpenCom

//輸    入:long lngPort,        序列槽号

//   char *cfgMessage,    配置資訊,形如"9600,e,8,1"

//   long lngInSize,      接收緩沖區大小

//   long lngOutSize      發送緩沖區大小

//輸    出:long

//功能描述:打開序列槽

//全局變量:

//調用子產品:

//作    者:葉帆

//日    期:2006年4月4日

//修 改 人:

//日    期:

//版    本:

long OpenCom(long lngPort,char *cfgMessage,long lngInSize,long lngOutSize)

{

 try

 {

     char szMsg[255];

  DCB dcb;

  //打開端口

  if (lngPort>9)

  else

     sprintf( szMsg, "COM%d", lngPort );

  //用異步方式讀寫序列槽

  m_COM_Handle  = CreateFile(szMsg, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED , NULL );  

  if( m_COM_Handle == NULL ) return( 2 );

  //清空異步讀寫參數

  memset(&(m_OverlappedRead), 0, sizeof (OVERLAPPED));

        memset(&(m_OverlappedWrite), 0, sizeof (OVERLAPPED));

  //設定dcb塊

  dcb.DCBlength = sizeof( DCB );         //長度

  GetCommState(m_COM_Handle , &dcb );

  //波特率,奇偶校驗,資料位,停止位  如:9600,n,8,1

        sprintf(szMsg,"COM%d:%s", lngPort,cfgMessage);

  BuildCommDCB(szMsg,&dcb);

     //------------------------------ 

  dcb.fBinary=TRUE;                      //二進制方式 

  dcb.fOutxCtsFlow=FALSE;                //不用CTS檢測發送流控制

  dcb.fOutxDsrFlow=FALSE;                //不用DSR檢測發送流控制

        dcb.fDtrControl=DTR_CONTROL_DISABLE;   //禁止DTR流量控制

  dcb.fDsrSensitivity=FALSE;             //對DTR信号線不敏感

  dcb.fTXContinueOnXoff=TRUE;            //檢測接收緩沖區

  dcb.fOutX=FALSE;                       //不做發送字元控制

  dcb.fInX =FALSE;                       //不做接收控制

  dcb.fErrorChar=FALSE;                  //是否用指定字元替換校驗錯的字元

  dcb.fNull=FALSE;                       //保留NULL字元

     dcb.fRtsControl=RTS_CONTROL_ENABLE;    //允許RTS流量控制

  dcb.fAbortOnError=FALSE;               //發送錯誤後,繼續進行下面的讀寫操作

  dcb.fDummy2=0;                         //保留

  dcb.wReserved=0;                       //沒有使用,必須為0

  dcb.XonLim=0;                          //指定在XOFF字元發送之前接收到緩沖區中可允許的最小位元組數

  dcb.XoffLim=0;                         //指定在XOFF字元發送之前緩沖區中可允許的最小可用位元組數

     dcb.XonChar=0;                         //發送和接收的XON字元

        dcb.XoffChar=0;                        //發送和接收的XOFF字元

  dcb.ErrorChar=0;                       //代替接收到奇偶校驗錯誤的字元

  dcb.EofChar=0;                         //用來表示資料的結束

  dcb.EvtChar=0;                         //事件字元,接收到此字元時,會産生一個事件

  dcb.wReserved1=0;                      //沒有使用

     //dcb.BaudRate =9600;                  //波特率

  //dcb.Parity=0;                        //奇偶校驗

  //dcb.ByteSize=8;                      //資料位

  //dcb.StopBits=0;                      //停止位

        //------------------------------

  if(dcb.Parity==0 )        // 0-4=None,Odd,Even,Mark,Space

  {

   dcb.fParity=FALSE;    //奇偶校驗無效

  }

   dcb.fParity=TRUE;     //奇偶校驗有效

        sprintf(szMsg,"COM%d:%d,%d,%d,%d (InSize:%ld,OutSize:%ld)", lngPort,dcb.BaudRate,dcb.Parity,dcb.ByteSize,dcb.StopBits,lngInSize,lngOutSize);

  //讀寫逾時設定

  COMMTIMEOUTS CommTimeOuts;

  //西門子參數

  CommTimeOuts.ReadIntervalTimeout =0;                                   //字元允許間隔ms   該參數如果為最大值,會使readfile指令立即傳回  

  CommTimeOuts.ReadTotalTimeoutMultiplier =0;                             //總的逾時時間(對單個位元組) 

  CommTimeOuts.ReadTotalTimeoutConstant = 2500;                           //多餘的逾時時間ms

  CommTimeOuts.WriteTotalTimeoutMultiplier =0;                            //總的逾時時間(對單個位元組)

  CommTimeOuts.WriteTotalTimeoutConstant = 2500;                          //多餘的逾時時間

  SetCommTimeouts( m_COM_Handle, &CommTimeOuts );

  //擷取信号句柄

  m_OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

        m_OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

  if( !SetCommState( m_COM_Handle, &dcb ) ||                   //判斷設定參數是否成功

   !SetupComm( m_COM_Handle, lngInSize, lngOutSize ) ||     //設定輸入和輸出緩沖區是否成功

         m_OverlappedRead.hEvent==NULL ||

       m_OverlappedWrite.hEvent==NULL)

  { 

       DWORD dwError = GetLastError();                     //擷取最後的錯誤資訊

        if( m_OverlappedRead.hEvent != NULL )  CloseHandle( m_OverlappedRead.hEvent );

          if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );

    CloseHandle( m_COM_Handle );

            m_COM_Handle=NULL;

    return dwError;

  return( 0 );

    }

 catch(...)

  return -1;

 }

}

//函 數 名:CloseCom

//輸    入:

//功能描述:關閉序列槽

long CloseCom()

   try

   {

 if(m_COM_Handle  == NULL ) return( 1 );

 SetCommMask(m_COM_Handle ,NULL);

    SetEvent(m_OverlappedRead.hEvent);

 SetEvent(m_OverlappedWrite.hEvent);

 if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );

 if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );

    if (CloseHandle( m_COM_Handle )==FALSE)return (2);

 m_COM_Handle  = NULL;

   }

   catch(...)

    return (3);

 return( 0 );

//函 數 名:SendData

//輸    入:BYTE *bytBuffer,   資料

//      long lngSize       個數

//功能描述:發送資料

long SendData(BYTE *bytBuffer, long lngSize )

     if( m_COM_Handle  == NULL ) return( -1 );

  DWORD dwBytesWritten=lngSize;

  BOOL bWriteStat;

  COMSTAT ComStat;

  DWORD   dwErrorFlags;

  ClearCommError(m_COM_Handle,&dwErrorFlags,&ComStat);

  bWriteStat=WriteFile(m_COM_Handle, bytBuffer, lngSize, &dwBytesWritten, &(m_OverlappedWrite));

  if(!bWriteStat)

     if(GetLastError()==ERROR_IO_PENDING)

     {

      GetOverlappedResult(m_COM_Handle,&(m_OverlappedWrite),&dwBytesWritten,TRUE); //等待直到發送完畢

     }

     else

             dwBytesWritten=0;

  return (long)dwBytesWritten;

//函 數 名:AcceptData

//功能描述:讀取資料

long AcceptData(BYTE *bytBuffer, long lngSize )

    try

     if( m_COM_Handle == NULL ) return( -1 );

  DWORD   lngBytesRead=lngSize;

  BOOL    fReadStat;

  DWORD   dwRes=0;

  //讀資料

  fReadStat=ReadFile(m_COM_Handle,bytBuffer,lngSize,&lngBytesRead,&(m_OverlappedRead)); 

  //Sleep(1);

  if( !fReadStat )

   if( GetLastError() == ERROR_IO_PENDING )                                   //重疊 I/O 操作在進行中

   {

    dwRes=WaitForSingleObject(m_OverlappedRead.hEvent,1000);   //等待,直到逾時

    switch(dwRes)

    {

    case WAIT_OBJECT_0:   //讀完成  

     if(GetOverlappedResult(m_COM_Handle,&(m_OverlappedRead),&lngBytesRead,FALSE)==0)

     {

      //錯誤

      return -2;

     }

     break;

    case WAIT_TIMEOUT:    //逾時

     return -1;

    default:              //WaitForSingleObject 錯誤

    }

   }

     return lngBytesRead;             

//函 數 名:ClearAcceptBuffer

//功能描述:清除接收緩沖區

long ClearAcceptBuffer()

       if(m_COM_Handle  == NULL ) return( -1 );

       PurgeComm(m_COM_Handle,PURGE_RXABORT | PURGE_RXCLEAR);   //

    return(1);

 return(0);

//函 數 名:ClearSendBuffer

//功能描述:清除發送緩沖區

long ClearSendBuffer()

       PurgeComm(m_COM_Handle,PURGE_TXABORT |  PURGE_TXCLEAR);  //

  return (1);

繼續閱讀