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)
           sprintf( szMsg, "////.//COM%d", lngPort );
  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;    //奇偶校驗無效
  }
  else
  {
   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
//功能描述:關閉串口
//全局變量:
//調用模塊:
//作    者:葉帆
//日    期:2006年4月4日
//修 改 人:
//日    期:
//版    本:
//*************************************************************************
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
//功能描述:發送數據
//全局變量:
//調用模塊:
//作    者:葉帆
//日    期:2006年4月4日
//修 改 人:
//日    期:
//版    本:
//*************************************************************************
long SendData(BYTE *bytBuffer, long lngSize )
{
 try
 {
     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;
    }
 catch(...)
 {
  return -1;
 }
}

//*************************************************************************
//函 數 名:AcceptData
//輸    入:BYTE *bytBuffer,   數據
//      long lngSize       個數
//輸    出:long
//功能描述:讀取數據
//全局變量:
//調用模塊:
//作    者:葉帆
//日    期:2006年4月4日
//修 改 人:
//日    期:
//版    本:
//*************************************************************************
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;
     break;
    default:              //WaitForSingleObject 錯誤
     break;
    }
   }
  }

     return lngBytesRead;             
 
 }
 catch(...)
 {
  return -1;
 }
}

//*************************************************************************
//函 數 名:ClearAcceptBuffer
//輸    入:
//輸    出:long
//功能描述:清除接收緩衝區
//全局變量:
//調用模塊:
//作    者:葉帆
//日    期:2006年4月4日
//修 改 人:
//日    期:
//版    本:
//*************************************************************************
long ClearAcceptBuffer()
{
   try
   {
       if(m_COM_Handle  == NULL ) return( -1 );
       PurgeComm(m_COM_Handle,PURGE_RXABORT | PURGE_RXCLEAR);   //
   }
   catch(...)
   {
    return(1);
   }
 return(0);
}

//*************************************************************************
//函 數 名:ClearSendBuffer
//輸    入:
//輸    出:long
//功能描述:清除發送緩衝區
//全局變量:
//調用模塊:
//作    者:葉帆
//日    期:2006年4月4日
//修 改 人:
//日    期:
//版    本:
//*************************************************************************
long ClearSendBuffer()
{
 try
 {
       if(m_COM_Handle  == NULL ) return( -1 );
       PurgeComm(m_COM_Handle,PURGE_TXABORT |  PURGE_TXCLEAR);  //
    }
 catch(...)
 {
  return (1);
 }
 return(0);
}

 
發佈了16 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章