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

📄 serialport.cpp

📁 Bluetooth HCI应用程序的编写
💻 CPP
字号:
#include "StdAfx.h"
#include ".\serialport.h"

CSerialPort::CSerialPort(void)
{
	m_hComm			= INVALID_HANDLE_VALUE;
//	m_hWriteThread	= NULL;
	m_hWatchThread	= NULL;

	m_fOpen			= FALSE;

	SetDCB();
	SetTimeouts();

	InitializeCriticalSection(&m_CriticalSection);

	m_osWrite.Offset		= 0;
	m_osWrite.OffsetHigh	= 0;
	m_osWrite.hEvent		= CreateEvent(NULL,FALSE,FALSE,NULL);
	
	m_osRead.Offset			= 0;
	m_osRead.OffsetHigh		= 0;
	m_osRead.hEvent			= CreateEvent(NULL,FALSE,FALSE,NULL);
}

CSerialPort::~CSerialPort(void)
{
	Close();

	DeleteCriticalSection(&m_CriticalSection);

	CloseHandle(m_osWrite.hEvent);
	CloseHandle(m_osRead.hEvent);
}

// property inquire
BOOL CSerialPort::IsOpen(void)
{
	return m_fOpen;
}

// port process
BOOL CSerialPort::Open(DWORD dwComPort,DWORD dwBaudrate,BYTE bByteBits,BYTE bStopBits,BYTE bParity)
{
	TCHAR			szComName[20];
	DWORD			dwResult = TRUE;
	DWORD			dwID;

	Close();

	wsprintf(szComName,"COM%d",dwComPort+1);
	m_hComm = CreateFile(szComName,
							GENERIC_READ|GENERIC_WRITE,0,NULL,
							OPEN_EXISTING,
							FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);
	if (INVALID_HANDLE_VALUE != m_hComm)
	{			
		SetDCB(dwBaudrate,bByteBits,bStopBits,bParity);
		if (FALSE != SetupConnect())
		{
			m_hWatchThread = CreateThread(NULL,0,WatchThreadProc,this,0,&dwID);
			if (NULL != m_hWatchThread)
			{
				;
			}
			else
			{
				CloseHandle(m_hComm);
				dwResult = FALSE;
			}
		}
		else	// setup port property error
		{
			CloseHandle(m_hComm);
			dwResult = FALSE;
		}
	}	// errror open port
	else
	{		
		dwResult = FALSE;
	}
	m_fOpen = dwResult;
	return dwResult;
}
BOOL CSerialPort::Close(void)
{
	if (TRUE == m_fOpen)
	{
		m_fOpen			= FALSE;
		PurgeComm(m_hComm,PURGE_TXABORT | PURGE_RXABORT);
		SetCommMask(m_hComm,EV_RXCHAR | EV_BREAK);
		WaitForSingleObject(m_hWatchThread,INFINITE);

		CloseHandle(m_hComm);
		CloseHandle(m_hWatchThread);
		m_hComm			= INVALID_HANDLE_VALUE;
		m_hWatchThread	= NULL;
	}
	return 0;
}

// set port property	
BOOL CSerialPort::SetupConnect()
{
	COMSTAT			ComStat;
	DWORD			dwError;
	DWORD			dwResult1,dwResult2,dwResult3,dwResult4,dwResult5;

	dwResult1 = SetCommState(m_hComm,&m_Dcb);
	dwResult2 = SetCommTimeouts(m_hComm,&m_CommTimeouts);
	dwResult3 = ClearCommError(m_hComm,&dwError,&ComStat);
	dwResult4 = SetupComm(m_hComm,1024,1024);
	dwResult5 = PurgeComm(m_hComm,PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR);
	
	return dwResult1 && dwResult2 && dwResult3 && dwResult4 && dwResult5;
}
void CSerialPort::SetDCB(DWORD dwBaudrate,BYTE bByteBits,BYTE bStopBits,BYTE bParity)
{
	m_Dcb.BaudRate	= dwBaudrate;
	m_Dcb.ByteSize	= bByteBits;
	m_Dcb.StopBits	= bStopBits;

	switch (bParity)
	{
		case NOPARITY:
			m_Dcb.fParity	= FALSE;
			m_Dcb.Parity	= bParity;
			break;

		case ODDPARITY:
		case EVENPARITY:
		case MARKPARITY:
		case SPACEPARITY:
			m_Dcb.fParity	= TRUE;
			m_Dcb.Parity	= bParity;
			break;
	}
}
void CSerialPort::SetDCB(DCB* pDcb)
{
	TCHAR	szDef[40] = "baud=9600 parity=N data=8 stop=1";

	if (NULL != pDcb)
	{
		memcpy(&m_Dcb,pDcb,sizeof(m_Dcb));
	}
	else
	{
		BuildCommDCB(szDef,&m_Dcb);

		m_Dcb.fOutxCtsFlow		= FALSE;
		m_Dcb.fOutxDsrFlow		= FALSE;
		m_Dcb.fDsrSensitivity	= FALSE;

		m_Dcb.fTXContinueOnXoff = FALSE;

		m_Dcb.fDtrControl		= DTR_CONTROL_ENABLE;
		m_Dcb.fRtsControl		= RTS_CONTROL_ENABLE;//RTS_CONTROL_TOGGLE;

		m_Dcb.fBinary			= TRUE;

		m_Dcb.XoffLim			= 0;
		m_Dcb.XonLim			= 0;

		m_Dcb.XoffChar			= 0x13;
		m_Dcb.XonChar			= 0x11;

		m_Dcb.fBinary			= TRUE;

		m_Dcb.fErrorChar		= FALSE;
		m_Dcb.fNull				= FALSE;
	}
}
void CSerialPort::SetTimeouts(COMMTIMEOUTS* pCommTimeouts)
{
	if (NULL != pCommTimeouts)
	{
		memcpy(&m_CommTimeouts,pCommTimeouts,sizeof(m_CommTimeouts));
	}
	else
	{
		m_CommTimeouts.ReadIntervalTimeout			= 20;
		m_CommTimeouts.ReadTotalTimeoutMultiplier	= 10;
		m_CommTimeouts.ReadTotalTimeoutConstant		= 100;
		m_CommTimeouts.WriteTotalTimeoutMultiplier	= 10;
		m_CommTimeouts.WriteTotalTimeoutConstant	= 100;
	}
}
void CSerialPort::SetFlowControl(DWORD dwDtrControl,DWORD dwRtsControl,
									BOOL fOutCtsFlow,BOOL fOutDsrFlow,							
									BOOL fOutX,BOOL fInX,char cXonChar,char cXoffChar)
{
	m_Dcb.fDtrControl	= dwDtrControl;
	m_Dcb.fRtsControl	= dwRtsControl;
	m_Dcb.fOutxCtsFlow	= fOutCtsFlow;
	m_Dcb.fOutxDsrFlow	= fOutDsrFlow;
	m_Dcb.fOutX			= fOutX;
	m_Dcb.fInX			= fInX;
	m_Dcb.XonChar		= cXonChar;
	m_Dcb.XoffChar		= cXoffChar;
}

// communication
BOOL CSerialPort::PortOutput(BYTE* pData,UINT uLen)
{
	DWORD			dwError;
	DWORD			dwResult = TRUE;
	DWORD			dwLen;
	
	if (NULL != m_osWrite.hEvent)
	{
		EnterCriticalSection(&m_CriticalSection);

		ClearCommError(m_hComm,&dwError,NULL);

		dwResult = WriteFile(m_hComm,pData,uLen,&dwLen,&m_osWrite);
		if (FALSE != dwResult)
		{
			dwResult = TRUE;
		}
		else	// Written data to port is error or not complete
		{
			dwResult = GetLastError();
			if (dwResult == ERROR_IO_PENDING)	// Sent data is pending
			{
				GetOverlappedResult(m_hComm,&m_osWrite,&dwLen,TRUE);
				dwResult = TRUE;
			}
			else
			{
				dwResult = FALSE;
			}
		}
		LeaveCriticalSection(&m_CriticalSection);

	}	// Created evnet handle is error
	else
	{
		dwResult = FALSE;
	}
	return dwResult;
}

BOOL CSerialPort::PortInput(BYTE* pData,UINT& uLen)
{
	DWORD					dwError;
	COMSTAT					cs;
	DWORD					dwResult = TRUE;
	DWORD					dwReadLen;
	
	if (NULL != m_osRead.hEvent)
	{
		EnterCriticalSection(&m_CriticalSection);

		ClearCommError(m_hComm,&dwError,&cs);
		uLen = uLen < cs.cbInQue ? uLen : cs.cbInQue;
		dwResult = ReadFile(m_hComm,pData,uLen,&dwReadLen,&m_osRead);
		if (FALSE != dwResult)
		{
			dwResult = TRUE;
		}
		else	// Written data to port is error or not complete
		{
			dwResult = GetLastError();
			if (ERROR_IO_PENDING == dwResult)	// received data is pending
			{
				GetOverlappedResult(m_hComm,&m_osRead,&dwReadLen,TRUE);
				dwResult = TRUE;
			}
			else
			{
				dwResult = FALSE;
			}
		}
		LeaveCriticalSection(&m_CriticalSection);
	}
	else	// Created evnet handle is error
	{
		dwResult = FALSE;
	}
	return dwResult;
}
// receive buffer using queue
#include <queue>
using namespace std;

queue<BYTE> g_qReceive;

// interface of device
BOOL CSerialPort::Send(BYTE* pData,UINT uLen)
{	
	return PortOutput(pData,uLen);
}
BOOL CSerialPort::Receive(BYTE* pData,UINT& uLen,DWORD dwMilliSecond)
{	
	clock_t		tStart,tEnd;
	UINT		uReceiveLen = uLen;
//	DWORD		dwResult = TRUE;

	tEnd = tStart = clock();
	while (((tEnd - tStart) * 1000 < dwMilliSecond*CLK_TCK) && (uReceiveLen > 0))
	{
		tEnd = clock();
		Sleep(100);

		Receive(pData,uReceiveLen);
		pData		+= uReceiveLen;
		uReceiveLen	 = uLen - uReceiveLen;
	}	
	return uReceiveLen == 0;
}
UINT CSerialPort::GetReceivedLenght()
{
	return (UINT)g_qReceive.size();
}
BOOL CSerialPort::Receive(BYTE* pData,UINT& uLen)
{	
	UINT	uRec(0);
	DWORD	dwResult = TRUE;

	while (!g_qReceive.empty() && uLen > uRec)
	{
		*pData++ = g_qReceive.front();
		g_qReceive.pop();
		uRec++;
	}
	dwResult	= (uLen == uRec);
	uLen		= uRec;
	return dwResult;
}

// thread of watch input port
DWORD WINAPI CSerialPort::WatchThreadProc(PVOID pParam)
{
	CSerialPort* pOwner = (CSerialPort*)pParam;
	BYTE*	pBuffer = new BYTE[1024];
	UINT	uLen = 1024;
	DWORD	dwEvtMask = EV_RXCHAR | EV_BREAK;

	SetCommMask(pOwner->m_hComm,dwEvtMask);
	while(TRUE == pOwner->IsOpen())
	{
//		SetCommMask(pOwner->m_hComm,dwEvtMask);
		WaitCommEvent(pOwner->m_hComm,&dwEvtMask,NULL);
		uLen = 1024;
		if (TRUE == pOwner->PortInput(pBuffer,uLen))
		{
			for (UINT i=0; i<uLen; i++)
			{
				g_qReceive.push(*(pBuffer+i));
			}
		}
	}
	pOwner->m_fOpen = FALSE;

	delete []pBuffer;
	return 0;
}

⌨️ 快捷键说明

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