码迷,mamicode.com
首页 > 其他好文 > 详细

上位机简单串口类,VC串口类

时间:2014-04-29 13:24:20      阅读:418      评论:0      收藏:0      [点我收藏+]

标签:vc串口   串口类   串口   串口编程   

我是在一家做硬件的的公司里面做软件开发工程师的,我做的软件大多是是编写软件通过串口去控制硬件,所以串口编程对于我来说是很重要的。串口编程之前一直使用的是自己写的简单串口(只有发送,没有接收)类,或者上网下的CSerialPort类(个人觉得不好用啊,互锁变量一堆,代码一开始还让人看不懂,对于上位机使用不合适)。对于我做的上位机软件,其实使用串口只是需要顺序发送,接收数据无误就行了,不需要考虑太多东西。所以最近有点空,就自己再写了一个串口类(希望可以简单使用的,没有太高的要求的)。

(1)界面

mamicode.com,码迷

界面是粗糙了点,随便显示数据而已。

(2)代码

①代码文件列表

mamicode.com,码迷

通过继承和多态让串口相关的类可以随意替换,另外上面那个“串口管理委托"类,其实是参照Object-C的委托,觉得很好,自己也一直使用这种设计模式

②代码介绍

串口管理类:主要给主窗口调用,逻辑分层:主窗口-串口管理-串口类

#pragma once

#include "BaseComManage.h"

class CBaseCom;

class CComManage : public CBaseComManage
{
public:
	CComManage(void);
	~CComManage(void);

	//初始化
	virtual void Init();

	//获取串口状态
	virtual BOOL GetComState();

	//打开串口
	virtual BOOL OpenCom(CString szComName, CString szBaudRate, 
		CString szByteSize, CString szParity, CString szStopBits);

	//关闭串口
	virtual void CloseCom();

	//发送串口数据
	virtual BOOL SendData(const char* pData, const int nLen);

	//添加串口名称到ComboBox
	virtual void AddComNameToComboBox(CComboBox* pComBox);

	//添加波特率到ComboBox
	virtual void AddBaudRateToComboBox(CComboBox* pComBox);

	//添加数据位到ComboBox
	virtual void AddByteSizeToComboBox(CComboBox* pComBox);

	//添加停止位到ComboBox
	virtual void AddStopBitToComboBox(CComboBox* pComBox);

	//添加检验位到ComboBox
	virtual void AddParityToComboBox(CComboBox* pComBox);

private:

	//获取检验位
	BYTE GetParity(CString szData);

	//获取停止位
	BYTE GetStopBit(CString szData);

	//获取数据位
	BYTE GetByteSize(CString szData);

	//获取波特率
	DWORD GetBaudRate(CString szData);

	//获取串口名称
	CString GetComName(CString szComName);

private:

	//串口
	CBaseCom* m_pCom;
};
#include "StdAfx.h"
#include "ComManage.h"
#include "DelegateComManage.h"
#include "XCom.h"

CComManage::CComManage(void)
{
	m_pCom = nullptr;
}


CComManage::~CComManage(void)
{
	if (nullptr != m_pCom)
	{
		delete m_pCom;

		m_pCom = nullptr;
	}
}

/***********************************************************
** 功能描述: 初始化
************************************************************/
void CComManage::Init()
{
	m_pCom = new XCom;
}

/***********************************************************
** 功能描述: 获取串口状态
************************************************************/
BOOL CComManage::GetComState()
{
	return m_pCom->GetComState();
}

/***********************************************************
** 功能描述: 打开串口
************************************************************/
BOOL CComManage::OpenCom(CString szComName, CString szBaudRate, 
	CString szByteSize, CString szParity, CString szStopBits)
{
	return m_pCom->OpenCom(m_pDelegate->GetHWND(), GetComName(szComName), 
		GetBaudRate(szBaudRate), GetParity(szParity), GetByteSize(szByteSize), GetStopBit(szStopBits));
}

/***********************************************************
** 功能描述: 关闭串口
************************************************************/
void CComManage::CloseCom()
{
	m_pCom->CloseCom();
}

/***********************************************************
** 功能描述: 发送串口数据
************************************************************/
BOOL CComManage::SendData(const char* pData, const int nLen)
{
	return m_pCom->SendData(pData, nLen);
}

/***********************************************************
** 功能描述: 添加串口名称到ComboBox
************************************************************/
void CComManage::AddComNameToComboBox(CComboBox* pComBox)
{
	if (nullptr != pComBox)
	{
		pComBox->ResetContent();

		HKEY hKey;  

		//打开串口注册表
		LONG nResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Hardware\\DeviceMap\\SerialComm"), 
			NULL, KEY_READ, &hKey);

		if (ERROR_SUCCESS == nResult)     
		{
			DWORD dwPortName = MAX_PATH;
			DWORD dwComName = MAX_PATH;

			TCHAR cPortName[MAX_PATH];
			TCHAR cComName[MAX_PATH];  

			DWORD dwIndex = 0;

			CString szTemp = _T("");

			while(1)   
			{
				ZeroMemory(cPortName, MAX_PATH);
				ZeroMemory(cComName, MAX_PATH);

				dwPortName = MAX_PATH;
				dwComName = MAX_PATH;

				if (::RegEnumValue(hKey, dwIndex, cPortName, &dwPortName, NULL, NULL, (LPBYTE)cComName, 
					&dwComName) == ERROR_NO_MORE_ITEMS)
				{
					break;
				}

				szTemp.Format(_T("%s"), cComName);

				pComBox->AddString(cComName);

				dwIndex++;
			}

			RegCloseKey(hKey);
		}
	}
}

/***********************************************************
** 功能描述: 添加波特率到ComboBox
************************************************************/
void CComManage::AddBaudRateToComboBox(CComboBox* pComBox)
{
	if (nullptr != pComBox)
	{
		pComBox->ResetContent();

		pComBox->AddString(_T("2400"));
		pComBox->AddString(_T("4800"));
		pComBox->AddString(_T("9600"));
		pComBox->AddString(_T("14400"));
		pComBox->AddString(_T("19200"));
		pComBox->AddString(_T("38400"));
		pComBox->AddString(_T("57600"));
		pComBox->AddString(_T("115200"));
		pComBox->AddString(_T("128000"));
		pComBox->AddString(_T("256000"));
	}
}

/***********************************************************
** 功能描述: 添加数据位到ComboBox
************************************************************/
void CComManage::AddByteSizeToComboBox(CComboBox* pComBox)
{
	if (nullptr != pComBox)
	{
		pComBox->ResetContent();

		pComBox->AddString(_T("4"));
		pComBox->AddString(_T("5"));
		pComBox->AddString(_T("6"));
		pComBox->AddString(_T("7"));
		pComBox->AddString(_T("8"));
	}
}

/***********************************************************
** 功能描述: 添加停止位到ComboBox
************************************************************/
void CComManage::AddStopBitToComboBox(CComboBox* pComBox)
{
	if (nullptr != pComBox)
	{
		pComBox->ResetContent();

		pComBox->AddString(_T("1"));
		pComBox->AddString(_T("1.5"));
		pComBox->AddString(_T("2"));
	}
}

/***********************************************************
** 功能描述: 添加检验位到ComboBox
************************************************************/
void CComManage::AddParityToComboBox(CComboBox* pComBox)
{
	if (nullptr != pComBox)
	{
		pComBox->ResetContent();

		pComBox->AddString(_T("NO"));
		pComBox->AddString(_T("ODD"));
		pComBox->AddString(_T("EVEN"));
		pComBox->AddString(_T("MARK"));
	}
}

/***********************************************************
** 功能描述: 获取检验位
************************************************************/
BYTE CComManage::GetParity(CString szData)
{
	BYTE cData = 0;

	if (szData ==  _T("EVEN"))
	{
		cData = EVENPARITY;
	}
	else if (szData == _T("ODD"))
	{
		cData = ODDPARITY;
	}
	else if (szData == _T("NO"))
	{
		cData = NOPARITY;
	}
	else if (szData == _T("MARK"))
	{
		cData = MARKPARITY;
	}

	return cData;
}

/***********************************************************
** 功能描述: 获取停止位
************************************************************/
BYTE CComManage::GetStopBit(CString szData)
{
	BYTE cData = 0;

	if (szData ==  _T("1"))
	{
		cData = ONESTOPBIT;
	}
	else if (szData == _T("1.5"))
	{
		cData = ONE5STOPBITS;
	}
	else if (szData == _T("2"))
	{
		cData = TWOSTOPBITS;
	}
	
	return cData;
}

/***********************************************************
** 功能描述: 获取数据位
************************************************************/
BYTE CComManage::GetByteSize(CString szData)
{
	return (BYTE)_ttoi(szData);
}

