📄 comm.cpp
字号:
// Comm.cpp: implementation of the CComm class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CommPort.h"
#include "Comm.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define TIMEOUT 200
#define READTOTALTIMEOUTMULTIPLIER 6
#define WRITETOTALTIMEOUTMULTIPLIER 6
#define READTOTALTIMEOUTCONSTANT 600
#define WRITETOTALTIMEOUTCONSTANT 600
extern CCommPortApp theApp;
BOOL CComm::m_bLogDebug = FALSE;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CComm::CComm()
{
m_idComDev = NULL;
m_bConnected = FALSE;
m_nCommPort = 1;
//m_osWrite, m_osRead ;
//m_CommTimeOuts;
m_Baud = 9600;
m_cParity = 'F';
m_nDataBit = 8;
m_fStopBit = 1.0f;
m_Timeout = 300;
m_nTimeInterval = 300;
m_nTickLast = 0;
m_pFileLog = NULL;
m_bParamSetted = FALSE;
m_nWriteLog = LOG_AS_ASCII;
}
CComm::~CComm()
{
if(m_bConnected)
Close();
}
void CComm::GetCommReady()
{
long lTickCount = GetTickCount();
if(abs(lTickCount - m_nTickLast) < m_nTimeInterval)
{
Sleep(m_nTimeInterval - abs(lTickCount - m_nTickLast));
}
m_nTickLast = GetTickCount();
}
void CComm::SetReadyComm()
{
m_nTickLast = GetTickCount();
}
bool CComm::Open()
{
if(m_bConnected)
return true;
if(!m_bParamSetted)
{
m_bParamSetted = TRUE;
LoadDefaultSettings();
}
if(m_bLogDebug && m_nWriteLog != NO_LOG)
{
if(m_pFileLog == NULL)
{
CString strFileLog;
CreateDirectory(theApp.m_strPath + "\\Debug", NULL);
strFileLog.Format("%s\\Debug\\DebugCom%d.log", theApp.m_strPath, m_nCommPort);
m_pFileLog = fopen(strFileLog, "w+t");
if(m_pFileLog)
fputs(CString("Begin running:....") + strEndLine, m_pFileLog);
}
}
DCB dcb;
char szCom[32];
sprintf(szCom,"\\\\.\\COM%d", m_nCommPort);
// open a COMM
if((m_idComDev = //m_COM_ADR: the Handle of openned COM
CreateFile( (LPCTSTR)szCom, //pCommInfoNeed->m_COM_ADR,
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL ) ) == (HANDLE) -1 )
{
return false;
}
else
{
// 设置传送结束及接收到字符两个标志
SetCommMask(m_idComDev, EV_TXEMPTY | EV_RXCHAR ) ;
// 设置COMM口的发送缓冲区及接收缓冲区
SetupComm(m_idComDev, 4096, 4096 ) ;
// purge any information in the buffer
PurgeComm( m_idComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
// set up for overlapped I/O
m_CommTimeOuts.ReadIntervalTimeout = 400;
m_CommTimeOuts.ReadTotalTimeoutMultiplier = READTOTALTIMEOUTMULTIPLIER ;
m_CommTimeOuts.ReadTotalTimeoutConstant = (DWORD)m_Timeout ;
m_CommTimeOuts.WriteTotalTimeoutMultiplier = WRITETOTALTIMEOUTMULTIPLIER ;
m_CommTimeOuts.WriteTotalTimeoutConstant = WRITETOTALTIMEOUTCONSTANT ;
SetCommTimeouts(m_idComDev, &(m_CommTimeOuts) ) ;
dcb.DCBlength = sizeof( DCB ) ;
GetCommState(m_idComDev, &(dcb) ) ;
dcb.BaudRate = m_Baud;
dcb.ByteSize = (BYTE)m_nDataBit;
//set the stop bit
if (m_fStopBit == 1.0f)
{
dcb.StopBits = (BYTE) 0x00;
}
else if (m_fStopBit == 1.5f)
{
dcb.StopBits = (BYTE) 0x01;
}
else if (m_fStopBit == 2.0f)
{
dcb.StopBits = (BYTE) 0x02;
}
//set the Parity
if (m_cParity == 'T' || m_cParity == 'O')
{
dcb.fParity = 1;
dcb.Parity = ODDPARITY;
}
else if (m_cParity == 'E' )
{
dcb.fParity = 1;
dcb.Parity = EVENPARITY;
}
else if (m_cParity == 'M' )
{
dcb.fParity = 1;
dcb.Parity = MARKPARITY;
}
else if (m_cParity == 'B' || m_cParity == 'S')
{
dcb.fParity = 1;
dcb.Parity = SPACEPARITY;
}
else
{
dcb.fParity = 0;
dcb.Parity = NOPARITY ;
}
if( !SetCommState(m_idComDev, &(dcb) ) )
{
CloseHandle(m_idComDev);
m_idComDev = NULL;
return false;
}
}
m_osWrite.Offset = 0 ;
m_osWrite.OffsetHigh = 0 ;
m_osRead.Offset = 0 ;
m_osRead.OffsetHigh = 0 ;
// create I/O event used for overlapped reads / writes
m_osWrite.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (m_osWrite.hEvent == NULL)
{
//LocalFree( &OverLapped ) ;FreeHandle
CloseHandle(m_idComDev);
m_idComDev = NULL;
return false;
}
m_osRead.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (m_osRead.hEvent == NULL)
{
CloseHandle(m_osWrite.hEvent);
m_osRead.hEvent = NULL;
CloseHandle(m_idComDev);
m_idComDev = NULL;
return false;
}
m_bConnected = TRUE;
return true;
}
void CComm::Close()
{
if(m_idComDev != NULL)
CloseHandle(m_idComDev);
m_bConnected = FALSE;
m_idComDev = NULL;
if(m_pFileLog)
{
fputs("End run!", m_pFileLog);
fclose(m_pFileLog);
m_pFileLog = NULL;
}
}
bool CComm::Write(const char* pData, int nLen)
{
m_mutex.Lock();
GetCommReady();
bool bOK = false;
if(Open())//确保端口打开
{
//MakesureLogType(pData, nLen);
// if(m_nWriteLog == LOG_AS_ASCII)
// {
// if(m_pFileLog)
// {
// fputs("W:" + CString(pData) + strEndLine, m_pFileLog);
// }
// }
// else
{
if(m_pFileLog)
{
fputs("W:" + GetHex((BYTE*)pData, nLen) + strEndLine, m_pFileLog);
}
}
bOK = true;
BOOL fWriteStat ;
DWORD dwBytesWritten ;
DWORD dwErrorFlags;
DWORD dwError;
COMSTAT ComStat;
char szError[ 128 ] ;
fWriteStat = WriteFile(m_idComDev, pData, nLen,
&dwBytesWritten, &(m_osWrite) ) ;
if (!fWriteStat)
{
if(GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(m_idComDev,
&(m_osWrite),
&dwBytesWritten, 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(m_idComDev, &dwErrorFlags, &ComStat ) ;
if(dwErrorFlags > 0)
{
wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
}
break;
} // end of if(dwError == ERROR_IO_INCOMPLETE)
} // end of while(!GetOverlappedResult( pP.........
}
else
{// else of if(GetLastError() == ERROR_IO_PENDING)
// some other error occurred
ClearCommError(m_idComDev, &dwErrorFlags, &ComStat ) ;
if (dwErrorFlags > 0)
{
wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
}
bOK = false;
}
} // fWriteStat = FALSE
}
SetReadyComm();
m_mutex.Unlock();
return bOK;
}
int CComm::Read(char* pData, int nLen)
{
m_mutex.Lock();
DWORD dwLength = 0;
if(Open())
{
BOOL bReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwError;
char szError[ 10 ] ;
// only try to read number of bytes in queue
//ClearCommError(m_idComDev, &dwErrorFlags, &ComStat ) ;
if (nLen > 0)
{
bReadStat = ReadFile(m_idComDev, pData,
nLen, &dwLength, &(m_osRead)) ;
if (!bReadStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(m_idComDev,
&m_osRead, &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(m_idComDev, &dwErrorFlags, &ComStat ) ;
if (dwErrorFlags > 0)
{
wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
}
break;
}
}
}
else
{
// some other error occurred
dwLength = 0 ;
ClearCommError(m_idComDev, &dwErrorFlags, &ComStat ) ;
if (dwErrorFlags > 0)
{
wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
}
}
}
}
}
m_mutex.Unlock();
// if(m_nWriteLog == LOG_AS_ASCII)
// {
// if(m_pFileLog)
// {
// fputs("R:" + CString(pData) + strEndLine, m_pFileLog);
// fflush(m_pFileLog);
// }
// }
// else
{
if(m_pFileLog)
{
fputs("R:" + GetHex((BYTE*)pData, dwLength) + strEndLine, m_pFileLog);
fflush(m_pFileLog);
}
}
// MakesureLogType(pData, nLen);
return dwLength;
}
void CComm::WritePrivateProfileInt( LPCSTR lpAppName, LPCSTR lpKeyName, INT nValue, LPCSTR lpFileName )
{
CString strTemp;
strTemp.Format("%d", nValue);
WritePrivateProfileString(lpAppName, lpKeyName, strTemp, lpFileName);
}
void CComm::LoadSaveCommPortParams(int nComm,
int &nBaud,
int &nDataBit,
float &fStopBit,
int &nTimeOut,
char &cParity,
long &nTimeInterval,
BOOL bLoadParams)
{
CString strIni = theApp.m_strPath + AfxGetAppName() + ".ini";
CString strComm;
strComm.Format("COM%d", nComm);
if(bLoadParams)
{
nBaud = GetPrivateProfileInt(strComm, "Baud", 9600, strIni);
nDataBit = GetPrivateProfileInt(strComm, "DataBit", 8, strIni);
fStopBit = GetPrivateProfileInt(strComm, "StopBit", 10, strIni)/10.0f;
nTimeOut = GetPrivateProfileInt(strComm, "TimeOut", 800, strIni);
cParity = GetPrivateProfileInt(strComm, "Parity", 'N', strIni);
nTimeInterval = GetPrivateProfileInt(strComm, "TimeInterval", 900, strIni);
m_bLogDebug = GetPrivateProfileInt("Debug", "Log", 0, strIni);
}
else
{
WritePrivateProfileInt(strComm, "Baud", nBaud, strIni);
WritePrivateProfileInt(strComm, "DataBit", nDataBit, strIni);
WritePrivateProfileInt(strComm, "StopBit", int(fStopBit*10), strIni);
WritePrivateProfileInt(strComm, "TimeOut", nTimeOut, strIni);
WritePrivateProfileInt(strComm, "Parity", (int)cParity, strIni);
WritePrivateProfileInt(strComm, "TimeInterval", nTimeInterval, strIni);
}
}
CString CComm::GetHex(const BYTE* pData, int nLen)
{
CString strHex;
BOOL bContainNoAscii = FALSE;
for(int i = 0; i < nLen; i++)
{
UINT uV = pData[i];
if(uV <= 12 || (uV >= 14 && uV < 32) || uV > 127)
bContainNoAscii = TRUE;
CString strV;
strV.Format("%02X ", uV);
strHex += strV;
}
if(!bContainNoAscii)
return pData;
else
return strHex;
}
void CComm::LoadDefaultSettings()
{
LoadSaveCommPortParams(m_nCommPort, m_Baud, m_nDataBit, m_fStopBit, m_Timeout, m_cParity, m_nTimeInterval, TRUE);
//m_bParamSetted = TRUE;
}
void CComm::MakesureLogType(char* pData, int nLen)
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -