AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > VC编程

在VC++6.0中用Win32 API实现串行通信

51自学网 2015-08-30 http://www.wanshiok.com

  三、程序代码

//////////////////////////////////////////////////////////////

#if !defined(_COMM_ACCESS_FUNCTIONS_AND_DATA)
#define _COMM_ACCESS_FUNCTIONS_AND_DATA
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define EVENTCHAR 0x0d
#define MAXBLOCKLENGTH 59

extern BYTE XwCom;
extern BYTE sCom1[5],sCom2[MAXBLOCKLENGTH+12];
extern sCom3[MAXBLOCKLENGTH+12];
extern BYTE opation;
extern short ComNum;

#define FC_DTRDSR 0x01
#define FC_RTSCTS 0x02
#define FC_XONXOFF 0x04
#define ASCII_BEL 0x07
#define ASCII_BS 0x08
#define ASCII_LF 0x0A
#define ASCII_CR 0x0D
#define ASCII_XON 0x11
#define ASCII_XOFF 0x13

class CComStatus
{
 public:
  HANDLE m_hCom;
  BYTE m_bComId;
  BYTE m_bByteSize;
  BYTE m_bStopBits;
  BYTE m_bParity;
  DWORD m_dwBaudRate;

  //WORD m_fChEvt;

  char m_bEvtChar;
  DWORD m_fBinary;
  BOOL m_bConnected;
  BOOL m_fXonXoff;
  BOOL m_bFlowCtrl;
  OVERLAPPED m_rdos;
  OVERLAPPED m_wtos;

  //functions

  CComStatus();
  CComStatus(BYTE bComId,BYTE bByteSize,BYTE bStopBits,BYTE bParity,
    DWORD dwBaudRate,/*WORD fChEvt,*/char bEvtChar,DWORD fBinary);
  BOOL OpenConnection();
  BOOL CloseConnection();
  BOOL SetupConnection();
  BOOL IsConnected();
};

UINT CommWatchProc( LPVOID lpData );
BOOL WriteCommBlock( CComStatus& comDev, LPSTR lpByte , DWORD dwBytesToWrite);
int ReadCommBlock(CComStatus& comDev,LPSTR lpszBlock, int nMaxLength );
int ReadCommBlockEx(CComStatus& comDev,LPSTR lpszBlock, int nMaxLength,DWORD dwTimeOut);
#endif

///////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "com232.h"

BYTE XwCom=0x40;
BYTE sCom1[5],sCom2[MAXBLOCKLENGTH+12],sCom3[MAXBLOCKLENGTH+12];
BYTE opation;
short ComNum;
CComStatus::CComStatus()
{
 m_hCom = NULL;
 m_bComId = (char)ComNum;//COM1
 m_bByteSize=8;
 m_bStopBits=ONESTOPBIT;
 m_bParity=NOPARITY;
 m_dwBaudRate=9600;
 m_bEvtChar=EVENTCHAR;
 m_fBinary=1;
 m_bConnected = FALSE;
 m_bFlowCtrl = FC_XONXOFF ;
 m_fXonXoff = FALSE;
}

CComStatus::CComStatus(BYTE bComId,BYTE bByteSize,BYTE bStopBits,BYTE bParity,DWORD dwBaudRate,/*WORD fChEvt,*/char bEvtChar,DWORD fBinary)
{
 m_hCom = NULL;
 m_bComId = bComId;
 m_bByteSize=bByteSize;
 m_bStopBits=bStopBits;
 m_bParity=bParity;
 m_dwBaudRate=dwBaudRate;
 m_bEvtChar=bEvtChar;
 m_fBinary=fBinary;
 m_bConnected = FALSE;
 m_bFlowCtrl = FC_XONXOFF ;
 m_fXonXoff = FALSE;
}