/***********************************************************
** 功能描述: 获取波特率
************************************************************/
DWORD CComManage::GetBaudRate(CString szData)
{
	return (DWORD)_ttoi(szData);
}

/***********************************************************
** 功能描述: 获取串口名称
************************************************************/
CString CComManage::GetComName(CString szComName)
{
	return _T("\\\\.\\") + szComName;
}

串口类:

#pragma once

#include "BaseCom.h"

class XCom : public CBaseCom
{
public:
	XCom(void);
	~XCom(void);

	//打开串口
	virtual BOOL OpenCom(HWND pPortOwner, CString szComName, 
		DWORD nBaudRate, BYTE cParity, BYTE nByteSize, BYTE cStopsBits);

	//获取串口状态
	virtual BOOL GetComState();

	//关闭串口
	virtual void CloseCom();

	//发送串口数据
	virtual BOOL SendData(const char* pData, const int nLen);
	
public:

	//串口线程函数
	static UINT ComThread(LPVOID pParam);

	//接收字符
	BOOL ReceiveChar(DWORD dwLen);

private:

	//打开串口
	BOOL OpenCom(CString szComName);

	//设置DCB
	BOOL SetDCB(DWORD nBaudRate, BYTE cParity, BYTE nByteSize, 
		BYTE cStopsBits);

	//开始监控
	void StartMonitoring();

	//停止监控
	void StopMonitoring();

public:

	//串口句柄
	HANDLE m_hComm;

	//线程结束事件句柄
	HANDLE m_hThreadEndEvent; 

	//窗口句柄
	HWND m_Owner;

private:

	//串口状态
	BOOL m_bComSate;

	//串口DCB
	DCB	m_dcb;
};

#include "StdAfx.h"
#include "XCom.h"
#include "Constant.h"

XCom::XCom(void)
{
	m_bComSate = FALSE;

	m_Owner = NULL;

	m_hComm = INVALID_HANDLE_VALUE;

	m_hThreadEndEvent = NULL;
}


XCom::~XCom(void)
{
	CloseCom();
}

/***********************************************************
** 功能描述: 打开串口
************************************************************/
BOOL XCom::OpenCom(HWND pPortOwner, CString szComName, 
	DWORD nBaudRate, BYTE cParity, BYTE nByteSize, BYTE cStopsBits)
{
	if (OpenCom(szComName))
	{
		if (SetDCB(nBaudRate, cParity, nByteSize, cStopsBits))
		{
			if (SetCommMask(m_hComm, EV_RXCHAR))
			{
				if(PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR 
					| PURGE_RXABORT | PURGE_TXABORT))
				{
					StartMonitoring();

					m_Owner = pPortOwner;

					m_bComSate  = TRUE;
				}
			}
		}
	}

	if (!m_bComSate)
	{
		CloseCom();
	}

	return m_bComSate;
}

/***********************************************************
** 功能描述: 设置DCB
************************************************************/
BOOL XCom::SetDCB(DWORD nBaudRate, BYTE cParity, BYTE nByteSize, 
	BYTE cStopsBits)
{
	if (!GetCommState(m_hComm, &m_dcb))
	{
		return FALSE;
	}

	m_dcb.BaudRate = nBaudRate; 
	m_dcb.Parity   = cParity;
	m_dcb.ByteSize = nByteSize;
	m_dcb.StopBits = cStopsBits;

	return SetCommState(m_hComm, &m_dcb);
}

/***********************************************************
** 功能描述: 获取串口状态
************************************************************/
BOOL XCom::GetComState()
{
	return m_bComSate;
}

/***********************************************************
** 功能描述: 关闭串口
************************************************************/
void XCom::CloseCom()
{
	m_bComSate  = FALSE;

	if (INVALID_HANDLE_VALUE != m_hComm)
	{
		CloseHandle(m_hComm);

		m_hComm = INVALID_HANDLE_VALUE;
	}

	StopMonitoring();
}

/***********************************************************
** 功能描述: 打开串口
************************************************************/
BOOL XCom::OpenCom(CString szComName)
{
	m_hComm = CreateFile(szComName, GENERIC_READ | GENERIC_WRITE, 0, NULL,							
		OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, 0);								

	if (INVALID_HANDLE_VALUE == m_hComm)
	{
		return FALSE;
	}
	else
	{
		return TRUE;
	}
}

/***********************************************************
** 功能描述: 开始监控
************************************************************/
void XCom::StartMonitoring()
{
	m_hThreadEndEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

	AfxBeginThread(ComThread, this);
}

/***********************************************************
** 功能描述: 停止监控
************************************************************/
void XCom::StopMonitoring()
{
	if (NULL != m_hThreadEndEvent)
	{
		WaitForSingleObject(m_hThreadEndEvent, INFINITE);

		CloseHandle(m_hThreadEndEvent); 

		m_hThreadEndEvent = NULL;
	}
}

/***********************************************************
** 功能描述: 发送串口数据
************************************************************/
BOOL XCom::SendData(const char* pData, const int nLen)
{
	DWORD nNumberOfBytesWritten;

	OVERLAPPED overlapped = {0};

	BOOL bResultWrite = WriteFile(m_hComm, pData, nLen, &nNumberOfBytesWritten, &overlapped);

	BOOL bResult = FALSE;

	if (bResultWrite)
	{
		bResult = TRUE;
	}
	else
	{
		DWORD dwError = GetLastError();

		if (ERROR_IO_PENDING == dwError)
		{
			bResultWrite = GetOverlappedResult(m_hComm, &overlapped, &nNumberOfBytesWritten, TRUE); 

			if (bResultWrite)
			{
				bResult = TRUE;
			}
		}
	}

	return bResult;
}

/***********************************************************
** 功能描述: 接收字符
************************************************************/
BOOL XCom::ReceiveChar(DWORD dwLen)
{
	DWORD BytesRead = 0;

	unsigned char* pData = new unsigned char[dwLen];

	OVERLAPPED overlapped = {0};

	BOOL bReadResult = ReadFile(m_hComm, pData, dwLen, &BytesRead, &overlapped);

	BOOL bResult = FALSE;

	if (bReadResult)
	{
		bResult = TRUE;
	}
	else
	{
		DWORD dwError = GetLastError();

		if (ERROR_IO_PENDING == dwError)
		{
			bReadResult = GetOverlappedResult(m_hComm, &overlapped, &BytesRead, TRUE); 

			if (bReadResult)
			{
				bResult = TRUE;
			}
		}
	}

	if (bResult)
	{
		::PostMessage(m_Owner, MSG_COM_RECEIVEDATA, (WPARAM)pData, BytesRead);
	}

	return bResult;
}

/***********************************************************
** 功能描述: 串口线程函数
************************************************************/
UINT XCom::ComThread(LPVOID pParam)
{
	TRACE("XCOM ComThread:Start\n");

	XCom *pCom = (XCom*)pParam;

	DWORD dwEvtMask = 0;

	BOOL bResult = TRUE;

	DWORD dwError = 0;

	COMSTAT comstat;

	BOOL bRunning = TRUE;

	while (bRunning) 
	{ 
		bResult = WaitCommEvent(pCom->m_hComm, &dwEvtMask, NULL);

		if (!bResult)  
		{
			DWORD dwError = GetLastError();

			switch (dwError) 
			{ 
			case ERROR_IO_PENDING: 	
				{ 
					break;
				}
			case 87:
				{
					break;
				}
			default:
				{
					TRACE("XCOM ComThread WaitCommEvent:Error\n");

					::PostMessage(pCom->m_Owner, MSG_COM_ERROR, NULL, NULL);

					bRunning = FALSE;

					break;
				}
			}
		} 
		else
		{
			bResult = ClearCommError(pCom->m_hComm, &dwError, &comstat);

			if (0 == comstat.cbInQue)
			{
				continue;
			}

			pCom->ReceiveChar(comstat.cbInQue);
		}
	}

	SetEvent(pCom->m_hThreadEndEvent);

	TRACE("XCOM ComThread:End\n");

	return 0;
}

串口是用异步模式创建的,但使用是拿来当同步使用,是不是有大材小用,傻X是不,其实本是是想写成异步的,便同步比较好做,简单,就搞成四不像吧,方便进化成彻底异步模式。串品有数据到来时是用new一个char数组进行保存,然后发消息到主窗口,所以分配和释放内存这么多次不知道好不好,但如果只用一个共用的char数组进行保存时,就要使用互斥变量,处理慢。

(3)感想

我知道写得并不是很好,但足够我自己用了,试过没有问题,所以放上来给大家看看,供参考.


源码地址:http://pan.baidu.com/share/link?shareid=3711001912&uk=2852477476


上位机简单串口类,VC串口类

标签:vc串口   串口类   串口   串口编程   

原文地址:http://blog.csdn.net/cvbtvbwu/article/details/24694739

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!