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

📄 serialport.cpp

📁 采用文档类方法实现的一种串口通讯协议。可以借鉴参考
💻 CPP
字号:
/*
**	FILENAME			CSerialPort.h
**
**	PURPOSE				This class can read, write one serial port.
**
**	CREATION DATE		04-22-2005
**	LAST MODIFICATION	05-17-2005
**
**	AUTHOR				Yuangang Huang
**
**
*/

#include "stdafx.h"
#include "SerialPort.h"

#include <assert.h>
//
// Constructor
//
CSerialPort::CSerialPort()
{
	m_hComm = NULL;
}

//
// delete serial handle
//
CSerialPort::~CSerialPort()
{
	if (m_hComm != NULL)
	{
		CloseComPort(m_hComm);
		m_hComm = NULL;
	}
}

//
// Initialize the serial port. 
//
BOOL CSerialPort::InitPort(CWnd* pPortOwner,	// the owner (CWnd) of the port (receives message)
						   UINT  portnr,		// portnumber (1..4)
						   UINT  baud,			// baudrate
						   char  parity,		// parity 
						   UINT  databits,		// databits 
						   UINT  stopbits		// stopbits 
						   )	
{
	ASSERT((portnr > 0) && (portnr < 5));
	ASSERT(pPortOwner != NULL);

	// set the serial port and save the owner window handle
	m_pOwner = pPortOwner;
	m_nPortNr = portnr;

	BOOL bResult = FALSE;
	char *szPort = new char[50];
	char *szBaud = new char[50];

	// if the port is already opened: close it
	if (m_hComm != NULL)
	{
		CloseComPort(m_hComm);
		m_hComm = NULL;
	}

	// prepare port strings
	sprintf(szPort, "COM%d", portnr);
	sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);

	// get a handle to the port
	m_hComm = CreateFile(szPort,						// communication port string (COMX)
					     GENERIC_READ | GENERIC_WRITE,	// read/write types
					     0,								// comm devices must be opened with exclusive access
					     NULL,							// no security attributes
					     OPEN_EXISTING,					// comm devices must use OPEN_EXISTING
					     FILE_FLAG_OVERLAPPED,			// Async I/O
					     0);							// template must be 0 for comm devices

	if (m_hComm == INVALID_HANDLE_VALUE)
	{
		// port not found
		delete [] szPort;
		delete [] szBaud;

		return FALSE;
	}

	COMMTIMEOUTS	CommTimeouts;	
	// set the timeout values
	CommTimeouts.ReadIntervalTimeout = 1000;
	CommTimeouts.ReadTotalTimeoutMultiplier = 0;
	CommTimeouts.ReadTotalTimeoutConstant = 0;
	CommTimeouts.WriteTotalTimeoutMultiplier = 0;
	CommTimeouts.WriteTotalTimeoutConstant = 0;

	// set timeout
	if (SetCommTimeouts(m_hComm, &CommTimeouts))
	{						   
		if (GetCommState(m_hComm, &m_dcb))		//Get DCB
		{
		//	m_dcb.fRtsControl = RTS_CONTROL_ENABLE;		// set RTS bit high!
			if (BuildCommDCB(szBaud, &m_dcb))
			{
				if (SetCommState(m_hComm, &m_dcb))
					TRACE("Com Setup is finished\n"); // normal operation... continue
				else
				{
					TRACE("SetCommState FAILED\n");
					return FALSE;
				}		//end SetCommState()
			}
			else
			{
				TRACE("BuildCommDCB FAILED\n");
				return FALSE;
			}		//end BuildCommDCB()
		}
		else
		{
			TRACE("GetCommState FAILED\n");
			return FALSE;
		}		//end GetCommState()
	}
	else
	{
		TRACE("SetCommTimeouts FAILED\n");
		return FALSE;
	}		//end SetCommTimeouts()

	delete [] szPort;
	delete [] szBaud;
	
	// Set the Data Terminal Ready line
	EscapeCommFunction(m_hComm, SETDTR);
	// Set the Request to Send line
	EscapeCommFunction(m_hComm, SETRTS);
	// flush the port
	PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
		
	return TRUE;
}


//
// Return the serial DCB structure 
//
DCB CSerialPort::GetDCB()
{
	return m_dcb;
}


//
//Write single byte or string to port
//
BOOL CSerialPort::WriteData(BYTE *mOutBuf, DWORD mNeedWrite, DWORD &mWriten)
{
	BOOL	success;
	OVERLAPPED	ov;

	success = FALSE;
	memset(&ov, 0, sizeof(ov));
	ov.hEvent = CreateEvent(0, TRUE, FALSE, 0);

	success = WriteFile(m_hComm, mOutBuf, mNeedWrite, &mWriten, &ov);
	if(!success)
	{
	//	::AfxMessageBox("Fail to send ENQ");			//used when synchronization
	//	CloseComPort(m_hComm);
	//	return FALSE;
		if (GetLastError() == ERROR_IO_PENDING)
		{	
			BOOL pRet = GetOverlappedResult(m_hComm, &ov, &mWriten, TRUE);
			if (!pRet)
			{
				TRACE("Error TO Written\n");
				CloseHandle(ov.hEvent);
				return false;
			}
		}
		
	}
	
	CloseHandle(ov.hEvent);
	return TRUE;
}


//
//close serial port
//
void CSerialPort::CloseComPort(HANDLE comHandle)
{
	// Clear the Data Terminal Ready line
	EscapeCommFunction(comHandle, CLRDTR);
	// Clear the Request to Send line
	EscapeCommFunction(comHandle, CLRRTS);

	CloseHandle(comHandle);
}


//
//Read data from serial port
//
BOOL CSerialPort::ReadData(BYTE *mInBuf, DWORD mNeedRead, DWORD &mRead)
{
	BOOL	success;
	OVERLAPPED	ov;
	DWORD	Event = 0;
	BOOL	Ret = FALSE;

	success = FALSE;
	memset(&ov, 0, sizeof(ov));
	ov.hEvent = CreateEvent(0, TRUE, FALSE, 0);
	
//	Ret = SetCommMask(m_hComm, EV_RXCHAR);
//	Ret = WaitCommEvent(m_hComm, &Event, &ov);

//	Sleep(50);
	success = ReadFile(m_hComm, mInBuf, mNeedRead, &mRead, &ov);
	if(!success)  // || (mRead == 0))
	{
		if ( GetLastError () == ERROR_IO_PENDING)
		{
			while(!GetOverlappedResult(m_hComm, &ov, &mRead, TRUE ))
			{
				DWORD dwError = GetLastError();
				if(dwError == ERROR_IO_INCOMPLETE) 
					continue;
			}
		}
		
		//::AfxMessageBox("Error response from device for serial nember.");		//used when synchronization
		//CloseComPort(m_hComm);
		//return FALSE;
	}

	CloseHandle(ov.hEvent);
	return TRUE;
}


BOOL CSerialPort::GetData(BYTE *I_Buf, DWORD I_NeedWrite, BYTE *O_Buf)
{
	DWORD ByteCount = 0;
	DWORD ReceiveCount = 0;

	//com communication
	int Ret = WriteData(I_Buf, I_NeedWrite, ByteCount);
	if (Ret)
	{
		//if writing successfully, then read data from com
		Ret = ReadData(O_Buf, VERPACKETMAX, ReceiveCount);	
	}
	else
	{
		return FALSE;
	}

	return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -