⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comm.cpp

📁 串口通讯封装源码 串口通讯封装源码 串口通讯封装源码
💻 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 + -