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

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

(1)界面

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

(2)代码

①代码文件列表

通过继承和多态让串口相关的类可以随意替换,另外上面那个“串口管理委托"类,其实是参照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

时间: 2024-07-29 23:53:32

上位机简单串口类,VC串口类的相关文章

上位机用USB做虚拟串口,总算抓到一个纯代码的总结了,没有坑的完美解决。

用libUSB来实现自己的驱动+下位机理论速度.=1M字节每秒. 达到极限速度 WINDOWS已经自带虚拟串口驱动,只不过还需要一个Inf文件 方法1:直接下载一个串口inf,来修改文件. 方法2:用libUSB来实现自己的驱动...及应用.用那个工具安装成自己定义的设备名字,应用程序就根据PID,VID来找到我们的设备,进行一系列读写.   下位机: 1,配置描述符的编写,见工程代码注释.主要是CDC类接口用端点2,数据接口用端点1和端点3 2,Get_line_coding请求,获取串口属性

C#做一个简单的进行串口通信的上位机

C#做一个简单的进行串口通信的上位机 1.上位机与下位机 上位机相当于一个软件系统,可以用于接收数据.控制数据.即可以对接收到的数据直接发送操控命令来操作数据.上位机可以接收下位机的信号.下位机是一个控制器,是直接控制设备获取设备状况的计算机.上位机发出的命令首先给下位机,下位机再根据此命令解释成相应时序信号直接控制相应设备.下位机不时读取设备状态数据(一般为模拟量),转换成数字信号反馈给上位机.上位机不可以单独使用,而下位机可以单独使用. 2.串口通信 串口相当于硬件类型的接口.比如无线传感节

VC++编写简单串口上位机程序

转载: http://blog.sina.com.cn/s/articlelist_1809084904_0_1.html VC++编写简单串口上位机程序 串口通信,MCU跟PC通信经常用到的一种通信方式,做界面.写上位机程序的编程语言.编译环境等不少,VB.C#.LABVIEW等等,我会的语言很 少,C语言用得比较多,但是还没有找到如何用C语言来写串口通信上位机程序的资料,在图书管理找到了用VC++编写串口上位机的资料,参考书籍,用自己相 当蹩脚的C++写出了一个简单的串口上位机程序,分享一下

一个由印度人编写的VC串口类

软件介绍 一个由印度人编写的VC串口类(也是一种VC串口控件),他还配合这个类写了VC 串口通信方面的一些基础知识,如怎么用VC打开串口,如何对串口进行配置,读串口.写串口等. 这个类有点特别,它没有使用事件驱动原理,它是以查询方式工作的. 简介: 对没有接触过串口通信的VC程序员来说显得非常困难,很久以前我在 codeguru.com 上搜索过串口通信相关信息得到了非常大的帮助,从那时起能编写一个简单易用的VC 串口类是我的梦想. 经过七个月在串口通信编程方面实践经验后,我编写了一个基于API

一个印度人写的VC串口类CSerialCom(有串口基础介绍)

一个由印度人编写的VC串口类(也是一种VC串口控件),他还配合这个类写了VC 串口通信方面的一些基础知识,如怎么用VC打开串口,如何对串口进行配置,读串口.写串口等. 这个类有点特别,它没有使用事件驱动原理,它是以查询方式工作的. 简介: 对没有接触过串口通信的VC程序员来说显得非常困难,很久以前我在 codeguru.com 上搜索过串口通信相关信息得到了非常大的帮助,从那时起能编写一个简单易用的VC 串口类是我的梦想. 经过七个月在串口通信编程方面实践经验后,我编写了一个基于API实现的简单

(转)VC串口小程序(用SerialPort类)

××××××××××××××××××××××××××××××××××××××××××××××××××××× 在MFC里面实现串口通讯有很多方式: 方案一:使用微软公司提供的 串口类,SerialPort.这是官方的东西   有最大的灵活性和可靠性.  我的主攻选择为这个. 微软资源地址:https://msdn.microsoft.com/zh-cn/library/system.io.ports.serialport(v=vs.110).aspx?cs-save-lang=1&cs-lang=

2018最新mfc作为上位机接收硬件端USB或串口数据显示成图片 解决串口接收数据丢字节丢包问题

本文用的是VS2013MFC写串口数据接收: 第一步:首先建立一个MFC工程,成功后会跳出一个对话框,直接在对话框上点击右键->点击插入ACTIVAE控件->选择MicrosoftCommunications Control, version 6.0 成功后会显示一个电话的图标在对话框上,运行起来不会显示的 不用担心这个美观问题.如果没有这个插件的话,可能是版本太低  可以自己下载一个补上 第二步:大概的窗体搞好:   那个显示图片的大框是PICTURE控件变量 然后就要项目->类向导中

C#学习与上位机开发之串口通信模块介绍

串口通信模块(SerialPort) (1)模块简介 使用此模块需要首先包含一些文件IO相关文件 using System.IO;using System.IO.Ports; 图标如下图1所示,将其拖拽到面板.会显示在最下方,其参数有如下: BaudRate 波特率 DataBits 数据位 Parity 奇偶校验位 PortName 端口号 StopBits 停止位 ByteToRead 获取输入缓冲区的 IsOpen 获取是否开启串口         以上是我们做串口通信上位机需要用到的(如

LabVIEW上位机与串口通信

渊源 大一的时候,学校开了门公共选修课,叫LabVIEW编程,当时的我当然还不知道LabVIEW是啥东东,但还是选了.上课的老师是机械学院的一个副教授,他给我们展示了好几个用LabVIEW做的项目,譬如油箱监控上位机等,已经不太记得了.后来随着学习单片机.ARM等的串口操作,有时候一个漂亮的上位机(尤其是能显示波形的上位机)在项目中给用户展示非常的有用.过了这么多年,虽然曾经也用LabVIEW写过简单的温度监控上位机,但这次再拿起LabVIEW又好像从头开始一样,语法几已忘记殆尽! 定义通信格式