BOOL CComStatus::OpenConnection()
{
 char csCom[10];
 COMMTIMEOUTS CommTimeOuts ;
 if((m_bComId < 0) || (m_bComId > 4))
  return FALSE;//从COM1到COM4
 if(m_hCom)//if already open
 return FALSE;

 //OVERLAPPED包含异步I/O信息

 m_rdos.Offset = 0;
 m_rdos.OffsetHigh = 0;
 m_rdos.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
 if(m_rdos.hEvent == NULL)
  return FALSE;
 m_wtos.Offset = 0;
 m_wtos.OffsetHigh = 0;
 m_wtos.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
 if(m_wtos.hEvent == NULL)
 {
  CloseHandle(m_rdos.hEvent);
  return FALSE;
 }

 wsprintf(csCom,"COM%d",m_bComId);

 m_hCom = CreateFile(csCom,GENERIC_READ | GENERIC_WRITE, 0,NULL, OPEN_EXISTING,ILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);

 if(m_hCom == INVALID_HANDLE_VALUE) {
  //dwError = GetLastError();
  // handle error
  return FALSE;
 }
 else
 {
  SetCommMask( m_hCom, EV_RXCHAR ) ; // get any early notifications
  SetupComm( m_hCom, 4096, 4096 ) ; // setup device buffers
  // purge any information in the buffer

  PurgeComm( m_hCom, PURGE_TXABORT | PURGE_RXABORT |PURGE_TXCLEAR | PURGE_RXCLEAR ) ;

  // set up for overlapped I/O

  DWORD dwTemp = 1000 / (this->m_dwBaudRate / 8);
  CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
  CommTimeOuts.ReadTotalTimeoutMultiplier = 0;//((dwTemp > 0) ? dwTemp : 1);
  CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;

  // CBR_9600 is approximately 1byte/ms. For our purposes, allow
  // double the expected time per character for a fudge factor.

  CommTimeOuts.WriteTotalTimeoutMultiplier =2*CBR_9600/this->m_dwBaudRate;//( npTTYInfo ) ;
  CommTimeOuts.WriteTotalTimeoutConstant = 0;//1000 ;

  SetCommTimeouts( m_hCom, &CommTimeOuts ) ;
 }
 if(!SetupConnection())
 {
  CloseConnection();
  return FALSE;
 }
 EscapeCommFunction( m_hCom, SETDTR );
 m_bConnected = TRUE;
 return TRUE;
}

BOOL CComStatus::CloseConnection()
{
 if (NULL == m_hCom)
  return ( TRUE ) ;
 // set connected flag to FALSE
 m_bConnected = FALSE;
 // disable event notification and wait for thread
 // to halt
 SetCommMask( m_hCom, 0 ) ;
 EscapeCommFunction( m_hCom, CLRDTR ) ;
 // purge any outstanding reads/writes and close device handle
 PurgeComm( m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
 CloseHandle( m_hCom ) ;
 m_hCom = NULL;

 // change the selectable items in the menu

 CloseHandle(m_rdos.hEvent);
 CloseHandle(m_wtos.hEvent);
 return ( TRUE ) ;
}

BOOL CComStatus::SetupConnection()
{
 BOOL fRetVal ;
 BYTE bSet ;
 DCB dcb ;
 if(m_hCom == NULL)
  return FALSE;
 dcb.DCBlength = sizeof( DCB ) ;
 GetCommState( m_hCom, &dcb ) ;
 dcb.BaudRate = this->m_dwBaudRate;
 dcb.ByteSize = this->m_bByteSize;
 dcb.Parity = this->m_bParity;
 dcb.StopBits = this->m_bStopBits ;
 dcb.EvtChar = this->m_bEvtChar ;
 // setup hardware flow control
 bSet = (BYTE) ((m_bFlowCtrl & FC_DTRDSR) != 0) ;
 dcb.fOutxDsrFlow = bSet ;
 if (bSet)
  dcb.fDtrControl = DTR_CONTROL_HANDSHAKE ;
 else
  dcb.fDtrControl = DTR_CONTROL_ENABLE ;
 bSet = (BYTE) ((m_bFlowCtrl & FC_RTSCTS) != 0) ;
 dcb.fOutxCtsFlow = bSet ;
 if (bSet)
  dcb.fRtsControl = RTS_CONTROL_HANDSHAKE ;
 else
  dcb.fRtsControl = RTS_CONTROL_ENABLE ;
 // setup software flow control
 bSet = (BYTE) ((m_bFlowCtrl & FC_XONXOFF) != 0) ;
 dcb.fInX = dcb.fOutX = bSet ;
 dcb.XonChar = ASCII_XON ;
 char xon = ASCII_XON ;
 dcb.XoffChar = ASCII_XOFF ;
 char xoff = ASCII_XOFF ;
 dcb.XonLim = 100 ;
 dcb.XoffLim = 100 ;
 // other various settings
 dcb.fBinary = TRUE ;
 dcb.fParity = TRUE ;
 fRetVal = SetCommState( m_hCom, &dcb ) ;
 return ( fRetVal ) ;
} // end of SetupConnection()

BOOL CComStatus::IsConnected()
{
 return m_bConnected;
}

UINT CommWatchProc( LPVOID lpData )
{
 DWORD dwEvtMask ;
 //NPTTYINFO npTTYInfo = (NPTTYINFO) lpData ;
 OVERLAPPED os ;
 int nLength ;
 //BYTE abIn[ MAXBLOCK + 1] ;

 CComStatus * pCom = (CComStatus *)lpData;
 memset( &os, 0, sizeof( OVERLAPPED ) ) ;
 // create I/O event used for overlapped read

 os.hEvent = CreateEvent( NULL, // no security
  TRUE, // explicit reset req
  FALSE, // initial event reset
  NULL ) ; // no name

 if (os.hEvent == NULL)
 {
  MessageBox( NULL, "Failed to create event for thread!", "TTY Error!",MB_ICONEXCLAMATION | MB_OK ) ;
  return ( FALSE ) ;
 }
 if (!SetCommMask( pCom->m_hCom, EV_RXCHAR ))
  return ( FALSE ) ;
 char buf[256];
 while ( pCom->m_bConnected )
 {
  dwEvtMask = 0 ;
  WaitCommEvent( pCom->m_hCom, &dwEvtMask, NULL );
  if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
  {
   if ((nLength = ReadCommBlock( *pCom, (LPSTR) buf, 255 )))
   {
    //WriteTTYBlock( hTTYWnd, (LPSTR) abIn, nLength ) ;
    buf[nLength]='/0';
    AfxMessageBox(buf);
   }
  }
 }
 CloseHandle( os.hEvent ) ;
 return( TRUE ) ;
} // end of CommWatchProc()

int ReadCommBlock(CComStatus& comDev,LPSTR lpszBlock, int nMaxLength )
{
 BOOL fReadStat ;
 COMSTAT ComStat ;
 DWORD dwErrorFlags;
 DWORD dwLength;
 DWORD dwError;

 char szError[ 10 ] ;

 // only try to read number of bytes in queue

 ClearCommError( comDev.m_hCom, &dwErrorFlags, &ComStat ) ;
 dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;

 if (dwLength > 0)
 {
  fReadStat = ReadFile( comDev.m_hCom, lpszBlock,dwLength, &dwLength, &(comDev.m_rdos) ) ;
  if (!fReadStat)
  {
   if (GetLastError() == ERROR_IO_PENDING)
   {
    OutputDebugString("/n/rIO Pending");
    while(!GetOverlappedResult( comDev.m_hCom ,&(comDev.m_rdos), &dwLength, TRUE ))
    {
     dwError = GetLastError();
     if(dwError == ERROR_IO_INCOMPLETE)
      // normal result if not finished
      continue;
     else
     {
      // an error occurred, try to recover
      wsprintf( szError, "<CE-%u>", dwError ) ;
      ClearCommError( comDev.m_hCom , &dwErrorFlags, &ComStat ) ;
      break;
     }
    }
   }
   else
   {
    // some other error occurred
    dwLength = 0 ;
    ClearCommError( comDev.m_hCom , &dwErrorFlags, &ComStat ) ;
   }
  }
 }
 return ( dwLength ) ;
} // end of ReadCommBlock()

int ReadCommBlockEx(CComStatus& comDev,LPSTR lpszBlock, int nMaxLength,DWORD dwTimeOut)
{
 LPSTR lpOffset=lpszBlock;
 int nReadCount = 0;
 char chBuf;
 //time_t beginTime,endTime;
 if(!comDev.m_hCom)
  return 0;
 if(dwTimeOut <= 0)
  return 0;
 MSG msg;
 //time(&beginTime);
 DWORD dwLastTick,dwNowTick,dwGoneTime;
 dwGoneTime = 0;
 dwLastTick = GetTickCount();
 dwNowTick = dwLastTick;
 // double diftime;
 do
 {
  if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  {
   ::TranslateMessage(&msg);
   ::DispatchMessage(&msg);
  }
  if(ReadCommBlock(comDev,&chBuf,1) > 0)
  {
   //TRACE("----get a char----/n");
   *lpOffset = chBuf;
   lpOffset ++;
   nReadCount ++;
  }
  dwNowTick = GetTickCount();
  if(dwNowTick < dwLastTick)
  {
   dwLastTick = dwNowTick;
  }

  dwGoneTime = dwNowTick - dwLastTick;

  //TRACE("gon time = %lu/n",dwGoneTime);

 }while((nReadCount < nMaxLength) && (dwGoneTime < dwTimeOut));
 return (nReadCount);
}//end ReadCommBlockEx

BOOL WriteCommBlock( CComStatus& comDev, LPSTR lpByte , DWORD dwBytesToWrite)
{
 BOOL fWriteStat ;
 DWORD dwBytesWritten ;
 DWORD dwErrorFlags;
 DWORD dwError;
 DWORD dwBytesSent=0;
 COMSTAT ComStat;

 char szError[ 128 ] ;

 fWriteStat = WriteFile( comDev.m_hCom , lpByte, dwBytesToWrite,&dwBytesWritten, &( comDev.m_wtos) ) ;
 if (!fWriteStat)
 {
  if(GetLastError() == ERROR_IO_PENDING)
  {
   while(!GetOverlappedResult( comDev.m_hCom,&(comDev.m_wtos), &dwBytesWritten, TRUE ))
   {
    dwError = GetLastError();
    if(dwError == ERROR_IO_INCOMPLETE)
    {
     // normal result if not finished
     dwBytesSent += dwBytesWritten;
     continue;
    }
    else
    {
     // an error occurred, try to recover
     wsprintf( szError, "<CE-%u>", dwError ) ;
     ClearCommError( comDev.m_hCom, &dwErrorFlags, &ComStat ) ;
     break;
    }
   }
   dwBytesSent += dwBytesWritten;
   if( dwBytesSent != dwBytesToWrite )
    wsprintf(szError,"/nProbable Write Timeout: Total of %ld bytes sent", dwBytesSent);
   else
    wsprintf(szError,"/n%ld bytes written", dwBytesSent);
   OutputDebugString(szError);
  }
  else
  {
   // some other error occurred
   ClearCommError( comDev.m_hCom, &dwErrorFlags, &ComStat ) ;
   return ( FALSE );
  }
 }
 return ( TRUE ) ;
} // end of WriteCommBlock()

  四、小结

  以上给出了用Win32 API设计串行通信的基本思路,在实际应用中,我们可以利用Win32 API设计出满足各种需要的串行通信程序。

 
 
说明
:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。

上一篇:谈谈VC在工程机械及自动化行业中的应用  下一篇:在VC++项目中为MDI主框架窗口添加位图