📄 portobj.cpp
字号:
// PortObj.cpp: implementation of the CPortObj class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "PortObj.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPortObj::CPortObj()
{
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_hIDComDev = NULL;
m_bOpened = FALSE;
m_nErrCode = ERROR_SUCCESS;
}
CPortObj::~CPortObj()
{
Close();
}
//取最后错误信息
void CPortObj::GetLastErrInfo( int& nErrCode,
LPSTR *lpszErrInfo,
int nSize)
{
int nLen = 0;
nLen = CString((char *)m_lpMsgBuf).GetLength();
nLen = min(nLen, nSize);
memcpy( lpszErrInfo,m_lpMsgBuf, nLen);
nErrCode = m_nErrCode;
}
//取最后一次错误,并翻译
void CPortObj::GetAndFormatLastErr()
{
LocalFree( m_lpMsgBuf );
m_nErrCode = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
m_nErrCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &m_lpMsgBuf,
0,
NULL
);
// MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
}
BOOL CPortObj::Open( int nPort,
int nBaud,
int nParity,
int nByteSize,
int nStopBits )
{
char szPort[15];
DCB dcb;
COMMTIMEOUTS CommTimeOuts;
wsprintf( szPort, "\\\\.\\COM%d", nPort );
m_hIDComDev = CreateFile( szPort,
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL );
if( m_hIDComDev == NULL ) return FALSE ;
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hIDComDev, &CommTimeOuts );
memset( &dcb, 0, sizeof( DCB ) );
dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = nByteSize;
dcb.Parity = nParity;
dcb.StopBits = nStopBits; //1个停止位
dcb.fBinary = TRUE ;
dcb.fParity = TRUE ;
dcb.fDtrControl=DTR_CONTROL_DISABLE;
dcb.fRtsControl=RTS_CONTROL_DISABLE;
dcb. fOutxCtsFlow=FALSE; // CTS output flow control
dcb. fOutxDsrFlow=FALSE; // DSR output flow control
dcb. fDsrSensitivity=FALSE; // DSR sensitivity
dcb. fTXContinueOnXoff=FALSE; // XOFF continues Tx
dcb. fOutX=FALSE; // XON/XOFF out flow control
dcb. fInX=FALSE; // XON/XOFF in flow control
dcb. fErrorChar=FALSE; // enable error replacement
dcb. fNull=FALSE; // enable null stripping
dcb. fAbortOnError=FALSE; // abort reads/writes on error
unsigned char ucSet;
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );
if( !SetCommState( m_hIDComDev, &dcb ) ||
!SetupComm( m_hIDComDev, 10000, 10000 ) ||
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_hIDComDev );
return( FALSE );
}
m_bOpened = TRUE;
return( m_bOpened );
}
BOOL CPortObj::Close( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( TRUE );
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
m_bOpened = FALSE;
m_hIDComDev = NULL;
// MessageBox(NULL,"关闭","1",0);
return( TRUE );
}
BOOL CPortObj::WriteCommByte( unsigned char ucByte )
{
BOOL bWriteStat;
DWORD dwBytesWritten;
bWriteStat = WriteFile( m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) )
{
if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) )
{
dwBytesWritten = 0;
}
else
{
GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
return( TRUE );
}
BOOL CPortObj::ChangeParity( int nParity ) //改变奇偶校验
{
DCB dcb;
GetCommState( m_hIDComDev, &dcb );
if ( dcb.Parity != nParity )
{
dcb.Parity = nParity;
if( !SetCommState( m_hIDComDev, &dcb ) )
return FALSE;
}
return TRUE;
}
int CPortObj::SendData( const char *pDataBuf, int nSendLen )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwBytesWritten = 0;
int i;
for( i=0; i<nSendLen; i++ )
{
WriteCommByte( pDataBuf[i] );
dwBytesWritten++;
}
return( (int) dwBytesWritten );
}
int CPortObj::GetPortBufDataLen( int *pnParityErrCode )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( pnParityErrCode != NULL ) *pnParityErrCode = dwErrorFlags;
return (int) ComStat.cbInQue;
}
int CPortObj::ReadData( void *pDataBuf, int nBufSize )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
BOOL bReadStatus;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );
dwBytesRead = (DWORD) ComStat.cbInQue;
if( nBufSize < (int) dwBytesRead ) dwBytesRead = (DWORD) nBufSize;
bReadStatus = ReadFile( m_hIDComDev, pDataBuf, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus )
{
if( GetLastError() == ERROR_IO_PENDING )
{
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return( (int) dwBytesRead );
}
return( 0 );
}
return( (int) dwBytesRead );
}
///////////////////////////////////////////////////////////////////////////
CFFPortObj::CFFPortObj()
{
CPortObj::CPortObj();
m_nPort = 0;
m_nBaud = 0;
m_nParity = 0;
m_nByteSize = 0;
m_nStopBits = 0;
m_bSharePort = FALSE; //端口共享标志,如果允许共享,则多次打开时,进行引用计数
m_bDataFrameAddr = FALSE; //数据帧带有地址
m_nAddrByteLen = 1; //地址的长度
m_nPortUserTotal = 0; //端口引用计数
m_nRxDataLen = 0; //接收缓冲区字节长度
m_nRxBufSize = 5000; //接收缓冲区大小
// char *m_pRxBuf = new char[5000]; //接收缓冲区指针
// memset( m_pRxBuf, 0 ,5000 );
}
CFFPortObj::~CFFPortObj()
{
Close();
CPortObj::~CPortObj();
// delete[] m_pRxBuf;
}
BOOL CFFPortObj::Open( int nPort,
int nBaud,
int nParity,
int nByteSize,
int nStopBits) //打开端口
{
if( IsOpened() )
{
if( m_bSharePort )
{
if( m_nPort != nPort
|| m_nBaud != nBaud
|| m_nParity != nParity
|| m_nByteSize != nByteSize
|| m_nStopBits != nStopBits
)
return FALSE;
m_nPortUserTotal++; //允许共享端口
return TRUE;
}
}
m_nPort = nPort;
m_nBaud = nBaud;
m_nParity = nParity;
m_nByteSize = nByteSize;
m_nStopBits = nStopBits;
//计算字节间隔
CalByteIntervalByBaud();
return CPortObj::Open( nPort, nBaud, nParity, nByteSize, nStopBits );
}
void CFFPortObj::CalByteIntervalByBaud()
{
float fFrameLen = 1.0f + m_nByteSize;
switch( m_nStopBits )
{
case ONESTOPBIT: // 1 stop bit
fFrameLen += 1.0f;
break;
case ONE5STOPBITS: //1.5 stop bits
fFrameLen += 1.5f;
break;
case TWOSTOPBITS: //2 stop bits
fFrameLen += 2.0f;
break;
default:
fFrameLen += 1.0f;
break;
}
if( m_nParity != NOPARITY )
{
fFrameLen += 1.0f;
}
m_nByteInterval = (int)(BYTE_INTERVAL_CONST + (fFrameLen * 1000.0/m_nBaud));
}
void CFFPortObj::SetByteInterval( int nTime )
{
m_nByteInterval = nTime;
if( m_nByteInterval < BYTE_INTERVAL_CONST )
m_nByteInterval = BYTE_INTERVAL_CONST;
}
BOOL CFFPortObj::Close() //关闭端口
{
if( !IsOpened() )
{
m_nPortUserTotal = 0;
return TRUE;
}
if( !m_bSharePort ) return CPortObj::Close();
//允许共享端口时,处理引用计数
m_nPortUserTotal--;
// char TotalNumInfo[10];
// sprintf(TotalNumInfo,"%d",m_nPortUserTotal);
// MessageBox(NULL,TotalNumInfo,"1",0);
if( m_nPortUserTotal <= 0 ) return CPortObj::Close();
return TRUE;
}
int CFFPortObj::ReadData( void *pDataBuf, int nBufSize ) //读接收缓冲区数据
{
//取串口缓冲区已经接收数据大小
int nPortDataLen = GetPortBufDataLen();
char *pReadBufTemp = new char[nPortDataLen];
//取串口缓冲区已经接收数据
nPortDataLen = CPortObj::ReadData( pReadBufTemp,nPortDataLen );
//将串口缓冲区数据放到自己的缓冲区
int nByteRead = nPortDataLen;
if( m_nRxDataLen + nPortDataLen >= m_nRxBufSize-1 )
{
nByteRead = m_nRxBufSize - m_nRxDataLen;
}
memcpy( &m_pRxBuf[m_nRxDataLen],pReadBufTemp, nByteRead);
m_nRxDataLen += nByteRead;
//将数据放到调用者的缓冲区
nByteRead = m_nRxDataLen;
if( nBufSize < m_nRxDataLen) nByteRead = nBufSize;
memcpy( pDataBuf,m_pRxBuf, nByteRead);
delete pReadBufTemp;
return nByteRead;
}
//发送数据
int CFFPortObj::SendData( const char *pDataBuf, int nSendLen )
{
return CPortObj::SendData( pDataBuf, nSendLen );
}
//改变奇偶校验
BOOL CFFPortObj::ChangeParity( int nParity )
{
return CPortObj::ChangeParity( nParity );
}
//取串口缓冲区字节长度
int CFFPortObj::GetPortBufDataLen( int *pnParityErrCode )
{
return CPortObj::GetPortBufDataLen( pnParityErrCode );
}
//取最后错误信息
void CFFPortObj::GetLastErrInfo( int& nErrCode,
LPSTR *lpszErrInfo,
int nSize)
{
CPortObj::GetLastErrInfo( nErrCode, lpszErrInfo, nSize );
}
//清除接收缓冲区
void CFFPortObj::ClearRxBuf()
{
//取串口缓冲区已经接收数据大小
int nPortDataLen = GetPortBufDataLen();
char *pReadBufTemp = new char[nPortDataLen];
//清除串口缓冲区数据
CPortObj::ReadData( pReadBufTemp,nPortDataLen );
delete pReadBufTemp;
// memset( m_pRxBuf, 0, m_nRxBufSize );
m_nRxDataLen = 0;
return;
}
//取接收缓冲区数据长度
int CFFPortObj::GetRxBufDataLen()
{
return( GetPortBufDataLen() + m_nRxDataLen );
}
void CFFPortObj::SetRxBufSize( int nSize )
{
// delete m_pRxBuf;
m_nRxDataLen = 0; //接收缓冲区字节长度
m_nRxBufSize = nSize; //接收缓冲区大小
// char *m_pRxBuf = new char[nSize]; //接收缓冲区指针
memset( m_pRxBuf, 0 ,nSize );
return;
}
BOOL CFFPortObj::SetShareMode( BOOL bSharePort )
{
m_bSharePort=bSharePort;
if( bSharePort ) //设置为共享
{
if( IsOpened() && m_nPortUserTotal <=0 )
{
m_nPortUserTotal++;
}
}
else //设置为非共享
{
if( IsOpened() && m_nPortUserTotal>1 ) //如果已经打开了多个实例
{
return FALSE;
}
}
return TRUE;
}
BOOL CFFPortObj::SendAndWaitReply(const char *pWriteBuf, //发送缓冲区
int nWriteLen, //发送长度
char *pReadBuf, //接收缓冲区
int nReadBufSize, //接收缓冲区大小
int& nReturnDataLen, //接收到的返回数据长度
int nMaxWaitFirstByteTime)//最大等待时间
{
int nAlreadyReceiveLen;
BOOL bSuccess = FALSE;
FASM_CLOCK ClkFirstByte;
FASM_CLOCK ClkByteInterval;
///////////////////////////////////////////////////////////////////////////////////
//清除接收缓冲区
ClearRxBuf();
///////////////////////////////////////////////////////////////////////////////////
//发送数据
if( m_bDataFrameAddr)//数据帧带有地址
{
//发送地址帧
ChangeParity( MARKPARITY ); //奇偶校验位为1
if( !SendData( pWriteBuf,m_nAddrByteLen) ) return FALSE;
Sleep(2);
//发送数据帧
ChangeParity( SPACEPARITY ); //奇偶校验位为0
int iByteLen = nWriteLen - m_nAddrByteLen;
if ( iByteLen > 0 )
{
if( !SendData( &pWriteBuf[m_nAddrByteLen], iByteLen) ) return FALSE;
}
}
else
{
//发送数据
if( !SendData( pWriteBuf,nWriteLen) ) return FALSE;
}
///////////////////////////////////////////////////////////////////////////////////
//准备接收数据
nAlreadyReceiveLen = 0;
ClkFirstByte.Start();
MSG Msg;
while( TRUE )
{
//如果在指定时间内没有收到第一个字节,则返回FALSE
if( ClkFirstByte.IsTimePass(nMaxWaitFirstByteTime) )
return FALSE;
::Sleep(10);
//检索消息
if(::PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
{
::TranslateMessage( &Msg );
::DispatchMessage( &Msg );
}
nAlreadyReceiveLen = GetRxBufDataLen();
if( nAlreadyReceiveLen>0 )
break;
}
///////////////////////////////////////////////////////////////////////////////////
//等待发送结束
int nRxDataLenTemp = 0;
BOOL bReceiveStop = FALSE;
while( !bReceiveStop )
{
ClkByteInterval.Start();
//等待下一个字节
while(TRUE)
{
//查询串口接收缓冲区内字节数
nRxDataLenTemp = GetRxBufDataLen();
if( nAlreadyReceiveLen < nRxDataLenTemp ) //在允许两个字节的时间间隔内收到了新的字符
{
nAlreadyReceiveLen = nRxDataLenTemp;
break;
}
//判断是否已经接收结束,如果在允许两个字节的时间间隔内没有收到了新的字符,则认为结束了
if( ClkByteInterval.IsTimePass(m_nByteInterval) )
{
bReceiveStop = TRUE;
break;
}
::Sleep(1);
//检索消息
if(::PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
{
::TranslateMessage( &Msg );
::DispatchMessage( &Msg );
}
}
}
///////////////////////////////////////////////////////////////////////////////////
//将接收到的字节放到调用者制定的缓冲区
nAlreadyReceiveLen = GetRxBufDataLen();
nReturnDataLen = ReadData(pReadBuf, nReadBufSize);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -