📄 serial.cpp
字号:
// Serial.cpp
#include "stdafx.h"
#include "Serial.h"
CSerial::CSerial()
{
// Initialize all its compenents
// parity verify
m_Parity = EVENPARITY;
// Data bits
m_DataBits = 8;
// Stop Bits
m_StopBits = ONESTOPBIT;
// Baud Rate
m_BaudRate = 9600;
// Serial Port
m_SerialPortNo = 1;
// Read Buffer
//ZeroMemory(m_ReadBuffer,BUFFERLENGTH);
// Set NULL to m_hIDComDev
m_hIDComDev = NULL;
// timeout number
m_nTimeOut = 1500;
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_hIDComDev = NULL;
m_bOpened = FALSE;
}
CSerial::~CSerial()
{
Close();
}
BOOL CSerial::Open( int nPort, int nBaud )
{
if( this->m_bOpened ) return( TRUE );
CString szPort;
DCB dcb;
this->m_SerialPortNo = nPort;
szPort = "COM";
if(nPort >= 10)
{
szPort += (char)(0x30 + nPort);
}
else
{
szPort += (char)(0x30+nPort%10);
szPort += ':';
}
m_hIDComDev = CreateFile( szPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,//FILE_ATTRIBUTE_NORMAL,
NULL );
if( m_hIDComDev == INVALID_HANDLE_VALUE )
{
AfxMessageBox(_T("串口已经被占用,请关闭占用串口的程序,然后重新启动本系统。"));
return( FALSE );
}
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hIDComDev, &CommTimeOuts );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
GetCommState( m_hIDComDev, &dcb );
dcb.DCBlength = sizeof( DCB );
// Baud Rate
dcb.BaudRate = m_BaudRate;
// Data bits
dcb.ByteSize = m_DataBits;
// Stop Bits
dcb.StopBits = m_StopBits;
// parity verify
dcb.Parity = m_Parity;
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();
LPVOID lpMsgBuf; //Windows will allocate
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,0, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //默认语言
(LPTSTR)&lpMsgBuf, 0, NULL );
//显示
::MessageBox(0, (LPCTSTR)lpMsgBuf, ("GetLastError"), MB_OK|MB_ICONINFORMATION );
//释放内存
::LocalFree( lpMsgBuf );
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 );
}
// Close the COM port specified by User, and set NULL to handle
BOOL CSerial::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;
return( TRUE );
}
BOOL CSerial::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 );
}
int CSerial::SendData( const unsigned char *buffer, int size ,BOOL isUpComm)
{
if( !m_bOpened || m_hIDComDev == NULL )
return( 0 );
DWORD dwBytesWritten = 0;
int i;
for( i=0; i<size; i++ )
{
WriteCommByte( buffer[i] );
dwBytesWritten++;
if(!isUpComm)
{
Sleep(5);
}
}
return( (int) dwBytesWritten );
}
int CSerial::ReadDataWaiting( void )
{
if( !m_bOpened || m_hIDComDev == NULL )
return( 0 );
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
return( (int) ComStat.cbInQue );
}
int CSerial::ReadData( void *buffer, int limit )
{
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( limit < (int) dwBytesRead )
dwBytesRead = (DWORD) limit;
bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus )
{
if( GetLastError() == ERROR_IO_PENDING )
{
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return( (int) dwBytesRead );
}
return( 0 );
}
return( (int) dwBytesRead );
}
void CSerial::SetBaudRate(int BaudRate)
{
// CBR_110 CBR_19200 CBR_300 CBR_38400 CBR_600 CBR_56000 CBR_1200 CBR_57600 CBR_2400
// CBR_115200 CBR_4800 CBR_128000 CBR_9600 CBR_256000 CBR_14400
this->m_BaudRate = BaudRate;
}
void CSerial::SetStopBits(BYTE nSettings)
{
// nSettings = ONESTOPBIT | ONE5STOPBITS | TWOSTOPBITS
if ((nSettings != ONESTOPBIT) && (nSettings != ONE5STOPBITS) && (nSettings !=TWOSTOPBITS))
this->m_StopBits = ONESTOPBIT;
else
this->m_StopBits = nSettings;
}
void CSerial::SetDataBits(BYTE nSettings)
{
// nSettings = 8,7,6,5
if ((nSettings != 8) && (nSettings != 7) && (nSettings != 6) && (nSettings != 5))
this->m_DataBits = 8;
else
this->m_DataBits = nSettings;
}
void CSerial::SetParity(BYTE bParitySettings)
{
// bParitySettings = EVENPARITY Even
// MARKPARITY Mark
// NOPARITY No parity
// ODDPARITY Odd
// SPACEPARITY Space
if ( (bParitySettings != EVENPARITY) &&
(bParitySettings != MARKPARITY) &&
(bParitySettings != NOPARITY) &&
(bParitySettings != ODDPARITY) &&
(bParitySettings != SPACEPARITY))
this->m_Parity = NOPARITY;
else
this->m_Parity = bParitySettings;
}
int unstrcat(unsigned char *ss1,int ss1Length,unsigned char *ss2,int ss2Length)
{
int i;
for (i=0;i<ss2Length;i++)
{
*(ss1+ss1Length+i) = *(ss2+i);
}
return ss1Length+ss2Length;
}
BOOL CSerial::SendCommand(unsigned char *sCommand,unsigned char *sCommandHeader, int nCommandLength, int nCommandHeaderLength, int nRespondLength)
{
int lens = 0;
int i,j,lnTimes = 0;
int lnCommandRespondPointer = 0;
unsigned char lsBuffer[BUFFERLENGTH];
BOOL lbIsRespondHeader ;
int lulen = 0;
//ZeroMemory(this->m_ReadBuffer,BUFFERLENGTH);
this->SendData(sCommand,nCommandLength,TRUE);
for(lnTimes = 0 ; lnTimes < 500 ; lnTimes++)
{
if (lens < nRespondLength)
{
Sleep(5);
//ZeroMemory(lsBuffer,BUFFERLENGTH);
lens += this->ReadData(lsBuffer,BUFFERLENGTH);
//strcat(this->m_ReadBuffer,lsBuffer);
lulen = unstrcat(this->m_ReadBuffer,lulen,lsBuffer,lens);
lnTimes ++;
}
else
{
// Seek the header of the command respond
for(i=0;i<lens;i++)
{
lbIsRespondHeader = TRUE;
for(j=0;j<nCommandHeaderLength;j++)
{
if((this->m_ReadBuffer[i+j] != *(sCommandHeader+j)) && (lbIsRespondHeader))
lbIsRespondHeader = FALSE;
}
if (lbIsRespondHeader)
{
// command respond header has been found
lnCommandRespondPointer =i;
i= lens+1;
j=nCommandHeaderLength+1;
}
}
// get the command respond string (first byte of buffer = first byte of respond)
// strcat(this->m_ReadBuffer,lsBuffer+lnCommandRespondPointer);
lulen = unstrcat(m_ReadBuffer,lulen,lsBuffer+lnCommandRespondPointer,lens-lnCommandRespondPointer);
// if the Respond command string length less than user specified length continue to read
// if((int)strlen(this->m_ReadBuffer) >= nRespondLength)
if (lulen >= nRespondLength)
{
return TRUE;
}
}
}
return FALSE;
}
/*
// send a query status command at first
// then read serial port buffer every 3ms,timeout 500 times
// if no respond or respond string not longer enough after 500 times, operation failed and return FALSE
BOOL CSerial::GetCommandRespond(unsigned char *Command, int CommandLength, unsigned char *CommandRespondHeader, int CommandRespondHeaderLength, unsigned char *RespondBuffer, int RespondLength)
{
int lntimes,i;
BOOL lbResult = FALSE;
int lnlen,lnHeader=0;
unsigned char lsBuf[BUFFERLENGTH];
unsigned char lsTempBuf[BUFFERLENGTH];
int lnBufLength=0,lnTempBufLength=0;
SendData(Command,CommandLength);
ZeroMemory(lsBuf,BUFFERLENGTH);
for(lntimes =0;lntimes<this->m_nTimeOut;lntimes++)
{
Sleep(80);
ZeroMemory(lsTempBuf,BUFFERLENGTH);
lnTempBufLength = ReadData(lsTempBuf,BUFFERLENGTH);
lnlen = unstrcat(lsBuf,lnBufLength,lsTempBuf,lnTempBufLength);
if (lnlen >= RespondLength)
{
if (lbResult == FALSE)
{
for(i=0;i<lnlen-RespondLength+1;i++)
{
if ((*(lsBuf+i)==*(CommandRespondHeader+0)) &&
(*(lsBuf+i+1) == *(CommandRespondHeader+1)) &&
(*(lsBuf+i+2) == *(CommandRespondHeader+2)))
{
lnHeader = i;
i=1500;
lbResult = TRUE;
}
}
}
if(((lnlen - lnHeader) >= RespondLength) &&
(lbResult == TRUE))
{
unstrcat(this->m_ReadBuffer,0,lsBuf+lnHeader,lnlen - lnHeader);
unstrcat(RespondBuffer,0,lsBuf+lnHeader,lnlen - lnHeader);
return lbResult;
}
}
}
unstrcat(this->m_ReadBuffer,0,lsBuf+lnHeader,lnlen - lnHeader);
unstrcat(RespondBuffer,0,lsBuf+lnHeader,lnlen - lnHeader);
return lbResult;
}
*/
// send a query status command at first
// then read serial port buffer every 3ms,timeout 500 times
// if no respond or respond string not longer enough after 500 times, operation failed and return FALSE
BOOL CSerial::GetCommandRespond(unsigned char *Command, int CommandLength, unsigned char *CommandRespondHeader, int CommandRespondHeaderLength, unsigned char *RespondBuffer, int RespondLength)
{
BOOL lbResult = FALSE;
BOOL lbisFound = FALSE;
int i;
unsigned char lsReturnBuffer[2000];
unsigned char lsTempBuffer[2000];
int lnReturnBufferLength = 0,lnTempBufferLength = 0;
int lnRespondHeaderPos;
int m;
//PurgeComm(this->m_hIDComDev, PURGE_RXCLEAR);
//this->SendData(Command,CommandLength,TRUE);
ZeroMemory(lsReturnBuffer,1500);
//for(i=0;i<this->m_nTimeOut;i++)
for(i=0;i<1000;i++)
{
// receive data from serial port every 3 ms
if((i % 10) == 0)
Sleep(1);
lnTempBufferLength = this->ReadData(lsTempBuffer,1500);
for(m = 0;m < lnTempBufferLength;m++)
{
if (lnReturnBufferLength + m <= 1500)
{
*(lsReturnBuffer + lnReturnBufferLength + m) = *(lsTempBuffer + m);
}
}
lnReturnBufferLength += lnTempBufferLength;
// if receive data length equal or more than respond length,
// first step : find the header of respond string
if (lnReturnBufferLength >= RespondLength)
{
for(m = 0;m < lnReturnBufferLength;m++)
{
if(memcmp(lsReturnBuffer+m,CommandRespondHeader,3) == 0)
{
// has found the header
lnRespondHeaderPos = m;
// end this circle
m = lnReturnBufferLength;
lbisFound = TRUE;
}
}
}
// second step : if the respond string is full , retur the respond string
// and the lbResult = TRUE;
if (((lnReturnBufferLength - lnRespondHeaderPos) >= RespondLength) && (lbisFound))
{
// copy the respond data to the return parameter
for (m = 0;m < RespondLength;m++)
{
*(RespondBuffer + m) = *(lsReturnBuffer + lnRespondHeaderPos + m);
}
lbResult = TRUE;
return lbResult;
}
}
//return lbResult;
return FALSE;
}
void CSerial::GetRespondBuffer(unsigned char *sRespond)
{
// strcpy(sRespond,this->m_ReadBuffer);
unstrcat(sRespond,0,m_ReadBuffer,m_ReadBufferLength);
}
void CSerial::SetTimeOutNumber(int nTimeOut)
{
this->m_nTimeOut = nTimeOut;
}
void CSerial::GetCurrentStatus()
{
DCB ldcb;
::GetCommState(this->m_hIDComDev,&ldcb);
this->m_BaudRate = ldcb.BaudRate;
this->m_DataBits = ldcb.ByteSize;
this->m_StopBits = ldcb.StopBits;
this->m_Parity = ldcb.Parity;
}
BOOL CSerial::SetCurrentState()
{
DCB dcb;
dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
// Baud Rate
dcb.BaudRate = m_BaudRate;
// Data bits
dcb.ByteSize = m_DataBits;
// Stop Bits
dcb.StopBits = m_StopBits;
// parity verify
dcb.Parity = m_Parity;
return ::SetCommState(this->m_hIDComDev,&dcb);
}
void CSerial::SetSerialPortNo(int nSerial)
{
this->m_SerialPortNo = nSerial;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -