Com串口操作

直接上代码


头文件:

#pragma once

#include "Common.h"

class CSerialPort
{
public:
	CSerialPort(LPVOID lpUserData, FPUserMessageProc fpSendProc, FPUserMessageProc fpReceiveProc);
	~CSerialPort(void);
public:
	BOOL InitPort(DWORD nPort, DWORD nBandRate);
	int UninitPort();
	int SendData(LPBYTE lpBuffer, DWORD dwSize);
private:
	static DWORD WINAPI OnSendDataProc(LPVOID lpParameter);
	static DWORD WINAPI OnReceiveDataProc(LPVOID lpParameter);
	DWORD DoSendDataProc();
	DWORD DoReceiveDataProc();
	void DoRecvDataMessage(UINT uMsg, WPARAM wParam, LPARAM lpParam);
	void DoSendDataMessage(UINT uMsg, WPARAM wParam, LPARAM lpParam);
private:
	BOOL m_bExitThread;
	DWORD m_nSendSize;
	DWORD m_nReceiveSize;
	BYTE m_SendBuffer[MAX_BUFFER_SIZE];
	BYTE m_ReceiveBuffer[MAX_BUFFER_SIZE];

	LPVOID m_lpUserData;
	FPUserMessageProc m_fpSendDataProc;
	FPUserMessageProc m_fpReceiveDataProc;

	HANDLE m_hSerialPort;
	HANDLE m_hExitThread;
	HANDLE m_hSendDataEvent;
	HANDLE m_hSendDataThread;
	HANDLE m_hReceiveDataThread;
};

.cpp文件

#include "StdAfx.h"
#include "SerialPort.h"

#define MAX_COMDATALEN		2048

CSerialPort::CSerialPort(LPVOID lpUserData, FPUserMessageProc fpSendProc, FPUserMessageProc fpReceiveProc)
{
	m_bExitThread = FALSE;
	m_nSendSize = 0;
	m_nReceiveSize = 0;
	
	m_lpUserData = lpUserData;
	m_fpSendDataProc = fpSendProc;
	m_fpReceiveDataProc = fpReceiveProc;

	m_hSerialPort = INVALID_HANDLE_VALUE;
	m_hSendDataEvent = NULL;
	m_hSendDataThread = NULL;
	m_hReceiveDataThread = NULL;
}

CSerialPort::~CSerialPort(void)
{
	UninitPort();
}

int CSerialPort::UninitPort()
{
	m_bExitThread = TRUE;
	if (m_hSendDataThread)
	{
		SetEvent(m_hSendDataEvent);
		WaitForSingleObject(m_hSendDataThread, INFINITE);
		SAFE_DELETE_HANDLE(m_hSendDataEvent);
		SAFE_DELETE_HANDLE(m_hSendDataThread);
	}

	if (m_hReceiveDataThread)
	{
		SetCommMask(m_hSerialPort, INFINITE);
		WaitForSingleObject(m_hReceiveDataThread, 500);
		SAFE_DELETE_HANDLE(m_hReceiveDataThread);
	}

	if (m_hSerialPort != INVALID_HANDLE_VALUE)
	{
		CloseHandle(m_hSerialPort);
		m_hSerialPort = INVALID_HANDLE_VALUE;
	}

	m_bExitThread = FALSE;
	return 0;
}

int CSerialPort::InitPort(DWORD nPort, DWORD nBandRate)
{
	UninitPort();
	
	do 
	{
		DCB dcb;
		COMMTIMEOUTS cto;

		TCHAR szPortName[32] = {0};
		_stprintf(szPortName, _T("COM%d:"), nPort);
		m_hSerialPort = ::CreateFile(szPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
		if (m_hSerialPort == INVALID_HANDLE_VALUE)		break;

		::GetCommState(m_hSerialPort, &dcb);
		dcb.BaudRate = nBandRate;
		dcb.fParity = FALSE;
		dcb.fNull = FALSE;
		dcb.StopBits = ONESTOPBIT;
		dcb.Parity = NOPARITY;
		dcb.ByteSize = 8;
		::SetCommState(m_hSerialPort, &dcb);

		cto.ReadIntervalTimeout = 0;
		cto.ReadTotalTimeoutMultiplier = 0;
		cto.ReadTotalTimeoutConstant = 0;
		cto.WriteTotalTimeoutMultiplier = 0;
		cto.WriteTotalTimeoutConstant = 0;
		SetCommTimeouts(m_hSerialPort, &cto);

		DWORD dwThreadID = 0;
		m_hSendDataThread = ::CreateThread(NULL, 0, OnSendDataProc, this, CREATE_SUSPENDED, &dwThreadID);
		if (m_hSendDataThread == NULL)		break;

		m_hReceiveDataThread= ::CreateThread(NULL, 0, OnReceiveDataProc, this, CREATE_SUSPENDED, &dwThreadID);
		if (m_hReceiveDataThread == NULL)		break;

		m_hSendDataEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
		if (m_hSendDataEvent == NULL)		break;

		SetCommMask(m_hSerialPort, EV_RXCHAR | EV_ERR);
		//SetupComm(m_hSerialPort, MAX_COMDATALEN, MAX_COMDATALEN);
		PurgeComm(m_hSerialPort, PURGE_RXCLEAR | PURGE_TXCLEAR);
		ResumeThread(m_hSendDataThread);
		ResumeThread(m_hReceiveDataThread);
		return TRUE;
	} while (FALSE);

	if (m_hSendDataThread)		ResumeThread(m_hSendDataThread);
	if (m_hReceiveDataThread)	ResumeThread(m_hReceiveDataThread);
	return FALSE;
}

int CSerialPort::SendData(LPBYTE lpBuffer, DWORD dwSize)
{
	if (lpBuffer == NULL || dwSize == 0)	return -1;

	if (m_hSendDataEvent)
	{
		sprintf((char*)m_SendBuffer, (char*)lpBuffer, dwSize);
		m_nSendSize = dwSize;
		PurgeComm(m_hSerialPort, PURGE_RXCLEAR | PURGE_TXCLEAR);
		SetEvent(m_hSendDataEvent);
	}
	
	return 0;
}

DWORD WINAPI CSerialPort::OnSendDataProc(LPVOID lpParameter)
{
	CSerialPort* pThis = static_cast<CSerialPort*>(lpParameter);
	if (pThis)	pThis->DoSendDataProc();
	return 0;
}

DWORD WINAPI CSerialPort::OnReceiveDataProc(LPVOID lpParameter)
{
	CSerialPort* pThis = static_cast<CSerialPort*>(lpParameter);
	if (pThis)	pThis->DoReceiveDataProc();
	return 0;
}

DWORD CSerialPort::DoSendDataProc()
{
	DebugString(m_hSendDataEvent, _T("Thread %08x (SendData): Starting\n"), m_hSendDataEvent);
	DWORD nSendSize = 0;
	while (! m_bExitThread)
	{
		if (m_hSendDataEvent ==  NULL)		break;
		WaitForSingleObject(m_hSendDataEvent, INFINITE);	
		ResetEvent(m_hSendDataEvent);

		if (m_bExitThread)		break;
		WriteFile(m_hSerialPort, m_SendBuffer, m_nSendSize, &nSendSize, NULL);
		
		if (nSendSize == m_nSendSize)
			DoSendDataMessage(E_SEND_DATA_OK, 0, 0);
		else	
			DoSendDataMessage(E_SEND_DATA_ERROR, 0, 0);
	}
	DebugString(m_hSendDataEvent, _T("Thread %08x (SendData): Exiting \n"), m_hSendDataEvent);
	return 0;
}

DWORD CSerialPort::DoReceiveDataProc()
{
	DebugString(m_hReceiveDataThread, _T("Thread %08x (ReceiveData): Starting\n"), m_hReceiveDataThread);
	COMSTAT stat;
	DWORD dwError = 0;
	DWORD dwMask = 0;
	
	while (! m_bExitThread)
	{
		if (m_hSerialPort == INVALID_HANDLE_VALUE)		break;

		SetCommMask(m_hSerialPort, EV_RXCHAR | EV_ERR);
		if (WaitCommEvent(m_hSerialPort, &dwMask, NULL))
		{
			if (m_bExitThread)		break;
			ClearCommError(m_hSerialPort, &dwError, &stat);
			switch (dwMask & 0xff)
			{
			case EV_RXCHAR:
				ReadFile(m_hSerialPort, m_ReceiveBuffer, stat.cbInQue, &m_nReceiveSize, NULL);

				if (m_nReceiveSize == stat.cbInQue)
					DoRecvDataMessage(E_RECV_DATA_OK, (WPARAM)m_ReceiveBuffer, (LPARAM)m_nReceiveSize);
				else
					DoRecvDataMessage(E_RECV_DATA_ERROR, (WPARAM)0, (LPARAM)0);
				break;
			case EV_ERR:
				DoRecvDataMessage(E_RECV_DATA_ERROR, (WPARAM)0, (LPARAM)0);
				break;
			case EV_BREAK:
				break;
			}
		}
	}
	DebugString(m_hReceiveDataThread, _T("Thread %08x (ReceiveData): Exiting \n"), m_hReceiveDataThread);
	return 0;
}

void CSerialPort::DoRecvDataMessage(UINT uMsg, WPARAM wParam, LPARAM lpParam)
{
	if (m_fpReceiveDataProc)
	{
		m_fpReceiveDataProc(m_lpUserData, uMsg, wParam, lpParam);
	}
}

void CSerialPort::DoSendDataMessage(UINT uMsg, WPARAM wParam, LPARAM lpParam)
{
	if (m_fpSendDataProc)
	{
		m_fpSendDataProc(m_lpUserData, uMsg, wParam, lpParam);
	}
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值